diff --git a/bindings/consts.go b/bindings/consts.go index 5ba49c766..58f873a28 100644 --- a/bindings/consts.go +++ b/bindings/consts.go @@ -2,7 +2,7 @@ package bindings const CInt32Max = int(^uint32(0) >> 1) -const ReindexerVersion = "v3.28.2" +const ReindexerVersion = "v3.29.0" // public go consts from type_consts.h and reindexer_ctypes.h const ( diff --git a/changelog.md b/changelog.md index 0658da7d7..e5525167b 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,28 @@ +# Version 3.29.0 (08.10.2024) +## Core +- [fea] Added Chinese and Japanese symbols into locale. Currently those symbols will be indexed by fulltext engine (using space-separators), but proper tokenization for the languages will be added in the separate release +- [fea] Added [debug_rank() function](fulltext.md#debug_rank) for fulltext-indexes (it allows to get some more ranking details in the resulting docs) +- [fix] Fixed crash in fulltext index data deletion after `incorrect encoding` error handling +- [fix] Fixed LSN setting for deleted items +- [fix] Fixed large `int64` convertion in SQL queries + +## Replication +- [fix] Fixed possible datahash missmatch after WAL-sync in cascade replication setups +- [fix] Fixed storage rollback from v4 with non-default `server ID` values + +## Reindexer server +- [fix] Fixed GRPC queries responses in [Protobuf format](cpp_src/readme.md#protobuf) + +## Go connector +- [fea] Added ["equal_positions" filters](readme.md#search-in-array-fields-with-matching-array-indexes) support into [Go DSL](dsl/dsl.go) +- [fix] Fixed interaction between `query.Get()` and joined-queries. Now `Get()` correctly applies `limit` to the main query + +## Build +- [fix] Fixed `AltLinux` `gperftools` [dependency](dependencies.sh) name + +## Face +- [fix] Fixed NS config changes saving after tabs switch + # Version 3.28.2 (19.09.2024) ## Core - [fix] Fixed data race in cached comparators (`joins cache` may cause incorrect comparators deletion) diff --git a/cpp_src/CMakeLists.txt b/cpp_src/CMakeLists.txt index 8b287338f..7215726d9 100644 --- a/cpp_src/CMakeLists.txt +++ b/cpp_src/CMakeLists.txt @@ -44,7 +44,7 @@ else() option(LINK_RESOURCES "Link web resources as binary data" ON) endif() -set(REINDEXER_VERSION_DEFAULT "3.28.2") +set(REINDEXER_VERSION_DEFAULT "3.29.0") if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "RelWithDebInfo") @@ -87,7 +87,7 @@ endif() if(MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -wd4244 -wd4267 -wd4996 -wd4717 -MP -MD") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4244 -wd4267 -wd4996 -wd4717 -wd4800 -wd4396 -wd4503 -MP -MD") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4244 -wd4267 -wd4996 -wd4717 -wd4800 -wd4396 -wd4503 -MP -MD /bigobj") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -SAFESEH:NO") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -Wswitch-enum") @@ -619,8 +619,3 @@ add_custom_target(collect_coverage COMMAND genhtml coverage_filtered.info -o coverage_output COMMENT "Collecting Reindexer coverage" ) - -# Configure compile options extra -if(MSVC) - target_compile_options(${TARGET} PRIVATE /bigobj) -endif() diff --git a/cpp_src/cmd/reindexer_tool/commandsexecutor.cc b/cpp_src/cmd/reindexer_tool/commandsexecutor.cc index 085741e3c..254242b65 100644 --- a/cpp_src/cmd/reindexer_tool/commandsexecutor.cc +++ b/cpp_src/cmd/reindexer_tool/commandsexecutor.cc @@ -25,7 +25,6 @@ const std::string kVariableOutput = "output"; const std::string kOutputModeJson = "json"; const std::string kOutputModeTable = "table"; const std::string kOutputModePretty = "pretty"; -const std::string kOutputModePrettyCollapsed = "collapsed"; const std::string kBenchNamespace = "rxtool_bench"; const std::string kBenchIndex = "id"; @@ -157,7 +156,10 @@ Error CommandsExecutor::fromFileImpl(std::istream& in) { while (GetStatus().running && std::getline(in, line.str)) { if (reindexer::checkIfStartsWith("\\upsert ", line.str) || reindexer::checkIfStartsWith("\\delete ", line.str)) { try { - cmdCh.push(line); + LineData l; + l.lineNum = line.lineNum; + reindexer::deepCopy(l.str, line.str); + cmdCh.push(std::move(l)); } catch (std::exception&) { break; } @@ -506,7 +508,7 @@ Error CommandsExecutor::processImpl(const std::string& command) noe } catch (std::exception& e) { return Error(errLogic, "std::exception during command's execution: %s", e.what()); } catch (...) { - return Error(errLogic, "Unknow exception during command's execution"); + return Error(errLogic, "Unknown exception during command's execution"); } } return Error(errParams, "Unknown command '%s'. Type '\\help' to list of available commands", token); @@ -683,7 +685,7 @@ Error CommandsExecutor::commandUpsert(const std::string& command) { status = db().Upsert(nsName, item); if (!fromFile_ && status.ok()) { - output_() << "Upserted successfuly: 1 items" << std::endl; + output_() << "Upserted successfully: 1 items" << std::endl; } return status; } @@ -809,7 +811,7 @@ Error CommandsExecutor::commandDump(const std::string& command) { } for (auto it : itemResults) { - if (auto err = it.Status(); !err.ok()) { + if (err = it.Status(); !err.ok()) { return err; } if (cancelCtx_.IsCancelled()) { @@ -1103,7 +1105,7 @@ Error CommandsExecutor::commandProcessDatabase err = db().Status(); } if (err.ok()) { - output_() << "Succesfully connected to " << currentDsn << std::endl; + output_() << "Successfully connected to " << currentDsn << std::endl; } return err; } else if (subCommand == "create"sv) { @@ -1119,7 +1121,7 @@ Error CommandsExecutor::commandProcessDatabase std::vector dbNames; err = db().EnumDatabases(dbNames); if (std::find(dbNames.begin(), dbNames.end(), std::string(dbName)) != dbNames.end()) { - output_() << "Succesfully created database '" << dbName << "'" << std::endl; + output_() << "Successfully created database '" << dbName << "'" << std::endl; } else { std::cerr << "Error on database '" << dbName << "' creation" << std::endl; } diff --git a/cpp_src/core/cjson/baseencoder.cc b/cpp_src/core/cjson/baseencoder.cc index 992a268a6..b3950919d 100644 --- a/cpp_src/core/cjson/baseencoder.cc +++ b/cpp_src/core/cjson/baseencoder.cc @@ -1,6 +1,5 @@ #include "baseencoder.h" #include -#include #include "cjsonbuilder.h" #include "cjsontools.h" #include "core/keyvalue/p_string.h" @@ -42,7 +41,7 @@ void BaseEncoder::Encode(ConstPayload& pl, Builder& builder, IAdditiona } objectScalarIndexes_.reset(); - std::fill_n(std::begin(fieldsoutcnt_), pl.NumFields(), 0); + std::fill(fieldsoutcnt_.begin(), fieldsoutcnt_.end(), 0); builder.SetTagsMatcher(tagsMatcher_); if constexpr (kWithTagsPathTracking) { builder.SetTagsPath(&curTagsPath_); @@ -167,11 +166,11 @@ bool BaseEncoder::encode(ConstPayload* pl, Serializer& rdser, Builder& [&](KeyValueType::String) { builder.Array(tagName, pl->GetArray(tagField).subspan(cnt, count), cnt); }, [&](KeyValueType::Uuid) { builder.Array(tagName, pl->GetArray(tagField).subspan(cnt, count), cnt); }, [](OneOf) noexcept { - assertrx(0); + assertrx(false); abort(); }); } - cnt += count; + cnt += int(count); break; } case TAG_NULL: diff --git a/cpp_src/core/cjson/baseencoder.h b/cpp_src/core/cjson/baseencoder.h index 9eafa4808..bb1cd818d 100644 --- a/cpp_src/core/cjson/baseencoder.h +++ b/cpp_src/core/cjson/baseencoder.h @@ -10,7 +10,6 @@ namespace reindexer { class TagsMatcher; -class JsonBuilder; class MsgPackBuilder; class ProtobufBuilder; class CsvBuilder; @@ -38,7 +37,7 @@ class IAdditionalDatasource { template class BaseEncoder { public: - BaseEncoder(const TagsMatcher* tagsMatcher, const FieldsSet* filter = nullptr); + explicit BaseEncoder(const TagsMatcher* tagsMatcher, const FieldsSet* filter = nullptr); void Encode(ConstPayload& pl, Builder& builder, IAdditionalDatasource* = nullptr); void Encode(std::string_view tuple, Builder& wrSer, IAdditionalDatasource*); @@ -61,9 +60,9 @@ class BaseEncoder { std::string_view getPlTuple(ConstPayload& pl); - const TagsMatcher* tagsMatcher_; - std::array fieldsoutcnt_{0}; - const FieldsSet* filter_; + const TagsMatcher* tagsMatcher_{nullptr}; + std::array fieldsoutcnt_; + const FieldsSet* filter_{nullptr}; WrSerializer tmpPlTuple_; TagsPath curTagsPath_; IndexedTagsPathInternalT indexedTagsPath_; diff --git a/cpp_src/core/cjson/cjsondecoder.cc b/cpp_src/core/cjson/cjsondecoder.cc index 26c7d8549..3064f14e8 100644 --- a/cpp_src/core/cjson/cjsondecoder.cc +++ b/cpp_src/core/cjson/cjsondecoder.cc @@ -11,7 +11,6 @@ bool CJsonDecoder::decodeCJson(Payload& pl, Serializer& rdser, WrSerializer& wrs const ctag tag = rdser.GetCTag(); TagType tagType = tag.Type(); if (tagType == TAG_END) { - recoder.Serialize(wrser); wrser.PutCTag(kCTagEnd); return false; } diff --git a/cpp_src/core/cjson/cjsondecoder.h b/cpp_src/core/cjson/cjsondecoder.h index 443fea4c7..747c2fd7e 100644 --- a/cpp_src/core/cjson/cjsondecoder.h +++ b/cpp_src/core/cjson/cjsondecoder.h @@ -17,10 +17,8 @@ class Recoder { [[nodiscard]] virtual TagType Type(TagType oldTagType) = 0; virtual void Recode(Serializer&, WrSerializer&) const = 0; virtual void Recode(Serializer&, Payload&, int tagName, WrSerializer&) = 0; - [[nodiscard]] virtual bool Match(int field) noexcept = 0; - [[nodiscard]] virtual bool Match(TagType, const TagsPath&) = 0; - virtual void Serialize(WrSerializer& wrser) = 0; - virtual bool Reset() = 0; + [[nodiscard]] virtual bool Match(int field) const noexcept = 0; + [[nodiscard]] virtual bool Match(const TagsPath&) const = 0; virtual ~Recoder() = default; }; @@ -49,7 +47,7 @@ class CJsonDecoder { class IndexedSkipFilter { public: - IndexedSkipFilter(const FieldsSet& f) noexcept : f_(&f) {} + explicit IndexedSkipFilter(const FieldsSet& f) noexcept : f_(&f) {} IndexedSkipFilter MakeCleanCopy() const noexcept { return IndexedSkipFilter(*f_); } IndexedSkipFilter MakeSkipFilter() const noexcept { return IndexedSkipFilter(*f_); } @@ -57,7 +55,7 @@ class CJsonDecoder { RX_ALWAYS_INLINE bool match(const TagsPath&) const noexcept { return false; } private: - const FieldsSet* f_; + const FieldsSet* f_{nullptr}; }; class RestrictingFilter { @@ -85,8 +83,8 @@ class CJsonDecoder { } private: - const FieldsSet* f_; - bool match_; + const FieldsSet* f_{nullptr}; + bool match_{false}; }; class DummyRecoder { @@ -96,7 +94,6 @@ class CJsonDecoder { RX_ALWAYS_INLINE bool Recode(Serializer&, Payload&, int, WrSerializer&) const noexcept { return false; } RX_ALWAYS_INLINE TagType RegisterTagType(TagType tagType, int) const noexcept { return tagType; } RX_ALWAYS_INLINE TagType RegisterTagType(TagType tagType, const TagsPath&) const noexcept { return tagType; } - RX_ALWAYS_INLINE void Serialize(WrSerializer&) const {} }; class DefaultRecoder { public: @@ -121,14 +118,13 @@ class CJsonDecoder { return needToRecode_ ? r_->Type(tagType) : tagType; } RX_ALWAYS_INLINE TagType RegisterTagType(TagType tagType, const TagsPath& tagsPath) { - needToRecode_ = r_->Match(tagType, tagsPath); + needToRecode_ = r_->Match(tagsPath); return needToRecode_ ? r_->Type(tagType) : tagType; } - RX_ALWAYS_INLINE void Serialize(WrSerializer& wser) const { r_->Serialize(wser); } private: - Recoder* r_; - bool needToRecode_; + Recoder* r_{nullptr}; + bool needToRecode_{false}; }; struct NamedTagOpt {}; struct NamelessTagOpt {}; @@ -166,7 +162,7 @@ class CJsonDecoder { TagsMatcher& tagsMatcher_; TagsPath tagsPath_; - int32_t arrayLevel_ = 0; + int32_t arrayLevel_{0}; ScalarIndexesSetT objectScalarIndexes_; // storage for owning strings obtained from numbers std::deque& storage_; diff --git a/cpp_src/core/cjson/defaultvaluecoder.cc b/cpp_src/core/cjson/defaultvaluecoder.cc deleted file mode 100644 index d33713150..000000000 --- a/cpp_src/core/cjson/defaultvaluecoder.cc +++ /dev/null @@ -1,171 +0,0 @@ -#include "defaultvaluecoder.h" - -namespace reindexer { - -DefaultValueCoder::DefaultValueCoder(std::string_view ns, const PayloadFieldType& fld, std::vector&& tps, int16_t fieldIdx) - : ns_(ns), - field_(fld.Name()), - tags_(std::move(tps)), - fieldIdx_(fieldIdx), - type_(fld.Type().ToTagType()), - array_(fld.IsArray()), - basePath_(&tags_.front()) {} - -bool DefaultValueCoder::Match(int field) noexcept { - // non-nested field present in tuple - if ((field == fieldIdx_) && ready()) { - state_ = State::found; - } - return false; // returned result is always same -} - -bool DefaultValueCoder::Match(TagType tt, const TagsPath& tp) { - static const bool result = false; // returned result is always same - - // nothing to look for (start tuple global object) - if (tp.empty()) { - state_ = State::wait; - // inArray_ = false; - // arrField_ = 0; - return result; - } - - // found\recorded earlier - if ((state_ == State::found) || ((state_ == State::write) /* && !inArray_*/)) { - return result; - } - - // check if active array has been processed - const bool arrayTag = (tt == TAG_ARRAY); - // if (inArray_) { - // inArray_ = ((tt == TAG_OBJECT) || arrayTag) ? (tp.back() == arrField_) : (tp[tp.size() - 2] == arrField_); // -2 pre-last item - // // recorded earlier - stop it - // if (!inArray_ && (state_ == State::write)) { - // return result; - // } - // } - - // try match nested field - if (tt == TAG_OBJECT) { - assertrx(state_ != State::found); - match(tp); - return result; - } - - // may be end element of adjacent nested field - if (arrayTag) { - if (tp.size() <= basePath_->size() && std::equal(tp.begin(), tp.end(), basePath_->begin())) { - // Do not create anything inside objects arrays #1819 - state_ = State::found; - return result; - } - // inArray_ = (tp.front() == basePath_->front()); - // arrField_ = tp.back(); - } - - // not nested - if (copyPos_ == 0) { - return result; - } - - // detect array insertion into array (not supported) - if (arrayTag && array_) { - state_ = State::found; // do nothing - } else if ((tp.front() == basePath_->front()) && (tp.size() > basePath_->size())) { - ++nestingLevel_; - } - - return result; -} - -void DefaultValueCoder::Serialize(WrSerializer& wrser) { - if (blocked()) { - return; // skip processing - } - - // skip nested levels - if ((basePath_->size() > 1) || (nestingLevel_ > 1)) { - assertrx(nestingLevel_ > 0); - --nestingLevel_; - - // new field - move to valid level - if (nestingLevel_ > copyPos_) { - return; - } - } - - const auto written = write(wrser); - Reset(); - state_ = written ? State::write : State::found; -} - -bool DefaultValueCoder::Reset() noexcept { - nestingLevel_ = 1; - copyPos_ = 0; - // NOTE: return true when updating tuple - return (state_ == State::write); -} - -void DefaultValueCoder::match(const TagsPath& tp) { - ++nestingLevel_; - - for (auto& path : tags_) { - if (path.front() != tp.front()) { - continue; - } - - copyPos_ = 1; - auto pathSize = path.size(); - auto sz = std::min(pathSize, tp.size()); - for (size_t idx = 1; idx < sz; ++idx) { - if (path[idx] != tp[idx]) { - break; - } - ++copyPos_; - - // we are trying to add field with non-nested paths, but an intersection was found in additional nested paths. - // Stop, throw an error - if (tags_.front().size() == 1) { - throw Error(errLogic, "Cannot add field with name '%s' to namespace '%s'. One of nested json paths is already in use", - field_, ns_); - } - } - state_ = State::match; - basePath_ = &path; - break; - } -} - -bool DefaultValueCoder::write(WrSerializer& wrser) const { - if (array_ && copyPos_ + 1 < basePath_->size()) { - // Do not create multiple levels for nested array indexes to avoid problems with decoding in Go/Java connectors. #1819 - return false; - } - int32_t nestedObjects = 0; - for (size_t idx = copyPos_, sz = basePath_->size(); idx < sz; ++idx) { - auto tagName = (*basePath_)[idx]; - // real index field in last tag - const bool finalTag = (idx == (sz - 1)); - if (finalTag) { - if (array_) { - wrser.PutCTag(ctag{TAG_ARRAY, tagName, fieldIdx_}); - wrser.PutVarUint(0); - } else { - wrser.PutCTag(ctag{type_, tagName, fieldIdx_}); - } - break; - } - - // start nested object - wrser.PutCTag(ctag{TAG_OBJECT, tagName}); - ++nestedObjects; - } - - // add end tags to all objects - while (nestedObjects-- > 0) { - wrser.PutCTag(kCTagEnd); - } - return true; -} - -} // namespace reindexer diff --git a/cpp_src/core/cjson/defaultvaluecoder.h b/cpp_src/core/cjson/defaultvaluecoder.h deleted file mode 100644 index 3f4276dc2..000000000 --- a/cpp_src/core/cjson/defaultvaluecoder.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "cjsondecoder.h" - -namespace reindexer { - -class DefaultValueCoder : public Recoder { -public: - DefaultValueCoder(std::string_view ns, const PayloadFieldType& fld, std::vector&& tps, int16_t fieldIdx); - RX_ALWAYS_INLINE TagType Type(TagType tt) noexcept override final { return tt; } - [[nodiscard]] bool Match(int f) noexcept override final; - [[nodiscard]] bool Match(TagType tt, const TagsPath& tp) override final; - RX_ALWAYS_INLINE void Recode(Serializer&, WrSerializer&) const noexcept override final { assertrx(false); } - RX_ALWAYS_INLINE void Recode(Serializer&, Payload&, int, WrSerializer&) noexcept override final { assertrx(false); } - void Serialize(WrSerializer& wrser) override final; - bool Reset() noexcept override final; - -private: - void match(const TagsPath& tp); - [[nodiscard]] bool write(WrSerializer& wrser) const; - [[nodiscard]] RX_ALWAYS_INLINE bool blocked() const noexcept { return ((state_ == State::found) || (state_ == State::write)); } - [[nodiscard]] RX_ALWAYS_INLINE bool ready() const noexcept { return ((state_ == State::wait) || (state_ == State::match)); } - -private: - const std::string ns_; - const std::string field_; - const std::vector tags_; - const int16_t fieldIdx_{0}; - const TagType type_; - const bool array_{false}; - - const TagsPath* basePath_{nullptr}; - enum class State { wait, found, match, write } state_{State::wait}; - uint32_t nestingLevel_{1}; - uint32_t copyPos_{0}; - - // bool inArray_{false}; - // int16_t arrField_{0}; -}; - -} // namespace reindexer diff --git a/cpp_src/core/cjson/jsondecoder.cc b/cpp_src/core/cjson/jsondecoder.cc index 85d3ac79d..7ee9a0e0e 100644 --- a/cpp_src/core/cjson/jsondecoder.cc +++ b/cpp_src/core/cjson/jsondecoder.cc @@ -115,13 +115,8 @@ void JsonDecoder::decodeJson(Payload* pl, CJsonBuilder& builder, const gason::Js builder.Null(tagName); break; case gason::JSON_ARRAY: { - ObjType type; CounterGuardIR32 g(arrayLevel_); - if (gason::isHomogeneousArray(v)) { - type = ObjType::TypeArray; - } else { - type = ObjType::TypeObjectArray; - } + ObjType type = (gason::isHomogeneousArray(v)) ? ObjType::TypeArray : ObjType::TypeObjectArray; auto arrNode = builder.Array(tagName, type); for (const auto& elem : v) { decodeJson(pl, arrNode, elem.value, 0, match); diff --git a/cpp_src/core/cjson/jsondecoder.h b/cpp_src/core/cjson/jsondecoder.h index 73dad50f2..066f6740a 100644 --- a/cpp_src/core/cjson/jsondecoder.h +++ b/cpp_src/core/cjson/jsondecoder.h @@ -8,8 +8,8 @@ namespace reindexer { class JsonDecoder { public: - explicit JsonDecoder(TagsMatcher& tagsMatcher) noexcept : tagsMatcher_(tagsMatcher), filter_(nullptr) {} - JsonDecoder(TagsMatcher& tagsMatcher, const FieldsSet* filter) noexcept : tagsMatcher_(tagsMatcher), filter_(filter) {} + explicit JsonDecoder(TagsMatcher& tagsMatcher, const FieldsSet* filter = nullptr) noexcept + : tagsMatcher_(tagsMatcher), filter_(filter) {} Error Decode(Payload& pl, WrSerializer& wrSer, const gason::JsonValue& v); void Decode(std::string_view json, CJsonBuilder& builder, const TagsPath& fieldPath); @@ -21,8 +21,8 @@ class JsonDecoder { TagsMatcher& tagsMatcher_; TagsPath tagsPath_; - const FieldsSet* filter_; - int32_t arrayLevel_ = 0; + const FieldsSet* filter_{nullptr}; + int32_t arrayLevel_{0}; ScalarIndexesSetT objectScalarIndexes_; }; diff --git a/cpp_src/core/cjson/msgpackdecoder.cc b/cpp_src/core/cjson/msgpackdecoder.cc index e08e55ab5..8b72c9f21 100644 --- a/cpp_src/core/cjson/msgpackdecoder.cc +++ b/cpp_src/core/cjson/msgpackdecoder.cc @@ -145,13 +145,13 @@ Error MsgPackDecoder::Decode(std::string_view buf, Payload& pl, WrSerializer& wr } catch (const Error& err) { return err; } catch (const std::exception& ex) { - return Error(errNotValid, "%s", ex.what()); + return {errNotValid, "%s", ex.what()}; } catch (...) { // all internal errors shall be handled and converted to Error - return Error(errNotValid, "Unexpected exception"); + return {errNotValid, "Unexpected exception"}; } - return Error(); + return {}; } constexpr std::string_view ToString(msgpack_object_type type) { diff --git a/cpp_src/core/cjson/protobufdecoder.cc b/cpp_src/core/cjson/protobufdecoder.cc index a8313ab01..7d2dcc04a 100644 --- a/cpp_src/core/cjson/protobufdecoder.cc +++ b/cpp_src/core/cjson/protobufdecoder.cc @@ -1,14 +1,13 @@ #include "protobufdecoder.h" #include "core/schema.h" #include "estl/protobufparser.h" -#include "protobufbuilder.h" namespace reindexer { void ArraysStorage::UpdateArraySize(int tagName, int field) { GetArray(tagName, field); } CJsonBuilder& ArraysStorage::GetArray(int tagName, int field) { - assertrx(indexes_.size() > 0); + assertrx(!indexes_.empty()); auto it = data_.find(tagName); if (it == data_.end()) { indexes_.back().emplace_back(tagName); @@ -25,7 +24,7 @@ CJsonBuilder& ArraysStorage::GetArray(int tagName, int field) { void ArraysStorage::onAddObject() { indexes_.emplace_back(h_vector()); } void ArraysStorage::onObjectBuilt(CJsonBuilder& parent) { - assertrx(indexes_.size() > 0); + assertrx(!indexes_.empty()); for (int tagName : indexes_.back()) { auto it = data_.find(tagName); assertrx(it != data_.end()); @@ -69,10 +68,10 @@ void ProtobufDecoder::setValue(Payload& pl, CJsonBuilder& builder, ProtobufValue Error ProtobufDecoder::decodeArray(Payload& pl, CJsonBuilder& builder, const ProtobufValue& item) { ProtobufObject object(item.As(), *schema_, tagsPath_, tm_); ProtobufParser parser(object); - bool packed = item.IsOfPrimitiveType(); - int field = tm_.tags2field(tagsPath_.data(), tagsPath_.size()); + const bool packed = item.IsOfPrimitiveType(); + const int field = tm_.tags2field(tagsPath_.data(), tagsPath_.size()); if (field > 0) { - auto& f = pl.Type().Field(field); + const auto& f = pl.Type().Field(field); if rx_unlikely (!f.IsArray()) { throw Error(errLogic, "Error parsing protobuf field '%s' - got array, expected scalar %s", f.Name(), f.Type().Name()); } @@ -104,7 +103,7 @@ Error ProtobufDecoder::decodeArray(Payload& pl, CJsonBuilder& builder, const Pro } } } - return Error(); + return {}; } Error ProtobufDecoder::decode(Payload& pl, CJsonBuilder& builder, const ProtobufValue& item) { diff --git a/cpp_src/core/cjson/uuid_recoders.h b/cpp_src/core/cjson/uuid_recoders.h index cdc264ac3..9bb51c701 100644 --- a/cpp_src/core/cjson/uuid_recoders.h +++ b/cpp_src/core/cjson/uuid_recoders.h @@ -19,10 +19,8 @@ class RecoderUuidToString : public Recoder { } void Recode(Serializer&, WrSerializer&) const override final; void Recode(Serializer&, Payload&, int, WrSerializer&) override final { assertrx(false); } - [[nodiscard]] bool Match(int) noexcept override final { return false; } - [[nodiscard]] bool Match(TagType, const TagsPath& tp) noexcept override final { return tagsPath_ == tp; } - void Serialize(WrSerializer&) override final {} - bool Reset() override final { return false; } + [[nodiscard]] bool Match(int) const noexcept final { return false; } + [[nodiscard]] bool Match(const TagsPath& tp) const noexcept final { return tagsPath_ == tp; } private: TagsPath tagsPath_; @@ -54,8 +52,8 @@ class RecoderStringToUuidArray : public Recoder { } return TAG_ARRAY; } - [[nodiscard]] bool Match(int f) noexcept override final { return f == field_; } - [[nodiscard]] bool Match(TagType, const TagsPath&) noexcept override final { return false; } + [[nodiscard]] bool Match(int f) const noexcept final { return f == field_; } + [[nodiscard]] bool Match(const TagsPath&) const noexcept final { return false; } void Recode(Serializer&, WrSerializer&) const override final { assertrx(false); } void Recode(Serializer& rdser, Payload& pl, int tagName, WrSerializer& wrser) override final { if (fromNotArrayField_) { @@ -78,8 +76,6 @@ class RecoderStringToUuidArray : public Recoder { wrser.PutVarUint(count); } } - void Serialize(WrSerializer&) override final {} - bool Reset() override final { return false; } private: const int field_{std::numeric_limits::max()}; @@ -98,15 +94,13 @@ class RecoderStringToUuid : public Recoder { } return TAG_UUID; } - [[nodiscard]] bool Match(int f) noexcept override final { return f == field_; } - [[nodiscard]] bool Match(TagType, const TagsPath&) noexcept override final { return false; } + [[nodiscard]] bool Match(int f) const noexcept final { return f == field_; } + [[nodiscard]] bool Match(const TagsPath&) const noexcept final { return false; } void Recode(Serializer&, WrSerializer&) const override final { assertrx(false); } void Recode(Serializer& rdser, Payload& pl, int tagName, WrSerializer& wrser) override final { pl.Set(field_, Variant{rdser.GetStrUuid()}, true); wrser.PutCTag(ctag{TAG_UUID, tagName, field_}); } - void Serialize(WrSerializer&) override final {} - bool Reset() override final { return false; } private: const int field_{std::numeric_limits::max()}; diff --git a/cpp_src/core/formatters/key_string_fmt.h b/cpp_src/core/formatters/key_string_fmt.h index 37869b917..59d0086df 100644 --- a/cpp_src/core/formatters/key_string_fmt.h +++ b/cpp_src/core/formatters/key_string_fmt.h @@ -1,7 +1,7 @@ #pragma once -#include "fmt/format.h" #include "core/keyvalue/key_string.h" +#include "fmt/format.h" template <> struct fmt::printf_formatter { diff --git a/cpp_src/core/formatters/uuid_fmt.h b/cpp_src/core/formatters/uuid_fmt.h index e77ec886b..e249d4b55 100644 --- a/cpp_src/core/formatters/uuid_fmt.h +++ b/cpp_src/core/formatters/uuid_fmt.h @@ -1,7 +1,7 @@ #pragma once -#include "fmt/format.h" #include "core/keyvalue/uuid.h" +#include "fmt/format.h" template <> struct fmt::printf_formatter { diff --git a/cpp_src/core/ft/areaholder.h b/cpp_src/core/ft/areaholder.h index 53bac35b1..3bb410fa8 100644 --- a/cpp_src/core/ft/areaholder.h +++ b/cpp_src/core/ft/areaholder.h @@ -14,10 +14,8 @@ struct Area { Area() noexcept : start(0), end(0) {} Area(int s, int e) noexcept : start(s), end(e) {} - [[nodiscard]] bool inline IsIn(int pos) noexcept { return pos <= end && pos >= start; } - - [[nodiscard]] bool inline Concat(const Area& rhs) noexcept { - if (IsIn(rhs.start) || IsIn(rhs.end) || (start > rhs.start && end < rhs.end)) { + [[nodiscard]] bool Concat(const Area& rhs) noexcept { + if (isIn(rhs.start) || isIn(rhs.end) || (start > rhs.start && end < rhs.end)) { if (start > rhs.start) { start = rhs.start; } @@ -31,19 +29,35 @@ struct Area { int start; int end; + +private: + [[nodiscard]] bool inline isIn(int pos) noexcept { return pos <= end && pos >= start; } }; -class AreaHolder; +struct AreaDebug { + enum class PhraseMode { None, Start, End }; + AreaDebug() {} + AreaDebug(int s, int e, std::string&& p, PhraseMode phMode) noexcept : start(s), end(e), props(p), phraseMode(phMode) {} + [[nodiscard]] RX_ALWAYS_INLINE bool Concat(const AreaDebug&) noexcept { return false; } + int start = 0; + int end = 0; + std::string props; + PhraseMode phraseMode = PhraseMode::None; +}; -class AreaBuffer { +template +class AreasInDocument; + +template +class AreasInField { public: - AreaBuffer() = default; + AreasInField() = default; [[nodiscard]] size_t Size() const noexcept { return data_.size(); } [[nodiscard]] bool Empty() const noexcept { return data_.empty(); } void Commit() { if (!data_.empty()) { boost::sort::pdqsort_branchless(data_.begin(), data_.end(), - [](const Area& rhs, const Area& lhs) noexcept { return rhs.start < lhs.start; }); + [](const AreaType& rhs, const AreaType& lhs) noexcept { return rhs.start < lhs.start; }); for (auto vit = data_.begin() + 1; vit != data_.end(); ++vit) { auto prev = vit - 1; if (vit->Concat(*prev)) { @@ -52,7 +66,7 @@ class AreaBuffer { } } } - [[nodiscard]] bool Insert(Area&& area, float termRank, int maxAreasInDoc, float maxTermRank) { + [[nodiscard]] bool Insert(AreaType&& area, float termRank, int maxAreasInDoc, float maxTermRank) { if (!data_.empty() && data_.back().Concat(area)) { return true; } else { @@ -71,22 +85,26 @@ class AreaBuffer { return false; } - [[nodiscard]] const RVector& GetData() const noexcept { return data_; } - void MoveAreas(AreaHolder& to, int field, int32_t rank, int maxAreasInDoc); + [[nodiscard]] const RVector& GetData() const noexcept { return data_; } + void MoveAreas(AreasInDocument& to, int field, int32_t rank, int maxAreasInDoc) { + for (auto& v : data_) { + [[maybe_unused]] bool r = to.InsertArea(std::move(v), field, rank, maxAreasInDoc); + } + to.UpdateRank(rank); + data_.resize(0); + } private: - RVector data_; + RVector data_; int index_ = 0; }; -class AreaHolder { +template +class AreasInDocument { public: - typedef std::shared_ptr Ptr; - typedef std::unique_ptr UniquePtr; - - AreaHolder() = default; - ~AreaHolder() = default; - AreaHolder(AreaHolder&&) = default; + AreasInDocument() = default; + ~AreasInDocument() = default; + AreasInDocument(AreasInDocument&&) = default; void Reserve(int size) { areas_.reserve(size); } void ReserveField(int size) { areas_.resize(size); } void Commit() { @@ -95,21 +113,24 @@ class AreaHolder { area.Commit(); } } - [[nodiscard]] bool AddWord(int pos, int field, int32_t rank, int maxAreasInDoc) { - return InsertArea(Area{pos, pos + 1}, field, rank, maxAreasInDoc); + [[nodiscard]] bool AddWord(AreaType&& area, int field, int32_t rank, int maxAreasInDoc) { + return InsertArea(std::move(area), field, rank, maxAreasInDoc); } void UpdateRank(int32_t rank) noexcept { if (rank > maxTermRank_) { maxTermRank_ = rank; } } - [[nodiscard]] AreaBuffer* GetAreas(int field) { + + [[nodiscard]] AreasInField* GetAreas(int field) { if (!commited_) { Commit(); } return (areas_.size() <= size_t(field)) ? nullptr : &areas_[field]; } - [[nodiscard]] AreaBuffer* GetAreasRaw(int field) noexcept { return (areas_.size() <= size_t(field)) ? nullptr : &areas_[field]; } + [[nodiscard]] AreasInField* GetAreasRaw(int field) noexcept { + return (areas_.size() <= size_t(field)) ? nullptr : &areas_[field]; + } [[nodiscard]] bool IsCommited() const noexcept { return commited_; } [[nodiscard]] size_t GetAreasCount() const noexcept { size_t size = 0; @@ -118,7 +139,7 @@ class AreaHolder { } return size; } - [[nodiscard]] bool InsertArea(Area&& area, int field, int32_t rank, int maxAreasInDoc) { + [[nodiscard]] bool InsertArea(AreaType&& area, int field, int32_t rank, int maxAreasInDoc) { commited_ = false; if (areas_.size() <= size_t(field)) { areas_.resize(field + 1); @@ -129,16 +150,8 @@ class AreaHolder { private: bool commited_ = false; - RVector areas_; + RVector, 3> areas_; int32_t maxTermRank_ = 0; }; -inline void AreaBuffer::MoveAreas(AreaHolder& to, int field, int32_t rank, int maxAreasInDoc) { - for (auto& v : data_) { - [[maybe_unused]] bool r = to.InsertArea(std::move(v), field, rank, maxAreasInDoc); - } - to.UpdateRank(rank); - data_.resize(0); -} - } // namespace reindexer diff --git a/cpp_src/core/ft/ft_fast/dataholder.cc b/cpp_src/core/ft/ft_fast/dataholder.cc index 4dc826ce9..e41d4f0b7 100644 --- a/cpp_src/core/ft/ft_fast/dataholder.cc +++ b/cpp_src/core/ft/ft_fast/dataholder.cc @@ -104,8 +104,8 @@ void DataHolder::Clear() { } template -void DataHolder::StartCommit(bool complte_updated) { - if (NeedRebuild(complte_updated)) { +void DataHolder::StartCommit(bool complete_updated) { + if (NeedRebuild(complete_updated)) { status_ = FullRebuild; Clear(); diff --git a/cpp_src/core/ft/ft_fast/dataholder.h b/cpp_src/core/ft/ft_fast/dataholder.h index 5926fc491..943f02b65 100644 --- a/cpp_src/core/ft/ft_fast/dataholder.h +++ b/cpp_src/core/ft/ft_fast/dataholder.h @@ -109,7 +109,7 @@ class IDataHolder { virtual void Process(size_t fieldSize, bool multithread) = 0; virtual size_t GetMemStat() = 0; virtual void Clear() = 0; - virtual void StartCommit(bool complte_updated) = 0; + virtual void StartCommit(bool complete_updated) = 0; void SetConfig(FtFastConfig* cfg); CommitStep& GetStep(WordIdType id) noexcept { assertrx(id.b.step_num < steps.size()); diff --git a/cpp_src/core/ft/ft_fast/selecter.cc b/cpp_src/core/ft/ft_fast/selecter.cc index e0bef67a1..ec3f63899 100644 --- a/cpp_src/core/ft/ft_fast/selecter.cc +++ b/cpp_src/core/ft/ft_fast/selecter.cc @@ -119,9 +119,9 @@ void Selecter::prepareVariants(std::vector& variants, RV // RX_NO_INLINE just for build test purpose. Do not expect any effect here template -template -RX_NO_INLINE MergeData Selecter::Process(FtDSLQuery&& dsl, bool inTransaction, FtSortType ftSortType, - FtMergeStatuses::Statuses&& mergeStatuses, const RdxContext& rdxCtx) { +template +MergeType Selecter::Process(FtDSLQuery&& dsl, bool inTransaction, FtSortType ftSortType, FtMergeStatuses::Statuses&& mergeStatuses, + const RdxContext& rdxCtx) { FtSelectContext ctx; ctx.rawResults.reserve(dsl.size()); // STEP 2: Search dsl terms for each variant @@ -210,38 +210,38 @@ RX_NO_INLINE MergeData Selecter::Process(FtDSLQuery&& dsl, bool inTransa for (auto& res : ctx.rawResults) { results.emplace_back(std::move(res)); } - const auto maxMergedSize = std::min(size_t(holder_.cfg_->mergeLimit), ctx.totalORVids); + const auto maxMergedSize = std::min(size_t(holder_.cfg_->mergeLimit), ctx.totalORVids); if (maxMergedSize < 0xFFFF) { - return mergeResultsBmType(std::move(results), ctx.totalORVids, synonymsBounds, inTransaction, ftSortType, - std::move(mergeStatuses), rdxCtx); + return mergeResultsBmType(std::move(results), ctx.totalORVids, synonymsBounds, inTransaction, ftSortType, + std::move(mergeStatuses), rdxCtx); } else if (maxMergedSize < 0xFFFFFFFF) { - return mergeResultsBmType(std::move(results), ctx.totalORVids, synonymsBounds, inTransaction, ftSortType, - std::move(mergeStatuses), rdxCtx); + return mergeResultsBmType(std::move(results), ctx.totalORVids, synonymsBounds, inTransaction, ftSortType, + std::move(mergeStatuses), rdxCtx); } else { assertrx_throw(false); } - return MergeData(); + return MergeType(); } template -template -MergeData Selecter::mergeResultsBmType(std::vector&& results, size_t totalORVids, +template +MergeType Selecter::mergeResultsBmType(std::vector&& results, size_t totalORVids, const std::vector& synonymsBounds, bool inTransaction, FtSortType ftSortType, FtMergeStatuses::Statuses&& mergeStatuses, const RdxContext& rdxCtx) { switch (holder_.cfg_->bm25Config.bm25Type) { case FtFastConfig::Bm25Config::Bm25Type::rx: - return mergeResults(std::move(results), totalORVids, synonymsBounds, inTransaction, ftSortType, - std::move(mergeStatuses), rdxCtx); + return mergeResults(std::move(results), totalORVids, synonymsBounds, inTransaction, + ftSortType, std::move(mergeStatuses), rdxCtx); case FtFastConfig::Bm25Config::Bm25Type::classic: - return mergeResults(std::move(results), totalORVids, synonymsBounds, inTransaction, ftSortType, - std::move(mergeStatuses), rdxCtx); + return mergeResults(std::move(results), totalORVids, synonymsBounds, inTransaction, + ftSortType, std::move(mergeStatuses), rdxCtx); case FtFastConfig::Bm25Config::Bm25Type::wordCount: - return mergeResults(std::move(results), totalORVids, synonymsBounds, inTransaction, ftSortType, - std::move(mergeStatuses), rdxCtx); + return mergeResults(std::move(results), totalORVids, synonymsBounds, inTransaction, + ftSortType, std::move(mergeStatuses), rdxCtx); } assertrx_throw(false); - return MergeData(); + return MergeType(); } template @@ -449,33 +449,32 @@ RX_ALWAYS_INLINE void Selecter::debugMergeStep(const char* msg, int vid, template template RX_ALWAYS_INLINE void Selecter::calcFieldBoost(const Calculator& bm25Calc, unsigned long long f, const IdRelType& relid, - const FtDslOpts& opts, int termProc, double& termRank, double& normBm25, - bool& dontSkipCurTermRank, h_vector& ranksInFields, int& field) { + const FtDslOpts& opts, TermRankInfo& termInf, bool& dontSkipCurTermRank, + h_vector& ranksInFields, int& field) { assertrx(f < holder_.cfg_->fieldsCfg.size()); const auto& fldCfg = holder_.cfg_->fieldsCfg[f]; // raw bm25 const double bm25 = bm25Calc.Get(relid.WordsInField(f), holder_.vdocs_[relid.Id()].wordsCount[f], holder_.avgWordsCount_[f]); - // normalized bm25 const double normBm25Tmp = bound(bm25, fldCfg.bm25Weight, fldCfg.bm25Boost); + termInf.positionRank = bound(::pos2rank(relid.MinPositionInField(f)), fldCfg.positionWeight, fldCfg.positionBoost); + termInf.termLenBoost = bound(opts.termLenBoost, fldCfg.termLenWeight, fldCfg.termLenBoost); - const double positionRank = bound(::pos2rank(relid.MinPositionInField(f)), fldCfg.positionWeight, fldCfg.positionBoost); - - float termLenBoost = bound(opts.termLenBoost, fldCfg.termLenWeight, fldCfg.termLenBoost); // final term rank calculation - const double termRankTmp = opts.fieldsOpts[f].boost * termProc * normBm25Tmp * opts.boost * termLenBoost * positionRank; + const double termRankTmp = + opts.fieldsOpts[f].boost * termInf.proc * normBm25Tmp * opts.boost * termInf.termLenBoost * termInf.positionRank; const bool needSumRank = opts.fieldsOpts[f].needSumRank; - if (termRankTmp > termRank) { + if (termRankTmp > termInf.termRank) { if (dontSkipCurTermRank) { - ranksInFields.push_back(termRank); + ranksInFields.push_back(termInf.termRank); } field = f; - normBm25 = normBm25Tmp; - termRank = termRankTmp; + termInf.termRank = termRankTmp; + termInf.bm25Norm = normBm25Tmp; dontSkipCurTermRank = needSumRank; - } else if (!dontSkipCurTermRank && needSumRank && termRank == termRankTmp) { + } else if (!dontSkipCurTermRank && needSumRank && termInf.termRank == termRankTmp) { field = f; - normBm25 = normBm25Tmp; + termInf.bm25Norm = normBm25Tmp; dontSkipCurTermRank = true; } else if (termRankTmp && needSumRank) { ranksInFields.push_back(termRankTmp); @@ -483,44 +482,71 @@ RX_ALWAYS_INLINE void Selecter::calcFieldBoost(const Calculator& bm25Cal } template -AreaHolder Selecter::createAreaFromSubMerge(const MergedIdRelExArea& posInfo) { - AreaHolder area; - if (posInfo.wordPosForChain.empty()) { - return area; +template +void Selecter::insertSubMergeArea(const MergedIdRelGroupArea& posInfo, PosT cur, int prevIndex, AreasInDocument& area) { + PosT last = cur, first = cur; + int indx = int(posInfo.wordPosForChain.size()) - 2; + while (indx >= 0 && prevIndex != -1) { + auto pos = posInfo.wordPosForChain[indx][prevIndex].first; + prevIndex = posInfo.wordPosForChain[indx][prevIndex].second; + first = pos; + indx--; } + assertrx_throw(first.field() == last.field()); + if (area.InsertArea(Area(first.pos(), last.pos() + 1), cur.field(), posInfo.rank, maxAreasInDoc_)) { + area.UpdateRank(float(posInfo.rank)); + } +} - for (const auto& v : posInfo.wordPosForChain.back()) { - IdRelType::PosType last = v.first; - IdRelType::PosType first = v.first; - int indx = int(posInfo.wordPosForChain.size()) - 2; - int prevIndex = v.second; - while (indx >= 0 && prevIndex != -1) { - auto pos = posInfo.wordPosForChain[indx][prevIndex].first; - prevIndex = posInfo.wordPosForChain[indx][prevIndex].second; - first = pos; - indx--; +template +template +void Selecter::insertSubMergeArea(const MergedIdRelGroupArea& posInfo, PosT cur, int prevIndex, + AreasInDocument& area) { + int indx = int(posInfo.wordPosForChain.size()) - 1; + while (indx >= 0 && prevIndex != -1) { + PosT pos = posInfo.wordPosForChain[indx][prevIndex].first; + prevIndex = posInfo.wordPosForChain[indx][prevIndex].second; + AreaDebug::PhraseMode mode = AreaDebug::PhraseMode::None; + if (indx == int(posInfo.wordPosForChain.size()) - 1) { + mode = AreaDebug::PhraseMode::End; + } else if (indx == 0) { + mode = AreaDebug::PhraseMode::Start; } - assertrx(first.field() == last.field()); - if (area.InsertArea(Area(first.pos(), last.pos() + 1), v.first.field(), posInfo.rank, maxAreasInDoc_)) { + if (area.InsertArea(AreaDebug(pos.pos(), pos.pos() + 1, std::move(pos.info), mode), cur.field(), posInfo.rank, -1)) { area.UpdateRank(float(posInfo.rank)); } + + indx--; + } +} + +template +template +AreasInDocument Selecter::createAreaFromSubMerge(const MergedIdRelGroupArea& posInfo) { + AreasInDocument area; + if (posInfo.wordPosForChain.empty()) { + return area; + } + for (const auto& v : posInfo.wordPosForChain.back()) { + insertSubMergeArea(posInfo, v.first, v.second, area); } return area; } template -void Selecter::copyAreas(AreaHolder& subMerged, AreaHolder& merged, int32_t rank) { +template +void Selecter::copyAreas(AreasInDocument& subMerged, AreasInDocument& merged, int32_t rank) { for (size_t f = 0; f < fieldSize_; f++) { auto areas = subMerged.GetAreas(f); if (areas) { - areas->MoveAreas(merged, f, rank, maxAreasInDoc_); + areas->MoveAreas(merged, f, rank, std::is_same_v ? -1 : maxAreasInDoc_); } } } template -template -void Selecter::subMergeLoop(std::vector& subMerged, std::vector& subMergedPos, MergeData& merged, +template +void Selecter::subMergeLoop(MergeType& subMerged, std::vector& subMergedPos, MergeType& merged, std::vector& merged_rd, FtMergeStatuses::Statuses& mergeStatuses, std::vector& idoffsets, std::vector* checkAndOpMerge, const bool hasBeenAnd) { for (size_t subMergedIndex = 0, sz = subMerged.size(); subMergedIndex < sz; subMergedIndex++) { @@ -543,7 +569,7 @@ void Selecter::subMergeLoop(std::vector& subMerged, std::vect for (const auto& p : smPos.posTmp) { mPos.next.Add(p.first); } - merged.vectorAreas.emplace_back(createAreaFromSubMerge(smPos)); + merged.vectorAreas.emplace_back(createAreaFromSubMerge(smPos)); m.areaIndex = merged.vectorAreas.size() - 1; } else { mPos.next = std::move(smPos.posTmp); @@ -565,14 +591,13 @@ void Selecter::subMergeLoop(std::vector& subMerged, std::vect for (const auto& p : subPos.posTmp) { subPos.next.Add(p.first); } - AreaHolder area = createAreaFromSubMerge(subPos); + AreasInDocument area = createAreaFromSubMerge(subPos); int32_t areaIndex = merged[mergedIndex].areaIndex; if (areaIndex != -1 && areaIndex >= int(merged.vectorAreas.size())) { throw Error(errLogic, "FT merge: Incorrect area index %d (areas vector size is %d)", areaIndex, merged.vectorAreas.size()); } - AreaHolder& areaTo = merged.vectorAreas[areaIndex]; - copyAreas(area, areaTo, subMergeInfo.proc); + copyAreas(area, merged.vectorAreas[areaIndex], subMergeInfo.proc); } else { subPos.next = std::move(subPos.posTmp); } @@ -589,9 +614,9 @@ void Selecter::subMergeLoop(std::vector& subMerged, std::vect } template -template +template void Selecter::mergeGroupResult(std::vector& rawResults, size_t from, size_t to, - FtMergeStatuses::Statuses& mergeStatuses, MergeData& merged, std::vector& merged_rd, + FtMergeStatuses::Statuses& mergeStatuses, MergeType& merged, std::vector& merged_rd, OpType op, const bool hasBeenAnd, std::vector& idoffsets, const bool inTransaction, const RdxContext& rdxCtx) { // And - MustPresent @@ -599,14 +624,16 @@ void Selecter::mergeGroupResult(std::vector& rawResul // Not - NotPresent // hasBeenAnd shows whether it is possible to expand the set of documents (if there was already And, then the set of documents is not // expandable) - MergeData subMerged; - std::vector subMergedPositionData; + MergeType subMerged; + std::vector subMergedPositionData; - mergeResultsPart(rawResults, from, to, subMerged, subMergedPositionData, inTransaction, rdxCtx); + mergeResultsPart(rawResults, from, to, subMerged, subMergedPositionData, + inTransaction, rdxCtx); switch (op) { case OpOr: { - subMergeLoop(subMerged, subMergedPositionData, merged, merged_rd, mergeStatuses, idoffsets, nullptr, hasBeenAnd); + subMergeLoop(subMerged, subMergedPositionData, merged, merged_rd, mergeStatuses, + idoffsets, nullptr, hasBeenAnd); break; } case OpAnd: { @@ -614,7 +641,8 @@ void Selecter::mergeGroupResult(std::vector& rawResul // To do this, we intersect the checkAndOpMerge array with the merged array std::vector checkAndOpMerge; checkAndOpMerge.resize(holder_.vdocs_.size(), false); - subMergeLoop(subMerged, subMergedPositionData, merged, merged_rd, mergeStatuses, idoffsets, &checkAndOpMerge, hasBeenAnd); + subMergeLoop(subMerged, subMergedPositionData, merged, merged_rd, mergeStatuses, + idoffsets, &checkAndOpMerge, hasBeenAnd); // intersect checkAndOpMerge with merged for (auto& mergedDocInfo : merged) { if (!checkAndOpMerge[mergedDocInfo.id]) { @@ -639,22 +667,19 @@ void Selecter::mergeGroupResult(std::vector& rawResul } } template -template -void Selecter::addNewTerm(FtMergeStatuses::Statuses& mergeStatuses, MergeData& merged, std::vector& idoffsets, +template +void Selecter::addNewTerm(FtMergeStatuses::Statuses& mergeStatuses, MergeType& merged, std::vector& idoffsets, std::vector& curExists, const IdRelType& relid, index_t rawResIndex, int32_t termRank, int field) { const int vid = relid.Id(); MergeInfo info; info.id = vid; info.proc = termRank; info.field = field; - if (needArea_) { + + if constexpr (std::is_same_v&, decltype(merged)> || std::is_same_v&, decltype(merged)>) { auto& area = merged.vectorAreas.emplace_back(); info.areaIndex = merged.vectorAreas.size() - 1; area.ReserveField(fieldSize_); - for (auto pos : relid.Pos()) { - [[maybe_unused]] bool r = area.AddWord(pos.pos(), pos.field(), termRank, maxAreasInDoc_); - } - area.UpdateRank(termRank); } merged.push_back(std::move(info)); mergeStatuses[vid] = rawResIndex + 1; @@ -665,16 +690,30 @@ void Selecter::addNewTerm(FtMergeStatuses::Statuses& mergeStatuses, Merg } template -void Selecter::addAreas(MergeData& merged, int32_t areaIndex, const IdRelType& relid, int32_t termRank) { - if (needArea_) { - AreaHolder& area = merged.vectorAreas[areaIndex]; - for (auto pos : relid.Pos()) { - if (!area.AddWord(pos.pos(), pos.field(), termRank, maxAreasInDoc_)) { - break; - } +void Selecter::addAreas(AreasInDocument& area, const IdRelType& relid, int32_t termRank, const TermRankInfo& termInf, + const std::wstring& pattern) { + (void)termInf; + (void)pattern; + for (auto pos : relid.Pos()) { + if (!area.AddWord(Area(pos.pos(), pos.pos() + 1), pos.field(), termRank, maxAreasInDoc_)) { + break; } - area.UpdateRank(termRank); } + area.UpdateRank(termRank); +} + +template +void Selecter::addAreas(AreasInDocument& area, const IdRelType& relid, int32_t termRank, const TermRankInfo& termInf, + const std::wstring& pattern) { + (void)termRank; + utf16_to_utf8(pattern, const_cast(termInf.ftDslTerm)); + for (auto pos : relid.Pos()) { + if (!area.AddWord(AreaDebug(pos.pos(), pos.pos() + 1, termInf.ToString(), AreaDebug::PhraseMode::None), pos.field(), + termInf.termRank, -1)) { + break; + } + } + area.UpdateRank(termInf.termRank); } // idf=max(0.2, log((N-M+1)/M)/log(1+N)) @@ -692,9 +731,9 @@ void Selecter::addAreas(MergeData& merged, int32_t areaIndex, const IdRe // docRank=summ(max(subTermRank))*255/allmax // allmax=max(docRank) template -template +template void Selecter::mergeIteration(TextSearchResults& rawRes, index_t rawResIndex, FtMergeStatuses::Statuses& mergeStatuses, - MergeData& merged, std::vector& merged_rd, std::vector& idoffsets, + MergedType& merged, std::vector& merged_rd, std::vector& idoffsets, std::vector& curExists, const bool hasBeenAnd, const bool inTransaction, const RdxContext& rdxCtx) { const auto& vdocs = holder_.vdocs_; @@ -753,7 +792,10 @@ void Selecter::mergeIteration(TextSearchResults& rawRes, index_t rawResI } // Find field with max rank - auto [termRank, field] = calcTermRank(rawRes, bm25, relid, r.proc); + TermRankInfo termInf; + termInf.proc = r.proc; + termInf.pattern = r.pattern; + auto [termRank, field] = calcTermRank(rawRes, bm25, relid, termInf); if (!termRank) { continue; } @@ -764,13 +806,18 @@ void Selecter::mergeIteration(TextSearchResults& rawRes, index_t rawResI if (simple) { // one term if (vidStatus) { MergeInfo& info = merged[idoffsets[vid]]; - addAreas(merged, info.areaIndex, relid, termRank); + if constexpr (std::is_same_v, MergedType> || std::is_same_v, MergedType>) { + addAreas(merged.vectorAreas[info.areaIndex], relid, termRank, termInf, rawRes.term.pattern); + } if (info.proc < static_cast(termRank)) { info.proc = termRank; info.field = field; } } else if (merged.size() < holder_.cfg_->mergeLimit) { // add new addNewTerm(mergeStatuses, merged, idoffsets, curExists, relid, rawResIndex, int32_t(termRank), field); + if constexpr (std::is_same_v, MergedType> || std::is_same_v, MergedType>) { + addAreas(merged.vectorAreas.back(), relid, termRank, termInf, rawRes.term.pattern); + } } } else { if (vidStatus) { @@ -784,8 +831,9 @@ void Selecter::mergeIteration(TextSearchResults& rawRes, index_t rawResI normDist = bound(1.0 / double(std::max(distance, 1)), holder_.cfg_->distanceWeight, holder_.cfg_->distanceBoost); } int finalRank = normDist * termRank; - - addAreas(merged, info.areaIndex, relid, termRank); + if constexpr (std::is_same_v, MergedType> || std::is_same_v, MergedType>) { + addAreas(merged.vectorAreas[info.areaIndex], relid, termRank, termInf, rawRes.term.pattern); + } if (finalRank > curMerged_rd.rank) { info.proc -= curMerged_rd.rank; info.proc += finalRank; @@ -795,6 +843,10 @@ void Selecter::mergeIteration(TextSearchResults& rawRes, index_t rawResI curExists[vid] = true; } else if (merged.size() < holder_.cfg_->mergeLimit && !hasBeenAnd) { // add new addNewTerm(mergeStatuses, merged, idoffsets, curExists, relid, rawResIndex, termRank, field); + MergeInfo& info = merged[idoffsets[vid]]; + if constexpr (std::is_same_v, MergedType> || std::is_same_v, MergedType>) { + addAreas(merged.vectorAreas[info.areaIndex], relid, termRank, termInf, rawRes.term.pattern); + } merged_rd.emplace_back(IdRelType(std::move(relid)), int32_t(termRank), rawRes.term.opts.qpos); } } @@ -802,14 +854,13 @@ void Selecter::mergeIteration(TextSearchResults& rawRes, index_t rawResI } } template + template std::pair Selecter::calcTermRank(const TextSearchResults& rawRes, Calculator bm25Calc, const IdRelType& relid, - int proc) { + TermRankInfo& termInf) { // Find field with max rank int field = 0; - double termRank = 0.0; bool dontSkipCurTermRank = false; - double normBm25 = 0.0; h_vector ranksInFields; for (unsigned long long fieldsMask = relid.UsedFieldsMask(), f = 0; fieldsMask; ++f, fieldsMask >>= 1) { @@ -827,31 +878,31 @@ std::pair Selecter::calcTermRank(const TextSearchResults& r assertrx(f < rawRes.term.opts.fieldsOpts.size()); const auto fboost = rawRes.term.opts.fieldsOpts[f].boost; if (fboost) { - calcFieldBoost(bm25Calc, f, relid, rawRes.term.opts, proc, termRank, normBm25, dontSkipCurTermRank, ranksInFields, field); + calcFieldBoost(bm25Calc, f, relid, rawRes.term.opts, termInf, dontSkipCurTermRank, ranksInFields, field); } } - if (!termRank) { - return std::make_pair(termRank, field); + if (!termInf.termRank) { + return std::make_pair(termInf.termRank, field); } if (holder_.cfg_->summationRanksByFieldsRatio > 0) { boost::sort::pdqsort_branchless(ranksInFields.begin(), ranksInFields.end()); double k = holder_.cfg_->summationRanksByFieldsRatio; for (auto rank : ranksInFields) { - termRank += (k * rank); + termInf.termRank += (k * rank); k *= holder_.cfg_->summationRanksByFieldsRatio; } } - return std::make_pair(termRank, field); + return std::make_pair(termInf.termRank, field); } template -template +template void Selecter::mergeIterationGroup(TextSearchResults& rawRes, index_t rawResIndex, FtMergeStatuses::Statuses& mergeStatuses, - MergeData& merged, std::vector

& merged_rd, std::vector& idoffsets, - std::vector& present, const bool firstTerm, const bool inTransaction, - const RdxContext& rdxCtx) { + MergeType& merged, std::vector& mergedPos, + std::vector& idoffsets, std::vector& present, const bool firstTerm, + const bool inTransaction, const RdxContext& rdxCtx) { const auto& vdocs = holder_.vdocs_; const size_t totalDocsCount = vdocs.size(); @@ -886,7 +937,10 @@ void Selecter::mergeIterationGroup(TextSearchResults& rawRes, index_t ra } // Find field with max rank - auto [termRank, field] = calcTermRank(rawRes, bm25, relid, r.proc); + TermRankInfo termInf; + termInf.proc = r.proc; + termInf.pattern = r.pattern; + auto [termRank, field] = calcTermRank(rawRes, bm25, relid, termInf); if (!termRank) { continue; } @@ -898,8 +952,18 @@ void Selecter::mergeIterationGroup(TextSearchResults& rawRes, index_t ra // match of 2-rd, and next terms if (!firstTerm) { auto& curMerged = merged[idoffsets[vid]]; - auto& curMergedPos = merged_rd[idoffsets[vid]]; - int minDist = curMergedPos.cur.MergeWithDist(relid, rawRes.term.opts.distance, curMergedPos.posTmp); + auto& curMergedPos = mergedPos[idoffsets[vid]]; + int minDist = -1; + if constexpr (isGroupMergeWithAreas()) { + if constexpr (std::is_same_v) { + utf16_to_utf8(rawRes.term.pattern, termInf.ftDslTerm); + minDist = curMergedPos.cur.MergeWithDist(relid, rawRes.term.opts.distance, curMergedPos.posTmp, termInf.ToString()); + } else { + minDist = curMergedPos.cur.MergeWithDist(relid, rawRes.term.opts.distance, curMergedPos.posTmp, ""); + } + } else { + minDist = curMergedPos.cur.MergeWithDist(relid, rawRes.term.opts.distance, curMergedPos.posTmp, ""); + } if (!curMergedPos.posTmp.empty()) { present[vid] = true; double normDist = bound(1.0 / minDist, holder_.cfg_->distanceWeight, holder_.cfg_->distanceBoost); @@ -915,14 +979,21 @@ void Selecter::mergeIterationGroup(TextSearchResults& rawRes, index_t ra } } else { if (vidStatus) { - if constexpr (isGroupMergeWithAreas

()) { - auto& pos = merged_rd[idoffsets[vid]].posTmp; + if constexpr (isGroupMergeWithAreas()) { + auto& pos = mergedPos[idoffsets[vid]].posTmp; pos.reserve(pos.size() + relid.Size()); for (const auto& p : relid.Pos()) { - pos.emplace_back(p, -1); + if constexpr (std::is_same_v) { + pos.emplace_back(p, -1); + } else if constexpr (std::is_same_v) { + utf16_to_utf8(rawRes.term.pattern, termInf.ftDslTerm); + pos.emplace_back(PosTypeDebug(p, termInf.ToString()), -1); + } else { + static_assert(!sizeof(MergedIdRelGroupType), "incorrect MergedIdRelGroupType::TypeTParam type"); + } } } else { - auto& pos = merged_rd[idoffsets[vid]].posTmp; + auto& pos = mergedPos[idoffsets[vid]].posTmp; pos.reserve(pos.Size() + relid.Size()); for (const auto& p : relid.Pos()) { @@ -938,16 +1009,24 @@ void Selecter::mergeIterationGroup(TextSearchResults& rawRes, index_t ra mergeStatuses[vid] = rawResIndex + 1; present[vid] = true; idoffsets[vid] = merged.size() - 1; - if constexpr (isGroupMergeWithAreas

()) { - RVector, 4> posTmp; + if constexpr (isGroupMergeWithAreas()) { + RVector, 4> posTmp; posTmp.reserve(relid.Size()); for (const auto& p : relid.Pos()) { - posTmp.emplace_back(p, -1); + if constexpr (std::is_same_v>) { + posTmp.emplace_back(p, -1); + } else if constexpr (std::is_same_v>) { + utf16_to_utf8(rawRes.term.pattern, termInf.ftDslTerm); + PosTypeDebug pd{p, termInf.ToString()}; + posTmp.emplace_back(pd, -1); + } else { + static_assert(!sizeof(MergedIdRelGroupType), "incorrect MergedIdRelGroupType type"); + } } - merged_rd.emplace_back(IdRelType(std::move(relid)), int(termRank), rawRes.term.opts.qpos, std::move(posTmp)); + mergedPos.emplace_back(IdRelType(std::move(relid)), int(termRank), rawRes.term.opts.qpos, std::move(posTmp)); } else { - merged_rd.emplace_back(IdRelType(std::move(relid)), int(termRank), rawRes.term.opts.qpos); + mergedPos.emplace_back(IdRelType(std::move(relid)), int(termRank), rawRes.term.opts.qpos); } } } @@ -955,7 +1034,7 @@ void Selecter::mergeIterationGroup(TextSearchResults& rawRes, index_t ra } for (size_t mergedIndex = 0; mergedIndex < merged.size(); mergedIndex++) { auto& mergedInfo = merged[mergedIndex]; - auto& mergedPosInfo = merged_rd[mergedIndex]; + auto& mergedPosInfo = mergedPos[mergedIndex]; if (mergedPosInfo.posTmp.empty()) { mergedInfo.proc = 0; mergeStatuses[mergedInfo.id] = 0; @@ -964,7 +1043,7 @@ void Selecter::mergeIterationGroup(TextSearchResults& rawRes, index_t ra mergedPosInfo.rank = 0; continue; } - if constexpr (isGroupMerge

()) { + if constexpr (isGroupMerge()) { mergedPosInfo.posTmp.SortAndUnique(); mergedPosInfo.cur = std::move(mergedPosInfo.posTmp); mergedPosInfo.next.Clear(); @@ -972,9 +1051,10 @@ void Selecter::mergeIterationGroup(TextSearchResults& rawRes, index_t ra mergedPosInfo.rank = 0; } else { auto& posTmp = mergedPosInfo.posTmp; - boost::sort::pdqsort_branchless(posTmp.begin(), posTmp.end(), - [](const std::pair& l, - const std::pair& r) noexcept { return l.first < r.first; }); + boost::sort::pdqsort_branchless( + posTmp.begin(), posTmp.end(), + [](const std::pair& l, + const std::pair& r) noexcept { return l.first < r.first; }); auto last = std::unique(posTmp.begin(), posTmp.end()); posTmp.resize(last - posTmp.begin()); @@ -992,9 +1072,9 @@ void Selecter::mergeIterationGroup(TextSearchResults& rawRes, index_t ra } template -template -void Selecter::mergeResultsPart(std::vector& rawResults, size_t from, size_t to, MergeData& merged, - std::vector& mergedPos, const bool inTransaction, const RdxContext& rdxCtx) { +template +void Selecter::mergeResultsPart(std::vector& rawResults, size_t from, size_t to, MergeType& merged, + std::vector& mergedPos, const bool inTransaction, const RdxContext& rdxCtx) { // Current implementation supports OpAnd only assertrx_throw(to <= rawResults.size()); FtMergeStatuses::Statuses mergeStatuses; @@ -1013,8 +1093,8 @@ void Selecter::mergeResultsPart(std::vector& rawResul std::vector exists; bool firstTerm = true; for (size_t i = from; i < to; ++i) { - mergeIterationGroup(rawResults[i], i, mergeStatuses, merged, mergedPos, idoffsets, exists, firstTerm, - inTransaction, rdxCtx); + mergeIterationGroup(rawResults[i], i, mergeStatuses, merged, mergedPos, + idoffsets, exists, firstTerm, inTransaction, rdxCtx); firstTerm = false; // set proc=0 (exclude) for document not containing term for (auto& info : merged) { @@ -1282,13 +1362,13 @@ bool Selecter::TyposHandler::isWordFitMaxLettPerm(const std::string_view } template -template -MergeData Selecter::mergeResults(std::vector&& rawResults, size_t maxMergedSize, - const std::vector& synonymsBounds, bool inTransaction, FtSortType ftSortType, - FtMergeStatuses::Statuses&& mergeStatuses, const RdxContext& rdxCtx) { +template +MergedType Selecter::mergeResults(std::vector&& rawResults, size_t maxMergedSize, + const std::vector& synonymsBounds, bool inTransaction, FtSortType ftSortType, + FtMergeStatuses::Statuses&& mergeStatuses, const RdxContext& rdxCtx) { const auto& vdocs = holder_.vdocs_; - MergeData merged; + MergedType merged; if (!rawResults.size() || !vdocs.size()) { return merged; } @@ -1322,12 +1402,15 @@ MergeData Selecter::mergeResults(std::vector&& rawRes rawResults[k].term.opts.op = OpAnd; k++; } - if (needArea_) { - mergeGroupResult(rawResults, i, k, mergeStatuses, merged, merged_rd, op, hasBeenAnd, idoffsets, - inTransaction, rdxCtx); + if constexpr (std::is_same_v>) { + mergeGroupResult, Bm25T, MergedOffsetT, MergedType>( + rawResults, i, k, mergeStatuses, merged, merged_rd, op, hasBeenAnd, idoffsets, inTransaction, rdxCtx); + } else if constexpr (std::is_same_v>) { + mergeGroupResult, Bm25T, MergedOffsetT, MergedType>( + rawResults, i, k, mergeStatuses, merged, merged_rd, op, hasBeenAnd, idoffsets, inTransaction, rdxCtx); } else { - mergeGroupResult(rawResults, i, k, mergeStatuses, merged, merged_rd, op, hasBeenAnd, idoffsets, - inTransaction, rdxCtx); + mergeGroupResult(rawResults, i, k, mergeStatuses, merged, merged_rd, op, + hasBeenAnd, idoffsets, inTransaction, rdxCtx); } if (op == OpAnd) { hasBeenAnd = true; @@ -1441,14 +1524,37 @@ void Selecter::printVariants(const FtSelectContext& ctx, const TextSearc } template class Selecter; -template MergeData Selecter::Process(FtDSLQuery&&, bool, FtSortType, FtMergeStatuses::Statuses&&, +template MergeDataBase Selecter::Process(FtDSLQuery&&, bool, FtSortType, + FtMergeStatuses::Statuses&&, + const RdxContext&); +template MergeData Selecter::Process>(FtDSLQuery&&, bool, FtSortType, + FtMergeStatuses::Statuses&&, + const RdxContext&); +template MergeData Selecter::Process>(FtDSLQuery&&, bool, + FtSortType, + FtMergeStatuses::Statuses&&, + const RdxContext&); + +template MergeDataBase Selecter::Process(FtDSLQuery&&, bool, FtSortType, + FtMergeStatuses::Statuses&&, const RdxContext&); +template MergeData Selecter::Process(FtDSLQuery&&, bool, FtSortType, + FtMergeStatuses::Statuses&&, const RdxContext&); +template MergeData Selecter::Process(FtDSLQuery&&, bool, FtSortType, + FtMergeStatuses::Statuses&&, const RdxContext&); + +template class Selecter; +template MergeDataBase Selecter::Process(FtDSLQuery&&, bool, FtSortType, FtMergeStatuses::Statuses&&, + const RdxContext&); +template MergeData Selecter::Process(FtDSLQuery&&, bool, FtSortType, FtMergeStatuses::Statuses&&, const RdxContext&); -template MergeData Selecter::Process(FtDSLQuery&&, bool, FtSortType, FtMergeStatuses::Statuses&&, +template MergeData Selecter::Process(FtDSLQuery&&, bool, FtSortType, + FtMergeStatuses::Statuses&&, const RdxContext&); + +template MergeDataBase Selecter::Process(FtDSLQuery&&, bool, FtSortType, FtMergeStatuses::Statuses&&, + const RdxContext&); +template MergeData Selecter::Process(FtDSLQuery&&, bool, FtSortType, FtMergeStatuses::Statuses&&, const RdxContext&); -template class Selecter; -template MergeData Selecter::Process(FtDSLQuery&&, bool, FtSortType, FtMergeStatuses::Statuses&&, - const RdxContext&); -template MergeData Selecter::Process(FtDSLQuery&&, bool, FtSortType, FtMergeStatuses::Statuses&&, - const RdxContext&); +template MergeData Selecter::Process(FtDSLQuery&&, bool, FtSortType, + FtMergeStatuses::Statuses&&, const RdxContext&); } // namespace reindexer diff --git a/cpp_src/core/ft/ft_fast/selecter.h b/cpp_src/core/ft/ft_fast/selecter.h index 0e159f484..0a7b555fe 100644 --- a/cpp_src/core/ft/ft_fast/selecter.h +++ b/cpp_src/core/ft/ft_fast/selecter.h @@ -6,6 +6,7 @@ namespace reindexer { +// Final information about found document struct MergeInfo { IdType id; // Virtual id of merged document (index in vdocs) int32_t proc; // Rank of document @@ -13,9 +14,15 @@ struct MergeInfo { int8_t field; // Field index, where was match }; -struct MergeData : public std::vector { +struct MergeDataBase : public std::vector { + virtual ~MergeDataBase() {} int maxRank = 0; - std::vector vectorAreas; +}; + +template +struct MergeData : public MergeDataBase { + using AT = AreaType; + std::vector> vectorAreas; }; template @@ -23,10 +30,10 @@ class Selecter { typedef fast_hash_map, WordIdTypeHash, WordIdTypeEqual, WordIdTypeLess> FoundWordsType; public: - Selecter(DataHolder& holder, size_t fieldSize, bool needArea, int maxAreasInDoc) - : holder_(holder), fieldSize_(fieldSize), needArea_(needArea), maxAreasInDoc_(maxAreasInDoc) {} + Selecter(DataHolder& holder, size_t fieldSize, int maxAreasInDoc) + : holder_(holder), fieldSize_(fieldSize), maxAreasInDoc_(maxAreasInDoc) {} - // Intermediate information about found document in current merge step. Used only for queries with 2 or more terms + // Intermediate information about document found at current merge step. Used only for queries with 2 or more terms struct MergedIdRel { explicit MergedIdRel(IdRelType&& c, int r, int q) : next(std::move(c)), rank(r), qpos(q) {} explicit MergedIdRel(int r, int q) : rank(r), qpos(q) {} @@ -37,24 +44,26 @@ class Selecter { int32_t qpos; // Position in query }; - struct MergedIdRelEx : public MergedIdRel { - explicit MergedIdRelEx(IdRelType&& c, int r, int q) : MergedIdRel(r, q), posTmp(std::move(c)) {} - MergedIdRelEx(MergedIdRelEx&&) = default; - IdRelType posTmp; // For group only. Collect all positions for subpatterns and the index in the vector with which we merged + struct MergedIdRelGroup : public MergedIdRel { + explicit MergedIdRelGroup(IdRelType&& c, int r, int q) : MergedIdRel(r, q), posTmp(std::move(c)) {} + MergedIdRelGroup(MergedIdRelGroup&&) = default; + IdRelType posTmp; // Group only. Collect all positions for subpatterns and index into vector we merged with }; - struct MergedIdRelExArea : public MergedIdRel { - MergedIdRelExArea(IdRelType&& c, int r, int q, RVector, 4>&& p) + template + struct MergedIdRelGroupArea : public MergedIdRel { + using TypeTParam = PosT; + MergedIdRelGroupArea(IdRelType&& c, int r, int q, RVector, 4>&& p) : MergedIdRel(std::move(c), r, q), posTmp(std::move(p)) {} - MergedIdRelExArea(MergedIdRelExArea&&) = default; + MergedIdRelGroupArea(MergedIdRelGroupArea&&) = default; - RVector, 4> + RVector, 4> posTmp; // For group only. Collect all positions for subpatterns and the index in the vector with which we merged - h_vector, 4>, 2> wordPosForChain; + RVector, 4>, 2> wordPosForChain; }; - template - MergeData Process(FtDSLQuery&& dsl, bool inTransaction, FtSortType ftSortType, FtMergeStatuses::Statuses&& mergeStatuses, + template + MergeType Process(FtDSLQuery&& dsl, bool inTransaction, FtSortType ftSortType, FtMergeStatuses::Statuses&& mergeStatuses, const RdxContext&); private: @@ -65,6 +74,24 @@ class Selecter { int16_t wordLen; }; + struct TermRankInfo { + int32_t termRank = 0; + double bm25Norm = 0.0; + double termLenBoost = 0.0; + double positionRank = 0.0; + double normDist = 0.0; + double proc = 0.0; + double fullMatchBoost = 0.0; + std::string_view pattern; + std::string ftDslTerm; + + std::string ToString() const { + return fmt::format( + R"json({{term_rank:{}, term:{}, pattern:{}, bm25_norm:{}, term_len_boost:{}, position_rank:{}, norm_dist:{}, proc:{}, full_match_boost:{}}} )json", + termRank, ftDslTerm, pattern, bm25Norm, termLenBoost, positionRank, normDist, proc, fullMatchBoost); + } + }; + struct FtVariantEntry { FtVariantEntry() = default; FtVariantEntry(std::string p, FtDslOpts o, int pr, int c) : pattern{std::move(p)}, opts{std::move(o)}, proc{pr}, charsCount{c} {} @@ -178,52 +205,69 @@ class Selecter { std::wstring foundWordUTF16_; }; - template - MergeData mergeResults(std::vector&& rawResults, size_t maxMergedSize, const std::vector& synonymsBounds, + template + MergeType mergeResults(std::vector&& rawResults, size_t totalORVids, const std::vector& synonymsBounds, bool inTransaction, FtSortType ftSortType, FtMergeStatuses::Statuses&& mergeStatuses, const RdxContext&); - template - void mergeIteration(TextSearchResults& rawRes, index_t rawResIndex, FtMergeStatuses::Statuses& mergeStatuses, MergeData& merged, + template + void mergeIteration(TextSearchResults& rawRes, index_t rawResIndex, FtMergeStatuses::Statuses& mergeStatuses, MergeType& merged, std::vector& merged_rd, std::vector& idoffsets, std::vector& curExists, const bool hasBeenAnd, const bool inTransaction, const RdxContext&); - template - void mergeIterationGroup(TextSearchResults& rawRes, index_t rawResIndex, FtMergeStatuses::Statuses& mergeStatuses, MergeData& merged, - std::vector

& merged_rd, std::vector& idoffsets, std::vector& present, + template + void mergeIterationGroup(TextSearchResults& rawRes, index_t rawResIndex, FtMergeStatuses::Statuses& mergeStatuses, MergeType& merged, + std::vector& mergedPos, std::vector& idoffsets, std::vector& present, const bool firstTerm, const bool inTransaction, const RdxContext& rdxCtx); - template + template void mergeGroupResult(std::vector& rawResults, size_t from, size_t to, FtMergeStatuses::Statuses& mergeStatuses, - MergeData& merged, std::vector& merged_rd, OpType op, const bool hasBeenAnd, + MergeType& merged, std::vector& merged_rd, OpType op, const bool hasBeenAnd, std::vector& idoffsets, const bool inTransaction, const RdxContext& rdxCtx); - template - void mergeResultsPart(std::vector& rawResults, size_t from, size_t to, MergeData& merged, + template + void mergeResultsPart(std::vector& rawResults, size_t from, size_t to, MergeType& merged, std::vector& mergedPos, const bool inTransaction, const RdxContext& rdxCtx); - AreaHolder createAreaFromSubMerge(const MergedIdRelExArea& posInfo); - void copyAreas(AreaHolder& subMerged, AreaHolder& merged, int32_t rank); - template - void subMergeLoop(std::vector& subMerged, std::vector& subMergedPos, MergeData& merged, - std::vector& merged_rd, FtMergeStatuses::Statuses& mergeStatuses, std::vector& idoffsets, - std::vector* checkAndOpMerge, const bool hasBeenAnd); + template + AreasInDocument createAreaFromSubMerge(const MergedIdRelGroupArea& posInfo); + + template + void insertSubMergeArea(const MergedIdRelGroupArea& posInfo, PosT cur, int prevIndex, AreasInDocument& area); + + template + void insertSubMergeArea(const MergedIdRelGroupArea& posInfo, PosT cur, int prevIndex, AreasInDocument& area); + + template + void copyAreas(AreasInDocument& subMerged, AreasInDocument& merged, int32_t rank); + + template + void subMergeLoop(MergeType& subMerged, std::vector& subMergedPos, MergeType& merged, std::vector& merged_rd, + FtMergeStatuses::Statuses& mergeStatuses, std::vector& idoffsets, std::vector* checkAndOpMerge, + const bool hasBeenAnd); template - void calcFieldBoost(const Calculator& bm25Calc, unsigned long long f, const IdRelType& relid, const FtDslOpts& opts, int termProc, - double& termRank, double& normBm25, bool& dontSkipCurTermRank, h_vector& ranksInFields, int& field); + void calcFieldBoost(const Calculator& bm25Calc, unsigned long long f, const IdRelType& relid, const FtDslOpts& opts, + TermRankInfo& termInf, bool& dontSkipCurTermRank, h_vector& ranksInFields, int& field); + template - std::pair calcTermRank(const TextSearchResults& rawRes, Calculator c, const IdRelType& relid, int proc); + std::pair calcTermRank(const TextSearchResults& rawRes, Calculator c, const IdRelType& relid, TermRankInfo& termInf); - template - void addNewTerm(FtMergeStatuses::Statuses& mergeStatuses, MergeData& merged, std::vector& idoffsets, + template + void addNewTerm(FtMergeStatuses::Statuses& mergeStatuses, MergeType& merged, std::vector& idoffsets, std::vector& curExists, const IdRelType& relid, index_t rawResIndex, int32_t termRank, int field); - void addAreas(MergeData& merged, int32_t areaIndex, const IdRelType& relid, int32_t termRank); + void addAreas(AreasInDocument& area, const IdRelType& relid, int32_t termRank, const TermRankInfo& termInf, + const std::wstring& pattern); + void addAreas(AreasInDocument& area, const IdRelType& relid, int32_t termRank, const TermRankInfo& termInf, + const std::wstring& pattern); + + template + constexpr static bool IsOneOf = (... || std::is_same_v); template static constexpr bool isSingleTermMerge() noexcept { static_assert( - std::is_same_v || std::is_same_v || std::is_same_v, + IsOneOf, MergedIdRelGroupArea, MergedIdRel>, "unsupported type for mergeIteration"); return std::is_same_v; } @@ -231,21 +275,22 @@ class Selecter { template static constexpr bool isGroupMerge() noexcept { static_assert( - std::is_same_v || std::is_same_v || std::is_same_v, + IsOneOf, MergedIdRelGroupArea, MergedIdRel>, "unsupported type for mergeIteration"); - return std::is_same_v; + return std::is_same_v; } template static constexpr bool isGroupMergeWithAreas() noexcept { static_assert( - std::is_same_v || std::is_same_v || std::is_same_v, + IsOneOf, MergedIdRelGroupArea, MergedIdRel>, "unsupported type for mergeIteration"); - return std::is_same_v; + return std::is_same_v> || + std::is_same_v>; } - template - MergeData mergeResultsBmType(std::vector&& results, size_t totalORVids, const std::vector& synonymsBounds, + template + MergeType mergeResultsBmType(std::vector&& results, size_t totalORVids, const std::vector& synonymsBounds, bool inTransaction, FtSortType ftSortType, FtMergeStatuses::Statuses&& mergeStatuses, const RdxContext& rdxCtx); @@ -263,7 +308,6 @@ class Selecter { DataHolder& holder_; size_t fieldSize_; - const bool needArea_; int maxAreasInDoc_; }; diff --git a/cpp_src/core/ft/ftsetcashe.h b/cpp_src/core/ft/ftsetcashe.h index 6d3802baa..ed1ea8f74 100644 --- a/cpp_src/core/ft/ftsetcashe.h +++ b/cpp_src/core/ft/ftsetcashe.h @@ -8,12 +8,11 @@ namespace reindexer { struct FtIdSetCacheVal { FtIdSetCacheVal() = default; FtIdSetCacheVal(IdSet::Ptr&& i) noexcept : ids(std::move(i)) {} - FtIdSetCacheVal(IdSet::Ptr&& i, FtCtx::Data::Ptr&& c) noexcept : ids(std::move(i)), ctx(std::move(c)) {} - + FtIdSetCacheVal(IdSet::Ptr&& i, FtCtxData::Ptr&& c) noexcept : ids(std::move(i)), ctx(std::move(c)) {} size_t Size() const noexcept { return ids ? (sizeof(*ids.get()) + ids->heap_size()) : 0; } IdSet::Ptr ids; - FtCtx::Data::Ptr ctx; + FtCtxData::Ptr ctx; }; using FtIdSetCache = LRUCache; diff --git a/cpp_src/core/ft/idrelset.cc b/cpp_src/core/ft/idrelset.cc index c1aeaf9e8..74cc28de9 100644 --- a/cpp_src/core/ft/idrelset.cc +++ b/cpp_src/core/ft/idrelset.cc @@ -76,4 +76,58 @@ int IdRelType::MinPositionInField(int field) const noexcept { return res; } +// RVector, 4> +// IdRelType +// RVector, 4> +template +int IdRelType::MergeWithDist(const IdRelType& newWordPos, unsigned int dist, PosTypeT& res, [[maybe_unused]] const std::string& inf) const { + unsigned int minDist = std::numeric_limits::max(); + auto rightIt = newWordPos.pos_.begin(); + const auto leftEnd = pos_.end(); + const auto rightEnd = newWordPos.pos_.end(); + for (auto leftIt = pos_.begin(); leftIt != leftEnd; ++leftIt) { + while (rightIt != rightEnd && rightIt->fpos < leftIt->fpos) { + ++rightIt; + } + // here right pos > left pos + if (rightIt == rightEnd) { + break; + } + if (rightIt->field() != leftIt->field()) { + continue; + } + + auto leftItNext = leftIt + 1; + uint32_t leftNextPos = std::numeric_limits::max(); + if (leftItNext != leftEnd) { + leftNextPos = leftItNext->pos(); + } + + while (rightIt != rightEnd && rightIt->field() == leftIt->field() && uint32_t(rightIt->pos()) < leftNextPos && + rightIt->fpos - leftIt->fpos <= dist) { + minDist = std::min(rightIt->fpos - leftIt->fpos, minDist); + if constexpr (std::is_same_v) { + res.Add(*rightIt); + } else if constexpr (std::is_same_v, 4>>) { + res.emplace_back(*rightIt, leftIt - pos_.begin()); + } else if constexpr (std::is_same_v, 4>>) { + res.emplace_back(PosTypeDebug{*rightIt, inf}, leftIt - pos_.begin()); + } else { + static_assert(!sizeof(PosTypeT), "incorrect PosType type "); + } + ++rightIt; + } + } + return minDist; +} + +template int IdRelType::MergeWithDist(const IdRelType& newWordPos, unsigned int dist, IdRelType& res, + const std::string& inf) const; +template int IdRelType::MergeWithDist, 4>>(const IdRelType& newWordPos, unsigned int dist, + RVector, 4>& res, + const std::string& inf) const; +template int IdRelType::MergeWithDist, 4>>(const IdRelType& newWordPos, unsigned int dist, + RVector, 4>& res, + const std::string&) const; + } // namespace reindexer diff --git a/cpp_src/core/ft/idrelset.h b/cpp_src/core/ft/idrelset.h index 05ed10950..fc967e460 100644 --- a/cpp_src/core/ft/idrelset.h +++ b/cpp_src/core/ft/idrelset.h @@ -48,46 +48,8 @@ class IdRelType { uint32_t fpos; }; - template - int MergeWithDist(const IdRelType& newWordPos, unsigned int dist, PosType& res) const { - int minDist = INT_MAX; - auto rightIt = newWordPos.pos_.begin(); - const auto leftEnd = pos_.end(); - const auto rightEnd = newWordPos.pos_.end(); - for (auto leftIt = pos_.begin(); leftIt != leftEnd; ++leftIt) { - while (rightIt != rightEnd && rightIt->fpos < leftIt->fpos) { - ++rightIt; - } - // here right pos > left pos - if (rightIt == rightEnd) { - break; - } - if (rightIt->field() != leftIt->field()) { - continue; - } - - auto leftItNext = leftIt + 1; - uint32_t leftNextPos = std::numeric_limits::max(); - if (leftItNext != leftEnd) { - leftNextPos = leftItNext->pos(); - } - - while (rightIt != rightEnd && rightIt->field() == leftIt->field() && uint32_t(rightIt->pos()) < leftNextPos && - rightIt->fpos - leftIt->fpos <= dist) { - int d = rightIt->fpos - leftIt->fpos; - if (d < minDist) { - minDist = d; - } - if constexpr (std::is_same_v) { - res.Add(*rightIt); - } else { - res.emplace_back(*rightIt, leftIt - pos_.begin()); - } - ++rightIt; - } - } - return minDist; - } + template + int MergeWithDist(const IdRelType& newWordPos, unsigned int dist, PosTypeT& res, const std::string& inf) const; void Add(int pos, int field) { assertrx_throw(0 <= field && field <= kMaxFtCompositeFields); @@ -141,6 +103,13 @@ class IdRelType { VDocIdType id_ = 0; // index of the document in which the word occurs }; +struct PosTypeDebug : public IdRelType::PosType { + PosTypeDebug() = default; + explicit PosTypeDebug(const IdRelType::PosType& pos, const std::string& inf) : IdRelType::PosType(pos), info(inf) {} + explicit PosTypeDebug(const IdRelType::PosType& pos, std::string&& inf) noexcept : IdRelType::PosType(pos), info(std::move(inf)) {} + std::string info; +}; + class IdRelSet : public std::vector { public: int Add(VDocIdType id, int pos, int field) { diff --git a/cpp_src/core/ft/usingcontainer.h b/cpp_src/core/ft/usingcontainer.h index 143376670..4edfe1549 100644 --- a/cpp_src/core/ft/usingcontainer.h +++ b/cpp_src/core/ft/usingcontainer.h @@ -11,11 +11,24 @@ namespace reindexer { template class RVector : public std::vector { public: + typedef unsigned size_type; + using std::vector::vector; template void clear() noexcept { std::vector::clear(); } + + size_t heap_size() { return std::vector::capacity() * sizeof(T); } + + static constexpr size_type max_size() noexcept { return std::numeric_limits::max() >> 1; } + + void grow(size_type sz) { + size_type cap = std::vector::capacity(); + if (sz > cap) { + std::vector::reserve(std::max(sz, std::min(max_size(), cap * 2))); + } + } }; #else template diff --git a/cpp_src/core/idset.h b/cpp_src/core/idset.h index d6235ac90..167370cc6 100644 --- a/cpp_src/core/idset.h +++ b/cpp_src/core/idset.h @@ -4,6 +4,7 @@ #include #include #include +#include "core/ft/usingcontainer.h" #include "cpp-btree/btree_set.h" #include "estl/h_vector.h" #include "estl/intrusive_ptr.h" @@ -12,7 +13,7 @@ namespace reindexer { -using base_idset = h_vector; +using base_idset = RVector; using base_idsetset = btree::btree_set; class IdSetPlain : protected base_idset { diff --git a/cpp_src/core/index/indextext/fastindextext.cc b/cpp_src/core/index/indextext/fastindextext.cc index fdded3b1f..75dac5450 100644 --- a/cpp_src/core/index/indextext/fastindextext.cc +++ b/cpp_src/core/index/indextext/fastindextext.cc @@ -97,8 +97,8 @@ void FastIndexText::Delete(const Variant& key, IdType id, StringsHolder& strH this->holder_->vdocs_[keyIt->second.VDocID()].keyEntry = nullptr; } if constexpr (is_str_map_v) { - this->idx_map.template erase>( - keyIt, {strHolder, this->KeyType().template Is() && this->opts_.GetCollateMode() == CollateNone}); + this->idx_map.template erase>(keyIt, + {strHolder, this->KeyType().template Is()}); } else { static_assert(is_payload_map_v); this->idx_map.template erase(keyIt, strHolder); @@ -106,9 +106,6 @@ void FastIndexText::Delete(const Variant& key, IdType id, StringsHolder& strH } else { this->addMemStat(keyIt); } - if (this->KeyType().template Is() && this->opts_.GetCollateMode() != CollateNone) { - IndexStore>::Delete(key, id, strHolder, clearCache); - } if (this->cache_ft_) { this->cache_ft_->Clear(); } @@ -125,8 +122,9 @@ IndexMemStat FastIndexText::GetMemStat(const RdxContext& ctx) { return ret; } template -MergeData::iterator FastIndexText::unstableRemoveIf(MergeData& md, int minRelevancy, double scalingFactor, size_t& releventDocs, - int& cnt) { +template +typename MergeType::iterator FastIndexText::unstableRemoveIf(MergeType& md, int minRelevancy, double scalingFactor, size_t& releventDocs, + int& cnt) { if (md.empty()) { return md.begin(); } @@ -138,14 +136,11 @@ MergeData::iterator FastIndexText::unstableRemoveIf(MergeData& md, int minRel if (first == last) { return first; } - auto& vdoc = holder.vdocs_[first->id]; - if (!vdoc.keyEntry) { - break; - } first->proc *= scalingFactor; if (first->proc < minRelevancy) { break; } + auto& vdoc = holder.vdocs_[first->id]; assertrx_throw(!vdoc.keyEntry->Unsorted().empty()); cnt += vdoc.keyEntry->Sorted(0).size(); ++releventDocs; @@ -157,9 +152,6 @@ MergeData::iterator FastIndexText::unstableRemoveIf(MergeData& md, int minRel if (first == last) { return first; } - if (!holder.vdocs_[last->id].keyEntry) { - continue; - } last->proc *= scalingFactor; if (last->proc >= minRelevancy) { break; @@ -176,53 +168,20 @@ MergeData::iterator FastIndexText::unstableRemoveIf(MergeData& md, int minRel } template -IdSet::Ptr FastIndexText::Select(FtCtx::Ptr fctx, FtDSLQuery&& dsl, bool inTransaction, FtSortType ftSortType, - FtMergeStatuses&& statuses, FtUseExternStatuses useExternSt, const RdxContext& rdxCtx) { - fctx->GetData()->extraWordSymbols_ = this->getConfig()->extraWordSymbols; - fctx->GetData()->isWordPositions_ = true; - - MergeData mergeData; - switch (holder_->cfg_->optimization) { - case FtFastConfig::Optimization::Memory: { - DataHolder* d = dynamic_cast*>(holder_.get()); - assertrx_throw(d); - Selecter selecter{*d, this->Fields().size(), fctx->NeedArea(), holder_->cfg_->maxAreasInDoc}; - if (useExternSt == FtUseExternStatuses::No) { - mergeData = selecter.Process(std::move(dsl), inTransaction, ftSortType, - std::move(statuses.statuses), rdxCtx); - } else { - mergeData = selecter.Process(std::move(dsl), inTransaction, ftSortType, - std::move(statuses.statuses), rdxCtx); - } - break; - } - case FtFastConfig::Optimization::CPU: { - DataHolder* d = dynamic_cast*>(holder_.get()); - assertrx_throw(d); - Selecter selecter{*d, this->Fields().size(), fctx->NeedArea(), holder_->cfg_->maxAreasInDoc}; - if (useExternSt == FtUseExternStatuses::No) { - mergeData = selecter.Process(std::move(dsl), inTransaction, ftSortType, - std::move(statuses.statuses), rdxCtx); - } else { - mergeData = selecter.Process(std::move(dsl), inTransaction, ftSortType, - std::move(statuses.statuses), rdxCtx); - } - break; - } - default: - assertrx_throw(0); - } - +template +IdSet::Ptr FastIndexText::afterSelect(FtCtx& fctx, MergeType&& mergeData, FtSortType ftSortType, FtMergeStatuses&& statuses, + FtUseExternStatuses useExternSt) { // convert vids(uniq documents id) to ids (real ids) IdSet::Ptr mergedIds = make_intrusive>(); - auto& holder = *this->holder_; + auto& holder = *this->holder_; if (mergeData.empty()) { return mergedIds; } int cnt = 0; const double scalingFactor = mergeData.maxRank > 255 ? 255.0 / mergeData.maxRank : 1.0; const int minRelevancy = getConfig()->minRelevancy * 100 * scalingFactor; + size_t releventDocs = 0; switch (ftSortType) { case FtSortType::RankAndID: { @@ -233,14 +192,10 @@ IdSet::Ptr FastIndexText::Select(FtCtx::Ptr fctx, FtDSLQuery&& dsl, bool inTr case FtSortType::RankOnly: { for (auto& vid : mergeData) { auto& vdoc = holder.vdocs_[vid.id]; - if (!vdoc.keyEntry) { - continue; - } vid.proc *= scalingFactor; if (vid.proc <= minRelevancy) { break; } - assertrx_throw(!vdoc.keyEntry->Unsorted().empty()); cnt += vdoc.keyEntry->Sorted(0).size(); ++releventDocs; @@ -253,47 +208,47 @@ IdSet::Ptr FastIndexText::Select(FtCtx::Ptr fctx, FtDSLQuery&& dsl, bool inTr } mergedIds->reserve(cnt); - fctx->Reserve(cnt); - if (!fctx->NeedArea()) { + if constexpr (std::is_same_v) { if (useExternSt == FtUseExternStatuses::No) { appendMergedIds(mergeData, releventDocs, [&fctx, &mergedIds](IdSetCRef::iterator ebegin, IdSetCRef::iterator eend, const MergeInfo& vid) { - fctx->Add(ebegin, eend, vid.proc); + fctx.Add(ebegin, eend, vid.proc); mergedIds->Append(ebegin, eend, IdSet::Unordered); }); } else { appendMergedIds(mergeData, releventDocs, [&fctx, &mergedIds, &statuses](IdSetCRef::iterator ebegin, IdSetCRef::iterator eend, const MergeInfo& vid) { - fctx->Add(ebegin, eend, vid.proc, statuses.rowIds); + fctx.Add(ebegin, eend, vid.proc, statuses.rowIds); mergedIds->Append(ebegin, eend, statuses.rowIds, IdSet::Unordered); }); } - } else { + } else if constexpr (std::is_same_v, MergeType> || std::is_same_v, MergeType>) { if (useExternSt == FtUseExternStatuses::No) { appendMergedIds(mergeData, releventDocs, [&fctx, &mergedIds, &mergeData](IdSetCRef::iterator ebegin, IdSetCRef::iterator eend, const MergeInfo& vid) { - assertrx_throw(vid.areaIndex != std::numeric_limits::max()); - fctx->Add(ebegin, eend, vid.proc, std::move(mergeData.vectorAreas[vid.areaIndex])); + fctx.Add(ebegin, eend, vid.proc, std::move(mergeData.vectorAreas[vid.areaIndex])); mergedIds->Append(ebegin, eend, IdSet::Unordered); }); + } else { appendMergedIds( mergeData, releventDocs, - [&fctx, &mergedIds, &mergeData, &statuses](IdSetCRef::iterator ebegin, IdSetCRef::iterator eend, const MergeInfo& vid) { - assertrx_throw(vid.areaIndex != std::numeric_limits::max()); - fctx->Add(ebegin, eend, vid.proc, statuses.rowIds, std::move(mergeData.vectorAreas[vid.areaIndex])); + [&fctx, &mergedIds, &statuses, &mergeData](IdSetCRef::iterator ebegin, IdSetCRef::iterator eend, const MergeInfo& vid) { + fctx.Add(ebegin, eend, vid.proc, statuses.rowIds, std::move(mergeData.vectorAreas[vid.areaIndex])); mergedIds->Append(ebegin, eend, statuses.rowIds, IdSet::Unordered); }); } + } else { + static_assert(!sizeof(MergeType), "incorrect MergeType"); } + if rx_unlikely (getConfig()->logLevel >= LogInfo) { logPrintf(LogInfo, "Total merge out: %d ids", mergedIds->size()); - std::string str; - for (size_t i = 0; i < fctx->Size();) { + for (size_t i = 0; i < fctx.Size();) { size_t j = i; - for (; j < fctx->Size() && fctx->Proc(i) == fctx->Proc(j); j++); - str += std::to_string(fctx->Proc(i)) + "%"; + for (; j < fctx.Size() && fctx.Proc(i) == fctx.Proc(j); j++); + str += std::to_string(fctx.Proc(i)) + "%"; if (j - i > 1) { str += "("; str += std::to_string(j - i); @@ -302,9 +257,9 @@ IdSet::Ptr FastIndexText::Select(FtCtx::Ptr fctx, FtDSLQuery&& dsl, bool inTr str += " "; i = j; } - logPrintf(LogInfo, "Relevancy(%d): %s", fctx->Size(), str); + logPrintf(LogInfo, "Relevancy(%d): %s", fctx.Size(), str); } - assertrx_throw(mergedIds->size() == fctx->Size()); + assertrx_throw(mergedIds->size() == fctx.Size()); if (ftSortType == FtSortType::RankAndID) { std::vector sortIds; size_t nItems = mergedIds->size(); @@ -312,7 +267,7 @@ IdSet::Ptr FastIndexText::Select(FtCtx::Ptr fctx, FtDSLQuery&& dsl, bool inTr for (size_t i = 0; i < nItems; i++) { sortIds.emplace_back(i); } - std::vector& proc = fctx->GetData()->proc_; + std::vector& proc = fctx.GetData()->proc; boost::sort::pdqsort(sortIds.begin(), sortIds.end(), [&proc, mergedIds](size_t i1, size_t i2) { int p1 = proc[i1]; int p2 = proc[i2]; @@ -345,6 +300,74 @@ IdSet::Ptr FastIndexText::Select(FtCtx::Ptr fctx, FtDSLQuery&& dsl, bool inTr } return mergedIds; } + +template +template +IdSet::Ptr FastIndexText::applyCtxTypeAndSelect(DataHolder* d, const BaseFunctionCtx::Ptr& bctx, FtDSLQuery&& dsl, + bool inTransaction, FtSortType ftSortType, FtMergeStatuses&& statuses, + FtUseExternStatuses useExternSt, const RdxContext& rdxCtx) { + Selecter selecter{*d, this->Fields().size(), holder_->cfg_->maxAreasInDoc}; + intrusive_ptr fctx = static_ctx_pointer_cast(bctx); + assertrx_throw(fctx); + fctx->SetExtraWordSymbols(this->getConfig()->extraWordSymbols); + fctx->SetWordPosition(true); + + switch (bctx->type) { + case BaseFunctionCtx::CtxType::kFtCtx: { + MergeDataBase mergeData = selecter.template Process( + std::move(dsl), inTransaction, ftSortType, std::move(statuses.statuses), rdxCtx); + return afterSelect(*fctx.get(), std::move(mergeData), ftSortType, std::move(statuses), useExternSt); + } + case BaseFunctionCtx::CtxType::kFtArea: { + MergeData mergeData = selecter.template Process>( + std::move(dsl), inTransaction, ftSortType, std::move(statuses.statuses), rdxCtx); + return afterSelect(*fctx.get(), std::move(mergeData), ftSortType, std::move(statuses), useExternSt); + } + case BaseFunctionCtx::CtxType::kFtAreaDebug: { + MergeData mergeData = selecter.template Process>( + std::move(dsl), inTransaction, ftSortType, std::move(statuses.statuses), rdxCtx); + return afterSelect(*fctx.get(), std::move(mergeData), ftSortType, std::move(statuses), useExternSt); + } + default: + throw_assert(false); + } +} + +template +template +IdSet::Ptr FastIndexText::applyOptimizationAndSelect(DataHolder* d, BaseFunctionCtx::Ptr bctx, FtDSLQuery&& dsl, + bool inTransaction, FtSortType ftSortType, FtMergeStatuses&& statuses, + FtUseExternStatuses useExternSt, const RdxContext& rdxCtx) { + if (useExternSt == FtUseExternStatuses::Yes) { + return applyCtxTypeAndSelect(d, std::move(bctx), std::move(dsl), inTransaction, ftSortType, + std::move(statuses), useExternSt, rdxCtx); + } else { + return applyCtxTypeAndSelect(d, std::move(bctx), std::move(dsl), inTransaction, ftSortType, + std::move(statuses), useExternSt, rdxCtx); + } +} + +template +IdSet::Ptr FastIndexText::Select(FtCtx::Ptr bctx, FtDSLQuery&& dsl, bool inTransaction, FtSortType ftSortType, + FtMergeStatuses&& statuses, FtUseExternStatuses useExternSt, const RdxContext& rdxCtx) { + switch (holder_->cfg_->optimization) { + case FtFastConfig::Optimization::Memory: { + DataHolder* d = dynamic_cast*>(holder_.get()); + assertrx_throw(d); + return applyOptimizationAndSelect(d, bctx, std::move(dsl), inTransaction, ftSortType, std::move(statuses), + useExternSt, rdxCtx); + } + case FtFastConfig::Optimization::CPU: { + DataHolder* d = dynamic_cast*>(holder_.get()); + assertrx_throw(d); + return applyOptimizationAndSelect(d, bctx, std::move(dsl), inTransaction, ftSortType, std::move(statuses), + useExternSt, rdxCtx); + } + default: + throw_assert(false); + } +} + template void FastIndexText::commitFulltextImpl() { try { @@ -431,15 +454,15 @@ void FastIndexText::buildVdocs(Container& data) { } else { doc = it; } - doc->second.SetVDocID(vdocs.size()); vdocsTexts.emplace_back(gt.getDocFields(doc->first, bufStrs)); - #ifdef REINDEX_FT_EXTRA_DEBUG std::string text(vdocsTexts.back()[0].first); vdocs.push_back({(text.length() > 48) ? text.substr(0, 48) + "..." : text, doc->second.get(), {}, {}}); #else vdocs.push_back({doc->second.get(), {}, {}}); #endif + // Set VDocID after actual doc emplacing + doc->second.SetVDocID(vdocs.size() - 1); if rx_unlikely (getConfig()->logLevel <= LogInfo) { for (auto& f : vdocsTexts.back()) { @@ -453,16 +476,13 @@ void FastIndexText::buildVdocs(Container& data) { } template -template -RX_ALWAYS_INLINE void FastIndexText::appendMergedIds(MergeData& mergeData, size_t releventDocs, F&& appender) { +template +RX_ALWAYS_INLINE void FastIndexText::appendMergedIds(MergeType& mergeData, size_t releventDocs, F&& appender) { auto& holder = *this->holder_; - for (size_t i = 0; i < releventDocs;) { + for (size_t i = 0; i < releventDocs; i++) { auto& vid = mergeData[i]; auto& vdoc = holder.vdocs_[vid.id]; - if (vdoc.keyEntry) { - appender(vdoc.keyEntry->Sorted(0).begin(), vdoc.keyEntry->Sorted(0).end(), vid); - i++; - } + appender(vdoc.keyEntry->Sorted(0).begin(), vdoc.keyEntry->Sorted(0).end(), vid); } } diff --git a/cpp_src/core/index/indextext/fastindextext.h b/cpp_src/core/index/indextext/fastindextext.h index 8e902d945..68c3afe29 100644 --- a/cpp_src/core/index/indextext/fastindextext.h +++ b/cpp_src/core/index/indextext/fastindextext.h @@ -7,8 +7,6 @@ namespace reindexer { -struct MergeData; - template class FastIndexText : public IndexText { using Base = IndexText; @@ -32,8 +30,9 @@ class FastIndexText : public IndexText { // Creates uncommited copy return std::make_unique>(*this); } - IdSet::Ptr Select(FtCtx::Ptr fctx, FtDSLQuery&& dsl, bool inTransactionbool, FtSortType ftSortType, FtMergeStatuses&&, - FtUseExternStatuses, const RdxContext&) override final; + IdSet::Ptr Select(FtCtx::Ptr ctx, FtDSLQuery&& dsl, bool inTransaction, FtSortType ftSortType, FtMergeStatuses&&, FtUseExternStatuses, + const RdxContext&) override final; + IndexMemStat GetMemStat(const RdxContext&) override final; Variant Upsert(const Variant& key, IdType id, bool& clearCache) override final; void Delete(const Variant& key, IdType id, StringsHolder&, bool& clearCache) override final; @@ -47,16 +46,30 @@ class FastIndexText : public IndexText { bool EnablePreselectBeforeFt() const override final { return getConfig()->enablePreselectBeforeFt; } private: + template + IdSet::Ptr afterSelect(FtCtx& fctx, MergeType&& mergeData, FtSortType ftSortType, FtMergeStatuses&& statuses, FtUseExternStatuses); + + template + IdSet::Ptr applyOptimizationAndSelect(DataHolder* d, BaseFunctionCtx::Ptr bctx, FtDSLQuery&& dsl, bool inTransaction, + FtSortType ftSortType, FtMergeStatuses&& statuses, FtUseExternStatuses, const RdxContext& rdxCtx); + + template + IdSet::Ptr applyCtxTypeAndSelect(DataHolder* d, const BaseFunctionCtx::Ptr& bctx, FtDSLQuery&& dsl, bool inTransaction, + FtSortType ftSortType, FtMergeStatuses&& statuses, FtUseExternStatuses useExternSt, + const RdxContext& rdxCtx); + +protected: void commitFulltextImpl() override final; FtFastConfig* getConfig() const noexcept { return dynamic_cast(this->cfg_.get()); } void initConfig(const FtFastConfig* = nullptr); void initHolder(FtFastConfig&); template void buildVdocs(Data& data); - template - void appendMergedIds(MergeData& merged, size_t releventDocs, F&& appender); - - MergeData::iterator unstableRemoveIf(MergeData& md, const int minRelevancy, double scalingFactor, size_t& releventDocs, int& cnt); + template + void appendMergedIds(MergeType& merged, size_t releventDocs, F&& appender); + template + typename MergeType::iterator unstableRemoveIf(MergeType& md, const int minRelevancy, double scalingFactor, size_t& releventDocs, + int& cnt); std::unique_ptr holder_; }; diff --git a/cpp_src/core/index/indextext/fieldsgetter.h b/cpp_src/core/index/indextext/fieldsgetter.h index 300fe4cdc..bce1e0579 100644 --- a/cpp_src/core/index/indextext/fieldsgetter.h +++ b/cpp_src/core/index/indextext/fieldsgetter.h @@ -45,7 +45,7 @@ class FieldsGetter { } else { const std::string_view stringRef(kref); if (rx_likely(!utf8::is_valid(stringRef.data(), stringRef.data() + stringRef.size()))) { - throw Error(errParams, "Invalid UTF8 string in FullTextindex"); + throw Error(errParams, "Invalid UTF8 string in FullText index"); } ret.emplace_back(stringRef, fieldPos); } diff --git a/cpp_src/core/index/indextext/fuzzyindextext.cc b/cpp_src/core/index/indextext/fuzzyindextext.cc index 148db2e0c..908bec1e3 100644 --- a/cpp_src/core/index/indextext/fuzzyindextext.cc +++ b/cpp_src/core/index/indextext/fuzzyindextext.cc @@ -5,7 +5,8 @@ namespace reindexer { template -IdSet::Ptr FuzzyIndexText::Select(FtCtx::Ptr fctx, FtDSLQuery&& dsl, bool inTransaction, FtSortType ftSortType, FtMergeStatuses&&, + +IdSet::Ptr FuzzyIndexText::Select(FtCtx::Ptr bctx, FtDSLQuery&& dsl, bool inTransaction, FtSortType ftSortType, FtMergeStatuses&&, FtUseExternStatuses withExternSt, const RdxContext& rdxCtx) { assertrx_throw(withExternSt == FtUseExternStatuses::No); (void)ftSortType; @@ -15,6 +16,7 @@ IdSet::Ptr FuzzyIndexText::Select(FtCtx::Ptr fctx, FtDSLQuery&& dsl, bool inT auto mergedIds = make_intrusive>(); mergedIds->reserve(result.data_->size() * 2); + intrusive_ptr fctx = static_ctx_pointer_cast(bctx); fctx->Reserve(result.data_->size() * 2); double coof = 1; if (result.max_proc_ > 100) { diff --git a/cpp_src/core/index/indextext/fuzzyindextext.h b/cpp_src/core/index/indextext/fuzzyindextext.h index d92a0a210..6459025a6 100644 --- a/cpp_src/core/index/indextext/fuzzyindextext.h +++ b/cpp_src/core/index/indextext/fuzzyindextext.h @@ -22,9 +22,10 @@ class FuzzyIndexText : public IndexText { assertrx(0); abort(); } + std::unique_ptr Clone() const override final { return std::make_unique>(*this); } - IdSet::Ptr Select(FtCtx::Ptr fctx, FtDSLQuery&& dsl, bool inTransaction, FtSortType ftSortType, FtMergeStatuses&&, FtUseExternStatuses, - const RdxContext&) override final; + IdSet::Ptr Select(FtCtx::Ptr fctx, FtDSLQuery&& dsl, bool inTransaction, FtSortType ftSortType, FtMergeStatuses&&, + FtUseExternStatuses withExternSt, const RdxContext&) override final; Variant Upsert(const Variant& key, IdType id, bool& clearCache) override final { this->isBuilt_ = false; return Base::Upsert(key, id, clearCache); diff --git a/cpp_src/core/index/indextext/indextext.cc b/cpp_src/core/index/indextext/indextext.cc index 695456a7e..e1e5db9c0 100644 --- a/cpp_src/core/index/indextext/indextext.cc +++ b/cpp_src/core/index/indextext/indextext.cc @@ -71,16 +71,6 @@ void IndexText::ReconfigureCache(const NamespaceCacheConfigData& cacheCfg) { Base::ReconfigureCache(cacheCfg); } -template -FtCtx::Ptr IndexText::prepareFtCtx(const BaseFunctionCtx::Ptr& ctx) { - FtCtx::Ptr ftctx = reindexer::static_ctx_pointer_cast(ctx); - if rx_unlikely (!ftctx) { - throw Error(errParams, "Full text index (%s) may not be used without context", Index::Name()); - } - ftctx->PrepareAreas(ftFields_, this->name_); - return ftctx; -} - template void IndexText::build(const RdxContext& rdxCtx) { smart_lock lck(mtx_, rdxCtx); @@ -103,7 +93,6 @@ SelectKeyResults IndexText::SelectKey(const VariantArray& keys, CondType cond throw Error(errParams, "Full text index (%s) support only EQ or SET condition with 1 or 2 parameter", Index::Name()); } - FtCtx::Ptr ftctx = prepareFtCtx(ctx); auto mergeStatuses = this->GetFtMergeStatuses(rdxCtx); bool needPutCache = false; IdSetCacheKey ckey{keys, condition, 0}; @@ -111,23 +100,26 @@ SelectKeyResults IndexText::SelectKey(const VariantArray& keys, CondType cond if (cache_ft.valid) { if (!cache_ft.val.ids) { needPutCache = true; - } else if (ftctx->NeedArea() && (!cache_ft.val.ctx || !cache_ft.val.ctx->NeedArea())) { + } else if (ctx->type == BaseFunctionCtx::CtxType::kFtArea && + (!cache_ft.val.ctx || !(cache_ft.val.ctx->type == BaseFunctionCtx::CtxType::kFtArea))) { needPutCache = true; } else { - return resultFromCache(keys, std::move(cache_ft), ftctx); + return resultFromCache(keys, std::move(cache_ft), ctx); } } + return doSelectKey(keys, needPutCache ? std::optional{std::move(ckey)} : std::nullopt, std::move(mergeStatuses), - FtUseExternStatuses::No, opts.inTransaction, FtSortType(opts.ftSortType), std::move(ftctx), rdxCtx); + FtUseExternStatuses::No, opts.inTransaction, FtSortType(opts.ftSortType), ctx, rdxCtx); } template -SelectKeyResults IndexText::resultFromCache(const VariantArray& keys, FtIdSetCache::Iterator&& it, FtCtx::Ptr& ftctx) { +SelectKeyResults IndexText::resultFromCache(const VariantArray& keys, FtIdSetCache::Iterator&& it, const BaseFunctionCtx::Ptr& ctx) { if rx_unlikely (cfg_->logLevel >= LogInfo) { logPrintf(LogInfo, "Get search results for '%s' in '%s' from cache", keys[0].As(), this->payloadType_ ? this->payloadType_->Name() : ""); } assertrx(it.val.ctx); + FtCtx::Ptr ftctx = static_ctx_pointer_cast(ctx); ftctx->SetData(std::move(it.val.ctx)); return SelectKeyResult{{SingleSelectKeyResult{std::move(it.val.ids)}}}; } @@ -135,7 +127,7 @@ SelectKeyResults IndexText::resultFromCache(const VariantArray& keys, FtIdSet template SelectKeyResults IndexText::doSelectKey(const VariantArray& keys, const std::optional& ckey, FtMergeStatuses&& mergeStatuses, FtUseExternStatuses useExternSt, bool inTransaction, - FtSortType ftSortType, FtCtx::Ptr ftctx, const RdxContext& rdxCtx) { + FtSortType ftSortType, const BaseFunctionCtx::Ptr& bctx, const RdxContext& rdxCtx) { if rx_unlikely (cfg_->logLevel >= LogInfo) { logPrintf(LogInfo, "Searching for '%s' in '%s' %s", keys[0].As(), this->payloadType_ ? this->payloadType_->Name() : "", ckey ? "(will cache)" : ""); @@ -145,36 +137,40 @@ SelectKeyResults IndexText::doSelectKey(const VariantArray& keys, const std:: FtDSLQuery dsl(this->ftFields_, this->cfg_->stopWords, this->cfg_->extraWordSymbols); dsl.parse(keys[0].As()); - IdSet::Ptr mergedIds = Select(ftctx, std::move(dsl), inTransaction, ftSortType, std::move(mergeStatuses), useExternSt, rdxCtx); + auto ftCtx = static_ctx_pointer_cast(bctx); + IdSet::Ptr mergedIds = Select(ftCtx, std::move(dsl), inTransaction, ftSortType, std::move(mergeStatuses), useExternSt, rdxCtx); SelectKeyResult res; if (mergedIds) { + auto ftCtxDataBase = ftCtx->GetData(); bool need_put = (useExternSt == FtUseExternStatuses::No) && ckey.has_value(); - if (ftctx->NeedArea() && need_put && mergedIds->size()) { + // count the number of Areas and determine whether the request should be cached + if (bctx->type == BaseFunctionCtx::CtxType::kFtArea && need_put && mergedIds->size()) { auto config = dynamic_cast(cfg_.get()); + auto ftCtxDataArea = static_ctx_pointer_cast>(ftCtxDataBase); + if (config && config->maxTotalAreasToCache >= 0) { - auto& d = *ftctx->GetData(); size_t totalAreas = 0; - assertrx_throw(d.holders_.has_value()); - for (auto& area : d.holders_.value()) { - totalAreas += d.area_[area.second].GetAreasCount(); + assertrx_throw(ftCtxDataArea->holders.has_value()); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + for (auto& area : ftCtxDataArea->holders.value()) { + totalAreas += ftCtxDataArea->area[area.second].GetAreasCount(); } + if (totalAreas > unsigned(config->maxTotalAreasToCache)) { need_put = false; } } - } - if (need_put && mergedIds->size()) { - // This areas will be shared via cache, so lazy commit may race - auto dPtr = ftctx->GetData(); - auto& d = *dPtr; - if (d.holders_.has_value()) { - for (auto& area : d.holders_.value()) { - if (auto& aData = d.area_[area.second]; !aData.IsCommited()) { + if (need_put && ftCtxDataArea->holders.has_value()) { + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + for (auto& area : ftCtxDataArea->holders.value()) { + if (auto& aData = ftCtxDataArea->area[area.second]; !aData.IsCommited()) { aData.Commit(); } } } - cache_ft_->Put(*ckey, FtIdSetCacheVal{IdSet::Ptr(mergedIds), std::move(dPtr)}); + } + if (need_put && mergedIds->size()) { + cache_ft_->Put(*ckey, FtIdSetCacheVal{IdSet::Ptr(mergedIds), std::move(ftCtxDataBase)}); } res.emplace_back(std::move(mergedIds)); @@ -190,7 +186,7 @@ SelectKeyResults IndexText::SelectKey(const VariantArray& keys, CondType cond throw Error(errParams, "Full text index (%s) support only EQ or SET condition with 1 or 2 parameter", Index::Name()); } return doSelectKey(keys, std::nullopt, std::move(preselect), FtUseExternStatuses::Yes, opts.inTransaction, FtSortType(opts.ftSortType), - prepareFtCtx(ctx), rdxCtx); + ctx, rdxCtx); } template diff --git a/cpp_src/core/index/indextext/indextext.h b/cpp_src/core/index/indextext/indextext.h index 52b094da8..3a0af5a12 100644 --- a/cpp_src/core/index/indextext/indextext.h +++ b/cpp_src/core/index/indextext/indextext.h @@ -33,8 +33,9 @@ class IndexText : public IndexUnordered { SelectKeyResults SelectKey(const VariantArray& keys, CondType, Index::SelectOpts, const BaseFunctionCtx::Ptr&, FtPreselectT&&, const RdxContext&) override; void UpdateSortedIds(const UpdateSortedContext&) override {} - virtual IdSet::Ptr Select(FtCtx::Ptr fctx, FtDSLQuery&& dsl, bool inTransaction, FtSortType ftSortType, FtMergeStatuses&&, + virtual IdSet::Ptr Select(FtCtx::Ptr ctx, FtDSLQuery&& dsl, bool inTransaction, FtSortType ftSortType, FtMergeStatuses&&, FtUseExternStatuses, const RdxContext&) = 0; + void SetOpts(const IndexOpts& opts) override; void Commit() override final { // Do nothing @@ -65,10 +66,11 @@ class IndexText : public IndexUnordered { using Mutex = MarkedMutex; virtual void commitFulltextImpl() = 0; - FtCtx::Ptr prepareFtCtx(const BaseFunctionCtx::Ptr&); SelectKeyResults doSelectKey(const VariantArray& keys, const std::optional&, FtMergeStatuses&&, - FtUseExternStatuses useExternSt, bool inTransaction, FtSortType ftSortType, FtCtx::Ptr, const RdxContext&); - SelectKeyResults resultFromCache(const VariantArray& keys, FtIdSetCache::Iterator&&, FtCtx::Ptr&); + FtUseExternStatuses useExternSt, bool inTransaction, FtSortType ftSortType, + const BaseFunctionCtx::Ptr& ctx, const RdxContext&); + + SelectKeyResults resultFromCache(const VariantArray& keys, FtIdSetCache::Iterator&&, const BaseFunctionCtx::Ptr&); void build(const RdxContext& rdxCtx); void initSearchers(); diff --git a/cpp_src/core/itemmodifier.h b/cpp_src/core/itemmodifier.h index 9cd09ab6d..003e4ff22 100644 --- a/cpp_src/core/itemmodifier.h +++ b/cpp_src/core/itemmodifier.h @@ -53,7 +53,7 @@ class ItemModifier { data_.reserve(DefaultCJsonSize); } data_.assign(str.begin(), str.end()); - cjson_ = std::string_view(&data_[0], str.size()); + cjson_ = !str.empty() ? std::string_view(&data_[0], str.size()) : std::string_view(); } p_string Get() const { return p_string(&cjson_); } void Reset() { cjson_ = {nullptr, 0}; } diff --git a/cpp_src/core/keyvalue/variant.cc b/cpp_src/core/keyvalue/variant.cc index 5005ef5dd..9e645d481 100644 --- a/cpp_src/core/keyvalue/variant.cc +++ b/cpp_src/core/keyvalue/variant.cc @@ -520,31 +520,31 @@ class Comparator { return compare(v1_.As(), v2_.As()); } RX_ALWAYS_INLINE ComparationResult operator()(KeyValueType::Bool, KeyValueType::Int) const noexcept { - return compare(v1_.As(), v2_.As()); + return compare(int(v1_.As()), v2_.As()); } RX_ALWAYS_INLINE ComparationResult operator()(KeyValueType::Bool, KeyValueType::Int64) const noexcept { - return compare(v1_.As(), v2_.As()); + return compare(int64_t(v1_.As()), v2_.As()); } RX_ALWAYS_INLINE ComparationResult operator()(KeyValueType::Bool, KeyValueType::Double) const noexcept { - return compare(v1_.As(), v2_.As()); + return compare(double(v1_.As()), v2_.As()); } RX_ALWAYS_INLINE ComparationResult operator()(KeyValueType::Int, KeyValueType::Bool) const noexcept { - return compare(v1_.As(), v2_.As()); + return compare(v1_.As(), int(v2_.As())); } RX_ALWAYS_INLINE ComparationResult operator()(KeyValueType::Int, KeyValueType::Int) const noexcept { return compare(v1_.As(), v2_.As()); } RX_ALWAYS_INLINE ComparationResult operator()(KeyValueType::Int, KeyValueType::Int64) const noexcept { - return compare(v1_.As(), v2_.As()); + return compare(int64_t(v1_.As()), v2_.As()); } RX_ALWAYS_INLINE ComparationResult operator()(KeyValueType::Int, KeyValueType::Double) const noexcept { return compare(v1_.As(), v2_.As()); } RX_ALWAYS_INLINE ComparationResult operator()(KeyValueType::Int64, KeyValueType::Bool) const noexcept { - return compare(v1_.As(), v2_.As()); + return compare(v1_.As(), int64_t(v2_.As())); } RX_ALWAYS_INLINE ComparationResult operator()(KeyValueType::Int64, KeyValueType::Int) const noexcept { - return compare(v1_.As(), v2_.As()); + return compare(v1_.As(), int64_t(v2_.As())); } RX_ALWAYS_INLINE ComparationResult operator()(KeyValueType::Int64, KeyValueType::Int64) const noexcept { return compare(v1_.As(), v2_.As()); @@ -553,7 +553,7 @@ class Comparator { return compare(v1_.As(), v2_.As()); } RX_ALWAYS_INLINE ComparationResult operator()(KeyValueType::Double, KeyValueType::Bool) const noexcept { - return compare(v1_.As(), v2_.As()); + return compare(v1_.As(), double(v2_.As())); } RX_ALWAYS_INLINE ComparationResult operator()(KeyValueType::Double, KeyValueType::Int) const noexcept { return compare(v1_.As(), v2_.As()); diff --git a/cpp_src/core/keyvalue/variant.h b/cpp_src/core/keyvalue/variant.h index 22c586620..9c147f2bb 100644 --- a/cpp_src/core/keyvalue/variant.h +++ b/cpp_src/core/keyvalue/variant.h @@ -43,6 +43,7 @@ class Variant { explicit Variant(std::string&& v) : variant_{0, 1, KeyValueType::String{}} { new (cast()) key_string(make_key_string(std::move(v))); } + explicit Variant(std::string_view v) : variant_{0, 1, KeyValueType::String{}} { new (cast()) key_string(make_key_string(v)); } explicit Variant(const key_string& v) noexcept : variant_{0, 1, KeyValueType::String{}} { new (cast()) key_string(v); } explicit Variant(key_string&& v) noexcept : variant_{0, 1, KeyValueType::String{}} { new (cast()) key_string(std::move(v)); } explicit Variant(const PayloadValue& v) noexcept : variant_{0, 1, KeyValueType::Composite{}} { new (cast()) PayloadValue(v); } diff --git a/cpp_src/core/lsn.h b/cpp_src/core/lsn.h index 75e1fbdb7..eb1c51941 100644 --- a/cpp_src/core/lsn.h +++ b/cpp_src/core/lsn.h @@ -38,6 +38,9 @@ struct lsn_t { lsn_t(int64_t counter, int16_t server) { validateCounter(counter); validateServerId(server); + if (counter < 0) { + counter = kDefaultCounter; + } payload_ = server * kMaxCounter + counter; } explicit operator int64_t() const { return payload_; } @@ -53,6 +56,9 @@ struct lsn_t { int64_t SetCounter(int64_t counter) { validateCounter(counter); payload_ = Server() * kMaxCounter + counter; + if (counter < 0) { + counter = kDefaultCounter; + } return payload_; } int64_t Counter() const noexcept { return payload_ % kMaxCounter; } diff --git a/cpp_src/core/namespace/itemsloader.cc b/cpp_src/core/namespace/itemsloader.cc index 1a7f59b44..89795271b 100644 --- a/cpp_src/core/namespace/itemsloader.cc +++ b/cpp_src/core/namespace/itemsloader.cc @@ -57,7 +57,7 @@ void ItemsLoader::reading() { throw Error(errLogic, "Can't load data storage of '%s' - there are no PK fields in ns", ns_.name_); } if (dataSlice.size() < sizeof(int64_t)) { - lastErr = Error(errParseBin, "Not enougth data in data slice"); + lastErr = Error(errParseBin, "Not enough data in data slice"); logPrintf(LogTrace, "Error load item to '%s' from storage: '%s'", ns_.name_, lastErr.what()); ++errCount; continue; @@ -66,7 +66,7 @@ void ItemsLoader::reading() { // Read LSN int64_t lsn = *reinterpret_cast(dataSlice.data()); if (lsn < 0) { - lastErr = Error(errParseBin, "Ivalid LSN value: %d", lsn); + lastErr = Error(errParseBin, "Invalid LSN value: %d", lsn); logPrintf(LogTrace, "Error load item to '%s' from storage: '%s'", ns_.name_, lastErr.what()); ++errCount; continue; @@ -114,7 +114,7 @@ void ItemsLoader::reading() { continue; } item.impl.Value().SetLSN(int64_t(l)); - // Prealloc payload here, because reading|parsing thread is faster then index insertion thread + // Preallocate payload here, because reading|parsing thread is faster than index insertion thread item.preallocPl = PayloadValue(item.impl.GetConstPayload().RealSize()); lck.lock(); diff --git a/cpp_src/core/namespace/namespaceimpl.cc b/cpp_src/core/namespace/namespaceimpl.cc index f32901545..126e20eeb 100644 --- a/cpp_src/core/namespace/namespaceimpl.cc +++ b/cpp_src/core/namespace/namespaceimpl.cc @@ -3,7 +3,6 @@ #include #include #include "core/cjson/cjsondecoder.h" -// #include "core/cjson/defaultvaluecoder.h" #include "core/cjson/jsonbuilder.h" #include "core/cjson/uuid_recoders.h" #include "core/formatters/lsn_fmt.h" @@ -99,7 +98,7 @@ NamespaceImpl::NamespaceImpl(const NamespaceImpl& src, AsyncStorage::FullLockT& optimizationState_{NotOptimized}, strHolder_{makeStringsHolder()}, nsUpdateSortedContextMemory_{0}, - dbDestroyed_(false) { + dbDestroyed_{false} { for (auto& idxIt : src.indexes_) { indexes_.push_back(idxIt->Clone()); } @@ -111,23 +110,23 @@ NamespaceImpl::NamespaceImpl(const NamespaceImpl& src, AsyncStorage::FullLockT& NamespaceImpl::NamespaceImpl(const std::string& name, UpdatesObservers& observers) : intrusive_atomic_rc_base(), - indexes_(*this), - name_(name), - payloadType_(name), - tagsMatcher_(payloadType_), - enablePerfCounters_(false), - queryCountCache_( - std::make_unique(config_.cacheConfig.queryCountCacheSize, config_.cacheConfig.queryCountHitsToCache)), - joinCache_(std::make_unique(config_.cacheConfig.joinCacheSize, config_.cacheConfig.joinHitsToCache)), + indexes_{*this}, + name_{name}, + payloadType_{name}, + tagsMatcher_{payloadType_}, + enablePerfCounters_{false}, + queryCountCache_{ + std::make_unique(config_.cacheConfig.queryCountCacheSize, config_.cacheConfig.queryCountHitsToCache)}, + joinCache_{std::make_unique(config_.cacheConfig.joinCacheSize, config_.cacheConfig.joinHitsToCache)}, wal_(getWalSize(config_)), - observers_(&observers), + observers_{&observers}, lastSelectTime_{0}, cancelCommitCnt_{0}, lastUpdateTime_{0}, - nsIsLoading_(false), - serverIdChanged_(false), + nsIsLoading_{false}, + serverIdChanged_{false}, strHolder_{makeStringsHolder()}, - dbDestroyed_(false) { + dbDestroyed_{false} { logPrintf(LogTrace, "NamespaceImpl::NamespaceImpl (%s)", name_); FlagGuardT nsLoadingGuard(nsIsLoading_); items_.reserve(10000); @@ -392,7 +391,7 @@ class NamespaceImpl::RollBack_recreateCompositeIndexes final : private RollBackB private: NamespaceImpl& ns_; std::vector> indexes_; - size_t startIdx_; + size_t startIdx_{0}; }; template <> @@ -476,32 +475,11 @@ class NamespaceImpl::RollBack_updateItems final : private RollBackBase { NamespaceImpl& ns_; RollBack_recreateCompositeIndexes rollbacker_recreateCompositeIndexes_; std::vector> items_; - uint64_t dataHash_; - size_t itemsDataSize_; + uint64_t dataHash_{0}; + size_t itemsDataSize_{0}; std::unique_ptr tuple_; }; -std::vector NamespaceImpl::pickJsonPath(const PayloadFieldType& fld) { - const auto& paths = fld.JsonPaths(); - if (fld.IsArray()) { - std::vector result; - result.reserve(paths.size()); - for (const auto& path : paths) { - auto tags = tagsMatcher_.path2tag(path, false); - result.push_back(std::move(tags)); - // first without nested path - always (any, now last one found) - if ((result.size() > 1) && (result.back().size() == 1)) { - std::swap(result.front(), result.back()); - } - } - return result; - } - - assertrx_throw(paths.size() == 1); - auto tags = tagsMatcher_.path2tag(paths.front(), false); - return {std::move(tags)}; -} - template <> class NamespaceImpl::RollBack_updateItems { public: @@ -565,16 +543,6 @@ NamespaceImpl::RollBack_updateItems NamespaceImpl::updateItems(con recoder = std::make_unique(changedField); } } - // TODO: This logic must be reenabled after #1353. Now it's potentially unsafe - // else { - // const auto& indexToUpdate = indexes_[changedField]; - // if (!IsComposite(indexToUpdate->Type()) && !indexToUpdate->Opts().IsSparse()) { - // auto tagsNames = pickJsonPath(fld); - // if (!tagsNames.empty()) { - // recoder = std::make_unique(name_, fld, std::move(tagsNames), changedField); - // } - // } - // } } rollbacker.SaveTuple(); @@ -598,7 +566,6 @@ NamespaceImpl::RollBack_updateItems NamespaceImpl::updateItems(con ItemImpl oldItem(oldPlType, plCurr, tagsMatcher_); oldItem.Unsafe(true); newItem.FromCJSON(oldItem, recoder.get()); - const bool itemTupleUpdated = recoder && recoder->Reset(); PayloadValue plNew = oldValue.CopyTo(payloadType_, fieldChangeType == FieldChangeType::Add); plNew.SetLSN(plCurr.GetLSN()); @@ -650,17 +617,6 @@ NamespaceImpl::RollBack_updateItems NamespaceImpl::updateItems(con plCurr = std::move(plNew); repl_.dataHash ^= Payload(payloadType_, plCurr).GetHash(); itemsDataSize_ += plCurr.GetCapacity() + sizeof(PayloadValue::dataHeader); - - // update data in storage - if (itemTupleUpdated && storage_.IsValid()) { - pk.Reset(); - data.Reset(); - pk << kRxStorageItemPrefix; - Payload(payloadType_, plCurr).SerializeFields(pk, pkFields()); - data.PutUInt64(plCurr.GetLSN()); - newItem.GetCJSON(data); - storage_.Write(pk.Slice(), data.Slice()); - } } markUpdated(IndexOptimization::Partial); @@ -753,13 +709,15 @@ void NamespaceImpl::SetSchema(std::string_view schema, const RdxContext& ctx) { repl_.lastSelfLSN = lsn; } if (!repl_.temporary) { - WrSerializer wser; - wser.PutVarint(tagsMatcher_.version()); - wser.PutVarint(tagsMatcher_.stateToken()); - tagsMatcher_.serialize(wser); - // This record is matter for the online replication only - observers_->OnWALUpdate(LSNPair(lsn, ctx.fromReplication_ ? ctx.LSNs_.originLSN_ : lsn), name_, - WALRecord(WalTagsMatcher, wser.Slice())); + if (!ctx.IsInWalSync()) { + WrSerializer wser; + wser.PutVarint(tagsMatcher_.version()); + wser.PutVarint(tagsMatcher_.stateToken()); + tagsMatcher_.serialize(wser); + // This record is matter for the online replication only + observers_->OnWALUpdate(LSNPair(lsn, ctx.fromReplication_ ? ctx.LSNs_.originLSN_ : lsn), name_, + WALRecord(WalTagsMatcher, wser.Slice())); + } } } addToWAL(schema, WalSetSchema, ctx); @@ -1351,7 +1309,7 @@ int NamespaceImpl::getIndexByName(std::string_view index) const { } int NamespaceImpl::getIndexByNameOrJsonPath(std::string_view index) const { - int idx; + int idx = 0; if (tryGetIndexByName(index, idx)) { return idx; } @@ -1364,7 +1322,7 @@ int NamespaceImpl::getIndexByNameOrJsonPath(std::string_view index) const { } int NamespaceImpl::getScalarIndexByName(std::string_view index) const { - int idx; + int idx = 0; if (tryGetIndexByName(index, idx)) { if (idx < indexes_.firstCompositePos()) { return idx; @@ -1395,7 +1353,7 @@ bool NamespaceImpl::getIndexByNameOrJsonPath(std::string_view name, int& index) } bool NamespaceImpl::getScalarIndexByName(std::string_view name, int& index) const { - int idx; + int idx = 0; if (tryGetIndexByName(name, idx)) { if (idx < indexes_.firstCompositePos()) { index = idx; @@ -1531,8 +1489,10 @@ void NamespaceImpl::replicateItem(IdType itemId, const NsContext& ctx, bool stat ItemImpl item(payloadType_, pv, tagsMatcher_); std::string_view cjson = item.GetCJSON(false); if (!repl_.temporary) { - observers_->OnWALUpdate(LSNPair(lsn, ctx.rdxContext.fromReplication_ ? ctx.rdxContext.LSNs_.originLSN_ : lsn), name_, - WALRecord(WalItemModify, cjson, tagsMatcher_.version(), mode, ctx.inTransaction)); + if (!ctx.rdxContext.IsInWalSync()) { + observers_->OnWALUpdate(LSNPair(lsn, ctx.rdxContext.fromReplication_ ? ctx.rdxContext.LSNs_.originLSN_ : lsn), name_, + WALRecord(WalItemModify, cjson, tagsMatcher_.version(), mode, ctx.inTransaction)); + } } if (!ctx.rdxContext.fromReplication_) { setReplLSNs(LSNPair(lsn_t(), lsn)); @@ -1609,7 +1569,7 @@ void NamespaceImpl::doDelete(IdType id) { storage_.Remove(pk.Slice()); // erase last item - int field; + int field = 0; // erase from composite indexes auto indexesCacheCleaner{GetIndexesCacheCleaner()}; @@ -1763,7 +1723,9 @@ void NamespaceImpl::doTruncate(const NsContext& ctx) { } markUpdated(IndexOptimization::Full); if (!repl_.temporary) { - observers_->OnWALUpdate(LSNPair(lsn, ctx.rdxContext.fromReplication_ ? ctx.rdxContext.LSNs_.originLSN_ : lsn), name_, wrec); + if (!ctx.rdxContext.IsInWalSync()) { + observers_->OnWALUpdate(LSNPair(lsn, ctx.rdxContext.fromReplication_ ? ctx.rdxContext.LSNs_.originLSN_ : lsn), name_, wrec); + } } if (!ctx.rdxContext.fromReplication_) { setReplLSNs(LSNPair(lsn_t(), lsn)); @@ -1918,7 +1880,9 @@ void NamespaceImpl::CommitTransaction(Transaction& tx, QueryResults& result, NsC repl_.lastSelfLSN = lsn; } if (!repl_.temporary) { - observers_->OnWALUpdate(LSNPair(lsn, ctx.rdxContext.fromReplication_ ? ctx.rdxContext.LSNs_.originLSN_ : lsn), name_, initWrec); + if (!ctx.rdxContext.IsInWalSync()) { + observers_->OnWALUpdate(LSNPair(lsn, ctx.rdxContext.fromReplication_ ? ctx.rdxContext.LSNs_.originLSN_ : lsn), name_, initWrec); + } } AsyncStorage::AdviceGuardT storageAdvice; @@ -2054,12 +2018,6 @@ void NamespaceImpl::doUpsert(ItemImpl* ritem, IdType id, bool doUpdate) { plNew.Get(field, skrefs); } - if (index.Opts().GetCollateMode() == CollateUTF8) { - for (auto& key : skrefs) { - key.EnsureUTF8(); - } - } - // Check for update if (doUpdate) { if (isIndexSparse) { @@ -2229,6 +2187,22 @@ void NamespaceImpl::doModifyItem(Item& item, ItemModifyMode mode, const NsContex return; } + for (int field = 1, regularIndexes = indexes_.firstCompositePos(); field < regularIndexes; ++field) { + Index& index = *indexes_[field]; + if (index.Opts().GetCollateMode() == CollateUTF8 && index.KeyType().Is()) { + if (index.Opts().IsSparse()) { + assertrx(index.Fields().getTagsPathsLength() > 0); + newPl.GetByJsonPath(index.Fields().getTagsPath(0), skrefs, KeyValueType::String{}); + } else { + newPl.Get(field, skrefs); + } + + for (auto& key : skrefs) { + key.EnsureUTF8(); + } + } + } + IdType id = exists ? realItem.first : createItem(newPl.RealSize()); lsn_t lsn(wal_.Add(WALRecord(WalItemUpdate, id, ctx.inTransaction), exists ? lsn_t(items_[id].GetLSN()) : lsn_t()), serverId_); @@ -2251,8 +2225,7 @@ void NamespaceImpl::doModifyItem(Item& item, ItemModifyMode mode, const NsContex } if (!repl_.temporary) { - // not send row with fromReplication=true and originLSN_= empty - if (!ctx.rdxContext.fromReplication_ || !ctx.rdxContext.LSNs_.originLSN_.isEmpty()) { + if (!ctx.rdxContext.IsInWalSync()) { observers_->OnModifyItem(LSNPair(lsn, ctx.rdxContext.fromReplication_ ? ctx.rdxContext.LSNs_.originLSN_ : lsn), name_, item.impl_, mode, ctx.inTransaction); } @@ -2984,6 +2957,9 @@ void NamespaceImpl::removeExpiredItems(RdxActivityContext* ctx) { qr.AddNamespace(this, true); auto q = Query(name_).Where(index->Name(), CondLt, expirationThreshold); doDelete(q, qr, rdxCtx); + if (qr.Count()) { + logFmt(LogInfo, "{}: {} items were removed: TTL({}) has expired", name_, qr.Count(), index->Name()); + } } tryForceFlush(std::move(wlck)); } @@ -3025,12 +3001,14 @@ void NamespaceImpl::mergeTagsMatcher(const TagsMatcher& tm, const NsContext& ctx if (tagsMatcher_.isUpdated()) { const lsn_t lsn(wal_.Add(WALRecord(WalEmpty, 0, ctx.inTransaction)), serverId_); if (!repl_.temporary) { - WrSerializer ser; - ser.PutVarint(tagsMatcher_.version()); - ser.PutVarint(tagsMatcher_.stateToken()); - tagsMatcher_.serialize(ser); - observers_->OnWALUpdate(LSNPair(lsn, ctx.rdxContext.LSNs_.originLSN_), name_, - WALRecord(WalTagsMatcher, ser.Slice(), ctx.inTransaction)); + if (!ctx.rdxContext.IsInWalSync()) { + WrSerializer ser; + ser.PutVarint(tagsMatcher_.version()); + ser.PutVarint(tagsMatcher_.stateToken()); + tagsMatcher_.serialize(ser); + observers_->OnWALUpdate(LSNPair(lsn, ctx.rdxContext.LSNs_.originLSN_), name_, + WALRecord(WalTagsMatcher, ser.Slice(), ctx.inTransaction)); + } } } @@ -3228,8 +3206,7 @@ void NamespaceImpl::checkApplySlaveUpdate(bool fromReplication) { if (repl_.slaveMode && !repl_.replicatorEnabled) // readOnly { throw Error(errLogic, "Can't modify read only ns '%s'", name_); - } else if (repl_.slaveMode && repl_.replicatorEnabled) // slave - { + } else if (repl_.slaveMode && repl_.replicatorEnabled) { // slave if (!fromReplication) { logPrintf(LogTrace, "[repl:%s]:%d Can't modify slave ns '%s' repl_.slaveMode=%d repl_.replicatorenabled=%d fromReplication=%d", name_, serverId_, name_, repl_.slaveMode, repl_.replicatorEnabled, fromReplication); @@ -3237,8 +3214,7 @@ void NamespaceImpl::checkApplySlaveUpdate(bool fromReplication) { } else if (repl_.status == ReplicationState::Status::Fatal) { throw Error(errLogic, "Can't modify slave ns '%s', ns has fatal replication error: %s", name_, repl_.replError.what()); } - } else if (!repl_.slaveMode && !repl_.replicatorEnabled) // master - { + } else if (!repl_.slaveMode && !repl_.replicatorEnabled) { // master if (fromReplication) { throw Error(errLogic, "Can't modify master ns '%s' from replicator", name_); } else if (repl_.status == ReplicationState::Status::Fatal) { @@ -3354,10 +3330,19 @@ void NamespaceImpl::processWalRecord(const WALRecord& wrec, const RdxContext& ct repl_.lastSelfLSN = lsn; } if (item) { - item->setLSN(int64_t(lsn)); + // Cloning is required to avoid LSN modification in the QueryResult's/Snapshot's item + if (!item->impl_->RealValue().IsFree()) { + item->impl_->RealValue().Clone(); + item->impl_->RealValue().SetLSN(int64_t(lsn)); + } else if (!item->impl_->Value().IsFree()) { + item->impl_->Value().Clone(); + item->impl_->Value().SetLSN(int64_t(lsn)); + } } if (!repl_.temporary) { - observers_->OnWALUpdate(LSNPair(lsn, ctx.fromReplication_ ? ctx.LSNs_.originLSN_ : lsn), name_, wrec); + if (!ctx.IsInWalSync()) { + observers_->OnWALUpdate(LSNPair(lsn, ctx.fromReplication_ ? ctx.LSNs_.originLSN_ : lsn), name_, wrec); + } } if (!ctx.fromReplication_) { setReplLSNs(LSNPair(lsn_t(), lsn)); diff --git a/cpp_src/core/namespace/namespaceimpl.h b/cpp_src/core/namespace/namespaceimpl.h index 3f0a75824..2bd31dd74 100644 --- a/cpp_src/core/namespace/namespaceimpl.h +++ b/cpp_src/core/namespace/namespaceimpl.h @@ -488,7 +488,6 @@ class NamespaceImpl final : public intrusive_atomic_rc_base { // NOLINT(*perfor } size_t getWalSize(const NamespaceConfigData& cfg) const noexcept { return isSystem() ? int64_t(1) : std::max(cfg.walSize, int64_t(1)); } void clearNamespaceCaches(); - std::vector pickJsonPath(const PayloadFieldType& fld); PerfStatCounterMT updatePerfCounter_, selectPerfCounter_; std::atomic_bool enablePerfCounters_{false}; diff --git a/cpp_src/core/nsselecter/joinedselector.cc b/cpp_src/core/nsselecter/joinedselector.cc index 8ff29e42e..d726ae1f9 100644 --- a/cpp_src/core/nsselecter/joinedselector.cc +++ b/cpp_src/core/nsselecter/joinedselector.cc @@ -229,7 +229,7 @@ void JoinedSelector::AppendSelectIteratorOfJoinIndexData(SelectIteratorContainer [](const SelectIteratorContainer&) -> VariantArray { throw_as_assert; }}, preresult.payload); auto ctx = selectFnc ? selectFnc->CreateCtx(joinEntry.LeftIdxNo()) : BaseFunctionCtx::Ptr{}; - assertrx_throw(!ctx || ctx->type != BaseFunctionCtx::kFtCtx); + assertrx_throw(!ctx || ctx->type != BaseFunctionCtx::CtxType::kFtCtx); if (leftIndex->Opts().GetCollateMode() == CollateUTF8) { for (auto& key : values) { diff --git a/cpp_src/core/nsselecter/selectiteratorcontainer.cc b/cpp_src/core/nsselecter/selectiteratorcontainer.cc index dcdfe7428..a0194ecd7 100644 --- a/cpp_src/core/nsselecter/selectiteratorcontainer.cc +++ b/cpp_src/core/nsselecter/selectiteratorcontainer.cc @@ -309,7 +309,7 @@ SelectKeyResults SelectIteratorContainer::processQueryEntry(const QueryEntry& qe opts.inTransaction = ctx_->inTransaction; auto ctx = selectFnc ? selectFnc->CreateCtx(qe.IndexNo()) : BaseFunctionCtx::Ptr{}; - if (ctx && ctx->type == BaseFunctionCtx::kFtCtx) { + if (ctx) { ftCtx = reindexer::static_ctx_pointer_cast(ctx); } diff --git a/cpp_src/core/nsselecter/sortexpression.cc b/cpp_src/core/nsselecter/sortexpression.cc index 7acaa9d3e..d8523a680 100644 --- a/cpp_src/core/nsselecter/sortexpression.cc +++ b/cpp_src/core/nsselecter/sortexpression.cc @@ -64,11 +64,11 @@ VariantArray SortExpression::GetJoinedFieldValues(IdType rowId, const joins::Nam const std::vector& joinedSelectors, size_t nsIdx, std::string_view column, int index) { const auto& js = joinedSelectors[nsIdx]; - std::reference_wrapper pt = - std::visit(overloaded{[](const JoinPreResult::Values& values) noexcept { return std::cref(values.payloadType); }, - Restricted{}( - [&js](const auto&) noexcept { return std::cref(js.rightNs_->payloadType_); })}, - js.PreResult().payload); + std::reference_wrapper pt = std::visit( + overloaded{ + [](const JoinPreResult::Values& values) noexcept { return std::cref(values.payloadType); }, + Restricted{}([&js](const auto&) noexcept { return std::cref(js.rightNs_->payloadType_); })}, + js.PreResult().payload); const ConstPayload pv{pt, getJoinedValue(rowId, joinResults, joinedSelectors, nsIdx)}; VariantArray values; if (index == IndexValueType::SetByJsonPath) { @@ -156,11 +156,11 @@ double DistanceBetweenJoinedIndexes::GetValue(IdType rowId, const joins::Namespa double DistanceBetweenJoinedIndexesSameNs::GetValue(IdType rowId, const joins::NamespaceResults& joinResults, const std::vector& joinedSelectors) const { const auto& js = joinedSelectors[nsIdx]; - std::reference_wrapper pt = - std::visit(overloaded{[](const JoinPreResult::Values& values) noexcept { return std::cref(values.payloadType); }, - Restricted{}( - [&js](const auto&) noexcept { return std::cref(js.rightNs_->payloadType_); })}, - js.PreResult().payload); + std::reference_wrapper pt = std::visit( + overloaded{ + [](const JoinPreResult::Values& values) noexcept { return std::cref(values.payloadType); }, + Restricted{}([&js](const auto&) noexcept { return std::cref(js.rightNs_->payloadType_); })}, + js.PreResult().payload); const ConstPayload pv{pt, SortExpression::getJoinedValue(rowId, joinResults, joinedSelectors, nsIdx)}; TagsMatcher tm = std::visit(overloaded{[](const JoinPreResult::Values& values) noexcept { return std::cref(values.tagsMatcher); }, Restricted{}( diff --git a/cpp_src/core/payload/payloadiface.h b/cpp_src/core/payload/payloadiface.h index 672f3be04..b5629525e 100644 --- a/cpp_src/core/payload/payloadiface.h +++ b/cpp_src/core/payload/payloadiface.h @@ -84,7 +84,7 @@ class PayloadIface { template ::value>::type* = nullptr> void SetSingleElement(int field, const Variant& key); - // Set element or array by field index + // Set element or array by index path template ::value>::type* = nullptr> void Set(std::string_view field, const VariantArray& keys, bool append = false) { return Set(t_.FieldByName(field), keys, append); diff --git a/cpp_src/core/query/dsl/dslparser.cc b/cpp_src/core/query/dsl/dslparser.cc index 05a0b7ce4..f20bbb2ee 100644 --- a/cpp_src/core/query/dsl/dslparser.cc +++ b/cpp_src/core/query/dsl/dslparser.cc @@ -142,7 +142,7 @@ constexpr static auto kAggregationTypes = MakeFastStrMap({ {"count_cached", AggCountCached}, }); -// additionalfor parse field 'equation_positions' +// additional for parse field 'equation_positions' constexpr static auto kEquationPositionMap = MakeFastStrMap({{"positions", EqualPosition::Positions}}); // additional for 'Root::QueryType' field diff --git a/cpp_src/core/query/expressionevaluator.cc b/cpp_src/core/query/expressionevaluator.cc index 9dff39ede..b5369a8dc 100644 --- a/cpp_src/core/query/expressionevaluator.cc +++ b/cpp_src/core/query/expressionevaluator.cc @@ -55,21 +55,17 @@ ExpressionEvaluator::PrimaryToken ExpressionEvaluator::getPrimaryToken(tokenizer if rx_unlikely (parser.next_token().text() != ")"sv) { throw Error(errParams, "')' expected in arithmetical expression"); } - return {.value = val, .type = PrimaryToken::Type::Scalar}; + return {.value = Variant{val}, .type = PrimaryToken::Type::Scalar}; } else if (outTok.text() == "["sv) { captureArrayContent(parser); - return {.value = std::nullopt, .type = PrimaryToken::Type::Array}; + return {.value = Variant{}, .type = PrimaryToken::Type::Array}; } switch (outTok.type) { case TokenNumber: { try { - using double_conversion::StringToDoubleConverter; - static const StringToDoubleConverter converter{StringToDoubleConverter::NO_FLAGS, NAN, NAN, nullptr, nullptr}; - int countOfCharsParsedAsDouble; - return {.value = converter.StringToDouble(outTok.text_.data(), outTok.text_.size(), &countOfCharsParsedAsDouble), - .type = PrimaryToken::Type::Scalar}; + return {.value = getVariantFromToken(outTok), .type = PrimaryToken::Type::Scalar}; } catch (...) { - throw Error(errParams, "Unable to convert '%s' to double value", outTok.text()); + throw Error(errParams, "Unable to convert '%s' to numeric value", outTok.text()); } } case TokenName: @@ -78,7 +74,7 @@ ExpressionEvaluator::PrimaryToken ExpressionEvaluator::getPrimaryToken(tokenizer if (strAllowed == StringAllowed::Yes) { arrayValues_.MarkArray(); arrayValues_.emplace_back(token2kv(outTok, parser, CompositeAllowed::No, FieldAllowed::No)); - return {.value = std::nullopt, .type = PrimaryToken::Type::Array}; + return {.value = Variant{}, .type = PrimaryToken::Type::Array}; } else { throwUnexpectedTokenError(parser, outTok); } @@ -104,17 +100,17 @@ ExpressionEvaluator::PrimaryToken ExpressionEvaluator::handleTokenName(tokenizer arrayValues_.emplace_back(std::move(val)); } return (state_ == StateArrayConcat || fieldValues.size() != 1) - ? PrimaryToken{.value = std::nullopt, .type = PrimaryToken::Type::Array} + ? PrimaryToken{.value = Variant{}, .type = PrimaryToken::Type::Array} : type_.Field(field).Type().EvaluateOneOf( [this](OneOf) -> PrimaryToken { - return {.value = arrayValues_.back().As(), .type = PrimaryToken::Type::Array}; + return {.value = arrayValues_.back(), .type = PrimaryToken::Type::Array}; }, [&, this](OneOf) -> PrimaryToken { if rx_unlikely (nonIntAllowed == NonIntegralAllowed::No && state_ != StateArrayConcat && parser.peek_token(tokenizer::flags::treat_sign_as_token).text() != "|"sv) { throw Error(errParams, kWrongFieldTypeError, outTok.text()); } - return {.value = std::nullopt, .type = PrimaryToken::Type::Array}; + return {.value = Variant{}, .type = PrimaryToken::Type::Array}; }, [](OneOf) noexcept -> PrimaryToken { @@ -128,7 +124,7 @@ ExpressionEvaluator::PrimaryToken ExpressionEvaluator::handleTokenName(tokenizer if rx_unlikely (fieldValues.empty()) { throw Error(errParams, "Calculating value of an empty field is impossible: '%s'", outTok.text()); } - return {.value = fieldValues.front().As(), .type = PrimaryToken::Type::Scalar}; + return {.value = fieldValues.front(), .type = PrimaryToken::Type::Scalar}; }, [&, this](OneOf) -> PrimaryToken { throwUnexpectedTokenError(parser, outTok); @@ -138,20 +134,20 @@ ExpressionEvaluator::PrimaryToken ExpressionEvaluator::handleTokenName(tokenizer abort(); }); } else if rx_unlikely (outTok.text() == "array_remove"sv || outTok.text() == "array_remove_once"sv) { - return {.value = double((outTok.text() == "array_remove"sv) ? Command::ArrayRemove : Command::ArrayRemoveOnce), + return {.value = Variant{int(outTok.text() == "array_remove"sv ? Command::ArrayRemove : Command::ArrayRemoveOnce)}, .type = PrimaryToken::Type::Command}; } else if rx_unlikely (outTok.text() == "true"sv || outTok.text() == "false"sv) { if rx_unlikely (nonIntAllowed == NonIntegralAllowed::No) { throwUnexpectedTokenError(parser, outTok); } arrayValues_.emplace_back(outTok.text() == "true"sv); - return {.value = std::nullopt, .type = PrimaryToken::Type::Null}; + return {.value = Variant{}, .type = PrimaryToken::Type::Null}; } pv.GetByJsonPath(outTok.text(), tagsMatcher_, fieldValues, KeyValueType::Undefined{}); if (fieldValues.IsNullValue()) { - return {.value = std::nullopt, .type = PrimaryToken::Type::Null}; + return {.value = Variant{}, .type = PrimaryToken::Type::Null}; } const bool isArrayField = fieldValues.IsArrayValue(); @@ -160,18 +156,18 @@ ExpressionEvaluator::PrimaryToken ExpressionEvaluator::handleTokenName(tokenizer arrayValues_.emplace_back(std::move(val)); } if ((state_ == StateArrayConcat) || (fieldValues.size() != 1)) { - return {.value = std::nullopt, .type = PrimaryToken::Type::Array}; + return {.value = Variant{}, .type = PrimaryToken::Type::Array}; } } if (fieldValues.size() == 1) { const Variant* vptr = isArrayField ? &arrayValues_.back() : &fieldValues.front(); return vptr->Type().EvaluateOneOf( [vptr, isArrayField](OneOf) -> PrimaryToken { - return {.value = vptr->As(), .type = isArrayField ? PrimaryToken::Type::Array : PrimaryToken::Type::Scalar}; + return {.value = *vptr, .type = isArrayField ? PrimaryToken::Type::Array : PrimaryToken::Type::Scalar}; }, [&, this](OneOf) -> PrimaryToken { if (isArrayField) { - return {.value = std::nullopt, .type = PrimaryToken::Type::Array}; + return {.value = Variant{}, .type = PrimaryToken::Type::Array}; } throwUnexpectedTokenError(parser, outTok); }, @@ -182,16 +178,16 @@ ExpressionEvaluator::PrimaryToken ExpressionEvaluator::handleTokenName(tokenizer } else if (parser.peek_token(tokenizer::flags::treat_sign_as_token).text() == "("sv) { SelectFuncStruct funcData = SelectFuncParser().ParseFunction(parser, true, outTok); funcData.field = std::string(forField_); - return {.value = functionExecutor_.Execute(funcData).As(), .type = PrimaryToken::Type::Scalar}; + return {.value = functionExecutor_.Execute(funcData), .type = PrimaryToken::Type::Scalar}; } - return {.value = std::nullopt, .type = PrimaryToken::Type::Null}; + return {.value = Variant{}, .type = PrimaryToken::Type::Null}; } -void ExpressionEvaluator::handleCommand(tokenizer& parser, const PayloadValue& v, const std::optional& flag) { - if (!flag.has_value()) { +void ExpressionEvaluator::handleCommand(tokenizer& parser, const PayloadValue& v, const Variant& flag) { + if (!flag.Type().Is()) { throw Error(errParams, "Could not recognize command"); } - auto cmd = Command(int(flag.value())); + auto cmd = Command(flag.As()); if ((cmd != Command::ArrayRemove) && (cmd != Command::ArrayRemoveOnce)) { throw Error(errParams, "Unexpected command detected"); } @@ -226,8 +222,8 @@ void ExpressionEvaluator::handleCommand(tokenizer& parser, const PayloadValue& v if rx_unlikely (val.type != PrimaryToken::Type::Null) { if ((val.type != PrimaryToken::Type::Array) && (val.type != PrimaryToken::Type::Scalar)) { throw Error(errParams, "Expecting array or scalar as command parameter: '%s'", valueToken.text()); - } else if ((val.type == PrimaryToken::Type::Scalar) && val.value.has_value()) { - arrayValues_.emplace_back(Variant(val.value.value())); + } else if ((val.type == PrimaryToken::Type::Scalar) && !val.value.IsNullValue()) { + arrayValues_.emplace_back(val.value); } } @@ -272,7 +268,7 @@ double ExpressionEvaluator::performArrayConcatenation(tokenizer& parser, const P break; case PrimaryToken::Type::Array: case PrimaryToken::Type::Null: - if rx_unlikely (!left.value.has_value() && tok.text() != "|"sv) { + if rx_unlikely (left.value.IsNullValue() && tok.text() != "|"sv) { throw Error(errParams, "Unable to use array and null values outside of the arrays concatenation"); } break; @@ -280,7 +276,7 @@ double ExpressionEvaluator::performArrayConcatenation(tokenizer& parser, const P handleCommand(parser, v, left.value); // update state - left.value.reset(); + left.value = Variant{}; state_ = StateArrayConcat; tok = parser.peek_token(); break; @@ -302,12 +298,12 @@ double ExpressionEvaluator::performArrayConcatenation(tokenizer& parser, const P } if rx_unlikely (right.type == PrimaryToken::Type::Command) { handleCommand(parser, v, right.value); - right.value.reset(); + right.value = Variant{}; } - assertrx_throw(!right.value.has_value()); + assertrx_throw(right.value.IsNullValue()); tok = parser.peek_token(); } - return left.value.has_value() ? left.value.value() : 0.0; + return left.value.IsNullValue() ? 0.0 : left.value.As(); } double ExpressionEvaluator::performMultiplicationAndDivision(tokenizer& parser, const PayloadValue& v, token& tok) { diff --git a/cpp_src/core/query/expressionevaluator.h b/cpp_src/core/query/expressionevaluator.h index 4d60c0bf0..95ee1c8b6 100644 --- a/cpp_src/core/query/expressionevaluator.h +++ b/cpp_src/core/query/expressionevaluator.h @@ -21,7 +21,7 @@ class ExpressionEvaluator { struct PrimaryToken { enum class Type { Scalar, Array, Command, Null }; - std::optional value; + Variant value; Type type; }; @@ -33,7 +33,7 @@ class ExpressionEvaluator { [[nodiscard]] double performSumAndSubtracting(tokenizer& parser, const PayloadValue& v); [[nodiscard]] double performMultiplicationAndDivision(tokenizer& parser, const PayloadValue& v, token& lastTok); [[nodiscard]] double performArrayConcatenation(tokenizer& parser, const PayloadValue& v, token& lastTok); - void handleCommand(tokenizer& parser, const PayloadValue& v, const std::optional& flag); + void handleCommand(tokenizer& parser, const PayloadValue& v, const Variant& flag); void captureArrayContent(tokenizer& parser); [[noreturn]] void throwUnexpectedTokenError(tokenizer& parser, const token& outTok); diff --git a/cpp_src/core/query/queryentry.h b/cpp_src/core/query/queryentry.h index 202b69f3d..44d454833 100644 --- a/cpp_src/core/query/queryentry.h +++ b/cpp_src/core/query/queryentry.h @@ -377,9 +377,9 @@ class QueryJoinEntry { QueryField rightField_; const OpType op_{OpOr}; const CondType condition_{CondAny}; - const bool reverseNamespacesOrder_{false}; ///< controls SQL encoding order - ///< false: mainNs.index Condition joinNs.joinIndex - ///< true: joinNs.joinIndex Invert(Condition) mainNs.index + const bool reverseNamespacesOrder_{false}; ///< controls SQL encoding order + ///< false: mainNs.index Condition joinNs.joinIndex + ///< true: joinNs.joinIndex Invert(Condition) mainNs.index }; enum class InjectionDirection : bool { IntoMain, FromMain }; diff --git a/cpp_src/core/query/sql/sqlparser.cc b/cpp_src/core/query/sql/sqlparser.cc index 6ba7e678c..042bae570 100644 --- a/cpp_src/core/query/sql/sqlparser.cc +++ b/cpp_src/core/query/sql/sqlparser.cc @@ -299,33 +299,6 @@ class SQLParser::ParserContextsAppendGuard { SqlParsingCtx& nestedCtx_; }; -static KeyValueType detectValueType(const token& tok) { - const std::string_view val = tok.text(); - if (tok.type == TokenNumber) { - unsigned i = 0; - bool flt = false; - bool digit = val.length() < 21 && val.length() > 0; - if (val[i] == '+' || val[i] == '-') { - i++; - } - for (; i < val.length() && digit; i++) { - if (val[i] == '.') { - flt = true; - } else if (!isdigit(val[i])) { - digit = false; - } - } - if (digit && val.length() > 0) { - if (flt) { - return {KeyValueType::Double{}}; - } else { - return {KeyValueType::Int64{}}; - } - } - } - return {KeyValueType::String{}}; -} - Variant token2kv(const token& tok, tokenizer& parser, CompositeAllowed allowComposite, FieldAllowed allowField) { if (tok.text() == "{"sv) { // Composite value parsing @@ -338,7 +311,7 @@ Variant token2kv(const token& tok, tokenizer& parser, CompositeAllowed allowComp compositeValues.push_back(token2kv(nextTok, parser, CompositeAllowed::No, FieldAllowed::No)); nextTok = parser.next_token(); if (nextTok.text() == "}"sv) { - return Variant(compositeValues); // end process + return Variant(compositeValues); // end process } if (nextTok.text() != ","sv) { throw Error(errParseSQL, "Expected ',', but found '%s' in query, %s", nextTok.text(), parser.where()); @@ -363,24 +336,7 @@ Variant token2kv(const token& tok, tokenizer& parser, CompositeAllowed allowComp throw Error(errParseSQL, "Expected parameter, but found '%s' in query, %s", tok.text(), parser.where()); } - return detectValueType(tok).EvaluateOneOf( - [&](KeyValueType::Int64) { return Variant(int64_t(stoll(value))); }, - [&](KeyValueType::Double) { - try { - using double_conversion::StringToDoubleConverter; - static const StringToDoubleConverter converter{StringToDoubleConverter::NO_FLAGS, NAN, NAN, nullptr, nullptr}; - int countOfCharsParsedAsDouble; - return Variant(converter.StringToDouble(value.data(), int(value.size()), &countOfCharsParsedAsDouble)); - } catch (...) { - throw Error(errParseSQL, "Unable to convert '%s' to double value", value); - } - }, - [&](KeyValueType::String) { return Variant(make_key_string(value.data(), value.length())); }, - [](OneOf) noexcept -> Variant { - assertrx(0); - abort(); - }); + return getVariantFromToken(tok); } int SQLParser::parseOrderBy(tokenizer& parser, SortingEntries& sortingEntries, std::vector& forcedSortOrder_) { @@ -575,7 +531,7 @@ void SQLParser::parseCommand(tokenizer& parser) const { tok = parser.next_token(); // try parse as scalar value if ((tok.type == TokenNumber) || (tok.type == TokenString) || (tok.type == TokenName)) { - token2kv(tok, parser, CompositeAllowed::No, FieldAllowed::Yes); // ignore result + token2kv(tok, parser, CompositeAllowed::No, FieldAllowed::Yes); // ignore result } else { parseArray(parser, tok.text(), nullptr); } diff --git a/cpp_src/core/queryresults/queryresults.cc b/cpp_src/core/queryresults/queryresults.cc index 0a1ee037d..a56fbf265 100644 --- a/cpp_src/core/queryresults/queryresults.cc +++ b/cpp_src/core/queryresults/queryresults.cc @@ -8,6 +8,7 @@ #include "core/namespace/namespace.h" #include "core/namespace/namespaceimpl.h" #include "joinresults.h" +#include "server/outputparameters.h" #include "tools/catch_and_return.h" namespace reindexer { @@ -316,6 +317,9 @@ Error QueryResults::Iterator::GetProtobuf(WrSerializer& wrser, bool withHdrLen) auto& itemRef = qr_->items_[idx_]; assertrx(qr_->ctxs.size() > itemRef.Nsid()); auto& ctx = qr_->ctxs[itemRef.Nsid()]; + if (!ctx.schema_) { + return Error(errParams, "The schema was not found for Protobuf builder"); + } if (itemRef.Value().IsFree()) { return Error(errNotFound, "Item not found"); @@ -324,6 +328,10 @@ Error QueryResults::Iterator::GetProtobuf(WrSerializer& wrser, bool withHdrLen) ConstPayload pl(ctx.type_, itemRef.Value()); ProtobufEncoder encoder(&ctx.tagsMatcher_); ProtobufBuilder builder(&wrser, ObjType::TypePlain, ctx.schema_.get(), const_cast(&ctx.tagsMatcher_)); + + auto item = builder.Object(kProtoQueryResultsFields.at(kParamItems)); + auto ItemImpl = item.Object(ctx.schema_->GetProtobufNsNumber() + 1); + if (withHdrLen) { auto slicePosSaver = wrser.StartSlice(); encoder.Encode(pl, builder); diff --git a/cpp_src/core/rdxcontext.h b/cpp_src/core/rdxcontext.h index 679b40e78..82030e5b9 100644 --- a/cpp_src/core/rdxcontext.h +++ b/cpp_src/core/rdxcontext.h @@ -119,6 +119,7 @@ class RdxContext { RdxContext OnlyActivity() const { return RdxContext{Activity()}; } RdxActivityContext* Activity() const noexcept; Completion Compl() const { return cmpl_; } + bool IsInWalSync() const noexcept { return fromReplication_ && LSNs_.originLSN_.isEmpty(); } const bool fromReplication_; LSNPair LSNs_; diff --git a/cpp_src/core/selectfunc/ctx/basefunctionctx.h b/cpp_src/core/selectfunc/ctx/basefunctionctx.h index cebba4e26..261ff9960 100644 --- a/cpp_src/core/selectfunc/ctx/basefunctionctx.h +++ b/cpp_src/core/selectfunc/ctx/basefunctionctx.h @@ -1,5 +1,6 @@ #pragma once +#include "core/selectfunc/functions/debugrank.h" #include "core/selectfunc/functions/highlight.h" #include "core/selectfunc/functions/snippet.h" @@ -26,21 +27,22 @@ constexpr std::size_t variant_index() { } } -using SelectFuncVariant = std::variant; +using SelectFuncVariant = std::variant; enum class SelectFuncType { None = variant_index(), Snippet = variant_index(), Highlight = variant_index(), SnippetN = variant_index(), - + DebugRank = variant_index(), Max // Max possible value }; class BaseFunctionCtx : public intrusive_atomic_rc_base { public: typedef intrusive_ptr Ptr; - enum CtxType { kFtCtx = 0 }; - virtual ~BaseFunctionCtx() {} + enum class CtxType { kFtCtx = 1, kFtArea = 2, kFtAreaDebug = 3 }; + BaseFunctionCtx(CtxType t) noexcept : type(t) {} + virtual ~BaseFunctionCtx() = default; void AddFunction(const std::string& name, SelectFuncType functionIndx) { auto it = std::find_if(functions_.begin(), functions_.end(), [&name](const FuncData& data) { return data.name == name; }); @@ -67,7 +69,8 @@ class BaseFunctionCtx : public intrusive_atomic_rc_base { FuncData(std::string&& _name) noexcept : name(std::move(_name)) {} std::string name; - TypesArrayT types{}; + + TypesArrayT types = {}; }; h_vector functions_; }; diff --git a/cpp_src/core/selectfunc/ctx/ftctx.cc b/cpp_src/core/selectfunc/ctx/ftctx.cc index 5964c81a0..ff8b68922 100644 --- a/cpp_src/core/selectfunc/ctx/ftctx.cc +++ b/cpp_src/core/selectfunc/ctx/ftctx.cc @@ -2,38 +2,19 @@ namespace reindexer { -bool FtCtx::PrepareAreas(const RHashMap& fields, const std::string& name) { - assertrx_dbg(!NeedArea()); - auto& data = *data_; - if (!fields.empty()) { - data.isComposite_ = true; - } - - bool needArea = false; - if (data.isComposite_) { - for (auto& field : fields) { - needArea = CheckFunction(field.first, {SelectFuncType::Snippet, SelectFuncType::SnippetN, SelectFuncType::Highlight}); - if (needArea) { - break; - } - } - } - needArea = needArea || CheckFunction(name, {SelectFuncType::Snippet, SelectFuncType::SnippetN, SelectFuncType::Highlight}); - if (needArea) { - data.InitHolders(); - } - return needArea; -} - -template -void FtCtx::Add(InputIterator begin, InputIterator end, int16_t proc, AreaHolder&& holder) { - auto& data = *data_; - data.area_.emplace_back(std::move(holder)); - for (; begin != end; ++begin) { - data.proc_.emplace_back(proc); - if (data.holders_.has_value()) { - data.holders_->emplace(*begin, data_->area_.size() - 1); - } +FtCtx::FtCtx(BaseFunctionCtx::CtxType t) : BaseFunctionCtx(t) { + switch (t) { + case BaseFunctionCtx::CtxType::kFtCtx: + data_ = make_intrusive(t); + break; + case BaseFunctionCtx::CtxType::kFtArea: + data_ = make_intrusive>(t); + data_->holders.emplace(); + break; + case BaseFunctionCtx::CtxType::kFtAreaDebug: + data_ = make_intrusive>(t); + data_->holders.emplace(); + break; } } @@ -41,42 +22,66 @@ template void FtCtx::Add(InputIterator begin, InputIterator end, int16_t proc) { auto& data = *data_; for (; begin != end; ++begin) { - data.proc_.emplace_back(proc); + data.proc.emplace_back(proc); } } template -void FtCtx::Add(InputIterator begin, InputIterator end, int16_t proc, const std::vector& mask, AreaHolder&& holder) { +void FtCtx::Add(InputIterator begin, InputIterator end, int16_t proc, const std::vector& mask) { auto& data = *data_; - data.area_.emplace_back(std::move(holder)); for (; begin != end; ++begin) { assertrx(static_cast(*begin) < mask.size()); if (!mask[*begin]) { continue; } - data.proc_.emplace_back(proc); - if (data.holders_.has_value()) { - data.holders_->emplace(*begin, data.area_.size() - 1); + data.proc.emplace_back(proc); + } +} + +template +void FtCtx::Add(InputIterator begin, InputIterator end, int16_t proc, AreasInDocument&& areas) { + intrusive_ptr> dataArea = static_ctx_pointer_cast>(data_); + assertrx_throw(dataArea); + dataArea->area.emplace_back(std::move(areas)); + auto& data = *data_; + if (data.holders.has_value()) { + auto& holders = data.holders.value(); + for (; begin != end; ++begin) { + data.proc.push_back(proc); + holders.emplace(*begin, dataArea->area.size() - 1); } } } -template -void FtCtx::Add(InputIterator begin, InputIterator end, int16_t proc, const std::vector& mask) { +template +void FtCtx::Add(InputIterator begin, InputIterator end, int16_t proc, const std::vector& mask, AreasInDocument&& areas) { + intrusive_ptr> dataArea = static_ctx_pointer_cast>(data_); + assertrx_throw(dataArea); auto& data = *data_; - for (; begin != end; ++begin) { - assertrx(static_cast(*begin) < mask.size()); - if (!mask[*begin]) { - continue; + dataArea->area.emplace_back(std::move(areas)); + if (data.holders.has_value()) { + auto& holders = data.holders.value(); + for (; begin != end; ++begin) { + assertrx_dbg(static_cast(*begin) < mask.size()); + if (!mask[*begin]) { + continue; + } + data.proc.push_back(proc); + holders.emplace(*begin, dataArea->area.size() - 1); } - data.proc_.emplace_back(proc); } } +template void FtCtx::Add::iterator, Area>(span::iterator begin, span::iterator end, + int16_t proc, AreasInDocument&& holder); +template void FtCtx::Add::iterator, Area>(span::iterator begin, span::iterator end, + int16_t proc, const std::vector&, AreasInDocument&& holder); + template void FtCtx::Add::iterator>(span::iterator begin, span::iterator end, int16_t proc, - AreaHolder&& holder); + AreasInDocument&& holder); template void FtCtx::Add::iterator>(span::iterator begin, span::iterator end, int16_t proc, - const std::vector&, AreaHolder&& holder); + const std::vector&, AreasInDocument&& holder); + template void FtCtx::Add::iterator>(span::iterator begin, span::iterator end, int16_t proc); template void FtCtx::Add::iterator>(span::iterator begin, span::iterator end, int16_t proc, const std::vector&); diff --git a/cpp_src/core/selectfunc/ctx/ftctx.h b/cpp_src/core/selectfunc/ctx/ftctx.h index 636ccc42a..af696e286 100644 --- a/cpp_src/core/selectfunc/ctx/ftctx.h +++ b/cpp_src/core/selectfunc/ctx/ftctx.h @@ -8,49 +8,58 @@ namespace reindexer { +struct FtCtxData : public intrusive_atomic_rc_base { + FtCtxData(BaseFunctionCtx::CtxType t) noexcept : type(t) {} + virtual ~FtCtxData() = default; + void InitHolders() { + assertrx_dbg(!holders.has_value()); + holders.emplace(); + } + typedef intrusive_ptr Ptr; + std::vector proc; + std::optional> holders; + bool isComposite = false; + bool isWordPositions = false; + std::string extraWordSymbols; + BaseFunctionCtx::CtxType type; +}; + +template +struct FtCtxAreaData : public FtCtxData { + FtCtxAreaData(BaseFunctionCtx::CtxType t) noexcept : FtCtxData(t) {} + std::vector> area; +}; enum FtSortType { RankOnly, RankAndID, ExternalExpression }; class FtCtx : public BaseFunctionCtx { public: typedef intrusive_ptr Ptr; - struct Data : public BaseFunctionCtx { - bool NeedArea() const noexcept { return holders_.has_value(); } - void InitHolders() { - assertrx_dbg(!holders_.has_value()); - holders_.emplace(); - } - - typedef intrusive_ptr Ptr; - std::vector proc_; - std::optional> holders_; - std::vector area_; - bool isComposite_ = false; - bool isWordPositions_ = false; - std::string extraWordSymbols_; - }; - - FtCtx() : data_(make_intrusive()) { this->type = BaseFunctionCtx::kFtCtx; } - int16_t Proc(size_t pos) const noexcept { return (pos < data_->proc_.size()) ? data_->proc_[pos] : 0; } + FtCtx(BaseFunctionCtx::CtxType t); + int16_t Proc(size_t pos) const noexcept { return (pos < data_->proc.size()) ? data_->proc[pos] : 0; } - template - void Add(InputIterator begin, InputIterator end, int16_t proc, AreaHolder&& holder); template void Add(InputIterator begin, InputIterator end, int16_t proc); - template - void Add(InputIterator begin, InputIterator end, int16_t proc, const std::vector& mask, AreaHolder&& holder); template void Add(InputIterator begin, InputIterator end, int16_t proc, const std::vector& mask); - void Reserve(size_t size) { data_->proc_.reserve(size); } - size_t Size() const noexcept { return data_->proc_.size(); } - bool NeedArea() const noexcept { return data_->NeedArea(); } - bool PrepareAreas(const RHashMap& fields, const std::string& name); + template + void Add(InputIterator begin, InputIterator end, int16_t proc, AreasInDocument&& holder); - void SetData(Data::Ptr data) noexcept { data_ = std::move(data); } - const Data::Ptr& GetData() const noexcept { return data_; } + template + void Add(InputIterator begin, InputIterator end, int16_t proc, const std::vector& mask, AreasInDocument&& holder); + + void Reserve(size_t size) { data_->proc.reserve(size); } + size_t Size() const noexcept { return data_->proc.size(); } + + void SetExtraWordSymbols(const std::string& s) { data_->extraWordSymbols = s; } + void SetWordPosition(bool v) { data_->isWordPositions = v; } + + FtCtxData::Ptr GetData() { return data_; } + void SetData(FtCtxData::Ptr data) noexcept { data_ = std::move(data); } private: - Data::Ptr data_; + FtCtxData::Ptr data_; }; + } // namespace reindexer diff --git a/cpp_src/core/selectfunc/functions/debugrank.cc b/cpp_src/core/selectfunc/functions/debugrank.cc new file mode 100644 index 000000000..ac04e94a9 --- /dev/null +++ b/cpp_src/core/selectfunc/functions/debugrank.cc @@ -0,0 +1,103 @@ +#include "debugrank.h" +#include "core/keyvalue/p_string.h" +#include "core/payload/payloadiface.h" +#include "core/selectfunc/ctx/ftctx.h" +#include "core/selectfunc/selectfuncparser.h" + +namespace reindexer { + +bool DebugRank::Process(ItemRef& res, PayloadType& plType, const SelectFuncStruct& func, std::vector& stringsHolder) { + if (!func.funcArgs.empty()) { + throw Error(errParams, "'debug_rank()' does not expect any arguments, but got %d", func.funcArgs.size()); + } + if (!func.ctx || func.ctx->type != BaseFunctionCtx::CtxType::kFtAreaDebug) { + return false; + } + if (!func.tagsPath.empty()) { + throw Error(errConflict, "SetByJsonPath is not implemented yet!"); + } + + FtCtx::Ptr ftctx = reindexer::static_ctx_pointer_cast(func.ctx); + if (!ftctx->GetData()->isWordPositions) { + throw Error(errParams, "debug_rank() is supported for 'text' index only"); + } + + FtCtxAreaData& dataFtCtx = *(reindexer::static_ctx_pointer_cast>(ftctx->GetData())); + if (!dataFtCtx.holders.has_value()) { + return false; + } + const auto it = dataFtCtx.holders->find(res.Id()); + if (it == dataFtCtx.holders->end()) { + return false; + } + + Payload pl(plType, res.Value()); + + VariantArray kr; + pl.Get(func.field, kr); + + if (kr.empty() || !kr[0].Type().IsSame(KeyValueType::String{})) { + throw Error(errLogic, "Unable to apply debug_rank function to the non-string field '%s'", func.field); + } + + const std::string* data = p_string(kr[0]).getCxxstr(); + + const auto pva = dataFtCtx.area[it->second].GetAreas(func.fieldNo); + if (!pva || pva->Empty()) { + return false; + } + const auto& va = *pva; + + std::string resultString; + + Word2PosHelper word2pos(*data, ftctx->GetData()->extraWordSymbols); + + static const std::string_view startString = ""; + static const std::string_view endString = ""; + + const auto& areaVector = va.GetData(); + size_t id = 0; + size_t beforeStr = 0; + while (id < areaVector.size()) { + bool next = false; + int endStringCount = 0; + std::pair pos = word2pos.convert(areaVector[id].start, areaVector[id].end); + resultString += std::string_view(data->c_str() + beforeStr, pos.first - beforeStr); + do { + next = false; + switch (areaVector[id].phraseMode) { + case AreaDebug::PhraseMode::Start: + resultString += startString; + break; + case AreaDebug::PhraseMode::End: + endStringCount++; + break; + case AreaDebug::PhraseMode::None: + break; + } + resultString += areaVector[id].props; + id++; + if (id < areaVector.size() && areaVector[id].start == areaVector[id - 1].start) { + if (areaVector[id].end != areaVector[id - 1].end) { + throw Error(errLogic, "areas not equals start=%d ends(%d %d)", areaVector[id].start, areaVector[id].end, + areaVector[id - 1].end); + } + next = true; + } + } while (next); + resultString += std::string_view(data->c_str() + pos.first, pos.second - pos.first); + beforeStr = pos.second; + for (int i = 0; i < endStringCount; i++) { + resultString += endString; + } + } + resultString += std::string_view(data->c_str() + beforeStr, data->size() - beforeStr); + + stringsHolder.emplace_back(make_key_string(std::move(resultString))); + res.Value().Clone(); + + pl.Set(func.field, VariantArray{Variant{stringsHolder.back()}}); + + return true; +} +} // namespace reindexer \ No newline at end of file diff --git a/cpp_src/core/selectfunc/functions/debugrank.h b/cpp_src/core/selectfunc/functions/debugrank.h new file mode 100644 index 000000000..6cfecfa42 --- /dev/null +++ b/cpp_src/core/selectfunc/functions/debugrank.h @@ -0,0 +1,13 @@ +#pragma once +#include "core/item.h" +#include "core/queryresults/queryresults.h" + +namespace reindexer { + +struct SelectFuncStruct; + +class DebugRank { +public: + bool Process(ItemRef& res, PayloadType& plType, const SelectFuncStruct& func, std::vector& stringsHolder); +}; +} // namespace reindexer diff --git a/cpp_src/core/selectfunc/functions/highlight.cc b/cpp_src/core/selectfunc/functions/highlight.cc index ecbad1e7d..a3f9eb2b6 100644 --- a/cpp_src/core/selectfunc/functions/highlight.cc +++ b/cpp_src/core/selectfunc/functions/highlight.cc @@ -11,36 +11,35 @@ bool Highlight::Process(ItemRef& res, PayloadType& pl_type, const SelectFuncStru if (func.funcArgs.size() < 2) { throw Error(errParams, "Invalid highlight params need minimum 2 - have %d", func.funcArgs.size()); } - - if (!func.ctx || func.ctx->type != BaseFunctionCtx::kFtCtx) { + if (!func.ctx || func.ctx->type != BaseFunctionCtx::CtxType::kFtArea) { return false; } - + if (!func.tagsPath.empty()) { + throw Error(errConflict, "SetByJsonPath is not implemented yet!"); + } FtCtx::Ptr ftctx = reindexer::static_ctx_pointer_cast(func.ctx); - auto& dataFtCtx = *ftctx->GetData(); - if (!dataFtCtx.holders_.has_value()) { + FtCtxAreaData& dataFtCtx = *(reindexer::static_ctx_pointer_cast>(ftctx->GetData())); + if (!dataFtCtx.holders.has_value()) { return false; } - auto it = dataFtCtx.holders_->find(res.Id()); - if (it == dataFtCtx.holders_->end()) { + + auto it = dataFtCtx.holders->find(res.Id()); + if (it == dataFtCtx.holders->end()) { return false; } Payload pl(pl_type, res.Value()); VariantArray kr; - if (func.tagsPath.empty()) { - pl.Get(func.field, kr); - } else { - pl.GetByJsonPath(func.tagsPath, kr, KeyValueType::Undefined{}); - } + pl.Get(func.field, kr); if (kr.empty() || !kr[0].Type().IsSame(KeyValueType::String{})) { throw Error(errLogic, "Unable to apply highlight function to the non-string field '%s'", func.field); } const std::string* data = p_string(kr[0]).getCxxstr(); - auto pva = dataFtCtx.area_[it->second].GetAreas(func.fieldNo); + + auto pva = dataFtCtx.area[it->second].GetAreas(func.fieldNo); if (!pva || pva->Empty()) { return false; } @@ -50,12 +49,12 @@ bool Highlight::Process(ItemRef& res, PayloadType& pl_type, const SelectFuncStru result_string.reserve(data->size() + va.Size() * (func.funcArgs[0].size() + func.funcArgs[1].size())); result_string = *data; - Word2PosHelper word2pos(*data, ftctx->GetData()->extraWordSymbols_); + Word2PosHelper word2pos(*data, ftctx->GetData()->extraWordSymbols); int offset = 0; for (auto area : va.GetData()) { std::pair pos = - ftctx->GetData()->isWordPositions_ ? word2pos.convert(area.start, area.end) : std::make_pair(area.start, area.end); + ftctx->GetData()->isWordPositions ? word2pos.convert(area.start, area.end) : std::make_pair(area.start, area.end); result_string.insert(pos.first + offset, func.funcArgs[0]); offset += func.funcArgs[0].size(); @@ -68,11 +67,7 @@ bool Highlight::Process(ItemRef& res, PayloadType& pl_type, const SelectFuncStru stringsHolder.emplace_back(make_key_string(std::move(result_string))); res.Value().Clone(); - if (func.tagsPath.empty()) { - pl.Set(func.field, Variant{stringsHolder.back()}); - } else { - throw Error(errConflict, "SetByJsonPath is not implemented yet!"); - } + pl.Set(func.field, Variant{stringsHolder.back()}); return true; } diff --git a/cpp_src/core/selectfunc/functions/snippet.cc b/cpp_src/core/selectfunc/functions/snippet.cc index a6affd5fc..d512b97bb 100644 --- a/cpp_src/core/selectfunc/functions/snippet.cc +++ b/cpp_src/core/selectfunc/functions/snippet.cc @@ -185,10 +185,10 @@ A Snippet::RecalcZoneHelper::RecalcZoneToOffset(const Area& area) { return outAreas; } -void Snippet::buildResult(RecalcZoneHelper& recalcZoneHelper, const AreaBuffer& pva, const std::string& data, std::string& resultString) { +void Snippet::buildResult(RecalcZoneHelper& recalcZoneHelper, const AreasInField& pva, const std::string& data, + std::string& resultString) { // resultString =preDelim_+with_area_str+data_str_before+marker_before+zone_str+marker_after+data_strAfter+postDelim_ Area snippetAreaPrev; - Area snippetAreaPrevChar; zonesList_.clear(); for (const auto& area : pva.GetData()) { @@ -228,7 +228,7 @@ void Snippet::buildResult(RecalcZoneHelper& recalcZoneHelper, const AreaBuffer& resultString.append(postDelim_); } -void Snippet::buildResultWithPrefix(RecalcZoneHelper& recalcZoneHelper, const AreaBuffer& pva, const std::string& data, +void Snippet::buildResultWithPrefix(RecalcZoneHelper& recalcZoneHelper, const AreasInField& pva, const std::string& data, std::string& resultString) { // resultString =preDelim_+with_area_str+data_str_before+marker_before+zone_str+marker_after+data_strAfter+postDelim_ Area snippetAreaPrev; @@ -257,28 +257,31 @@ void Snippet::buildResultWithPrefix(RecalcZoneHelper& recalcZoneHelper, const Ar addSnippet(resultString, data, snippetAreaPrev, snippetAreaPrevChar); } -bool Snippet::Process(ItemRef& res, PayloadType& pl_type, const SelectFuncStruct& func, std::vector& stringsHolder) { +bool Snippet::Process(ItemRef& res, PayloadType& plType, const SelectFuncStruct& func, std::vector& stringsHolder) { if (!func.ctx) { return false; } + if (!func.tagsPath.empty()) { + throw Error(errConflict, "SetByJsonPath is not implemented yet!"); + } + init(func); FtCtx::Ptr ftctx = reindexer::static_ctx_pointer_cast(func.ctx); - auto& dataFtCtx = *ftctx->GetData(); - if (!dataFtCtx.isWordPositions_) { + auto& dataFtCtx = *(reindexer::static_ctx_pointer_cast>(ftctx->GetData())); + + if (!dataFtCtx.isWordPositions) { throw Error(errParams, "Snippet function does not work with ft_fuzzy index."); } - if (!func.tagsPath.empty()) { - throw Error(errConflict, "SetByJsonPath is not implemented yet!"); - } - if (!dataFtCtx.holders_.has_value()) { + if (!dataFtCtx.holders.has_value()) { return false; } - auto it = dataFtCtx.holders_->find(res.Id()); - if (it == dataFtCtx.holders_->end()) { + + auto it = dataFtCtx.holders->find(res.Id()); + if (it == dataFtCtx.holders->end()) { return false; } - Payload pl(pl_type, res.Value()); + Payload pl(plType, res.Value()); VariantArray kr; pl.Get(func.field, kr); @@ -287,7 +290,8 @@ bool Snippet::Process(ItemRef& res, PayloadType& pl_type, const SelectFuncStruct } const std::string* data = p_string(kr[0]).getCxxstr(); - auto pva = dataFtCtx.area_[it->second].GetAreas(func.fieldNo); + + auto pva = dataFtCtx.area[it->second].GetAreas(func.fieldNo); if (!pva || pva->Empty()) { return false; } @@ -295,7 +299,7 @@ bool Snippet::Process(ItemRef& res, PayloadType& pl_type, const SelectFuncStruct std::string resultString; resultString.reserve(data->size()); - RecalcZoneHelper recalcZoneHelper(*data, ftctx->GetData()->extraWordSymbols_, after_, before_, leftBound_, rightBound_); + RecalcZoneHelper recalcZoneHelper(*data, ftctx->GetData()->extraWordSymbols, after_, before_, leftBound_, rightBound_); if (needAreaStr_) { buildResultWithPrefix(recalcZoneHelper, *pva, *data, resultString); diff --git a/cpp_src/core/selectfunc/functions/snippet.h b/cpp_src/core/selectfunc/functions/snippet.h index d1240c8a5..c82dbda19 100644 --- a/cpp_src/core/selectfunc/functions/snippet.h +++ b/cpp_src/core/selectfunc/functions/snippet.h @@ -40,8 +40,8 @@ class Snippet { std::string_view leftBound_, rightBound_; }; - void buildResult(RecalcZoneHelper& recalcZoneHelper, const AreaBuffer& pva, const std::string& data, std::string& resultString); - void buildResultWithPrefix(RecalcZoneHelper& recalcZoneHelper, const AreaBuffer& pva, const std::string& data, + void buildResult(RecalcZoneHelper& recalcZoneHelper, const AreasInField& pva, const std::string& data, std::string& resultString); + void buildResultWithPrefix(RecalcZoneHelper& recalcZoneHelper, const AreasInField& pva, const std::string& data, std::string& resultString); bool isInit_ = false; diff --git a/cpp_src/core/selectfunc/selectfunc.cc b/cpp_src/core/selectfunc/selectfunc.cc index 734936b24..fdbdc8a0c 100644 --- a/cpp_src/core/selectfunc/selectfunc.cc +++ b/cpp_src/core/selectfunc/selectfunc.cc @@ -109,39 +109,6 @@ BaseFunctionCtx::Ptr SelectFunction::createFuncForProc(int indexNo) { } } -bool SelectFunction::NeedArea(int indexNo) const { - if (functions_.empty()) { - return false; - } - IndexType indexType = nm_.getIndexType(indexNo); - - auto checkField = [&](int field) -> bool { - const auto it = functions_.find(field); - if (it != functions_.end()) { - if (std::holds_alternative(it->second.func) || std::holds_alternative(it->second.func) || - std::holds_alternative(it->second.func)) { - return true; - } - } - return false; - }; - - if (IsComposite(indexType)) { - int cjsonFieldIdx = nm_.getIndexesCount(); - for (auto field : nm_.getIndexFields(indexNo)) { - if (field == IndexValueType::SetByJsonPath) { - field = cjsonFieldIdx++; - } - if (checkField(field)) { - return true; - } - } - } else { - return checkField(indexNo); - } - return false; -} - BaseFunctionCtx::Ptr SelectFunction::CreateCtx(int indexNo) { // we use this hack because ft always needs ctx to generate proc in response if (functions_.empty() && IsFullText(nm_.getIndexType(indexNo))) { @@ -220,8 +187,46 @@ bool SelectFunction::ProcessItem(ItemRef& res, PayloadType& pl_type, std::vector BaseFunctionCtx::Ptr SelectFunction::createCtx(SelectFuncStruct& data, BaseFunctionCtx::Ptr ctx, IndexType index_type) { if (IsFullText(index_type)) { if (!ctx) { - data.ctx = make_intrusive(); + switch (SelectFuncType(data.func.index())) { + case SelectFuncType::None: + data.ctx = make_intrusive(BaseFunctionCtx::CtxType::kFtCtx); + break; + case SelectFuncType::Snippet: + case SelectFuncType::Highlight: + case SelectFuncType::SnippetN: + data.ctx = make_intrusive(BaseFunctionCtx::CtxType::kFtArea); + break; + case SelectFuncType::DebugRank: + data.ctx = make_intrusive(BaseFunctionCtx::CtxType::kFtAreaDebug); + break; + case SelectFuncType::Max: + throw reindexer::Error(errLogic, "incorrect function type 'Max'"); + } } else { + switch (SelectFuncType(data.func.index())) { + case SelectFuncType::None: + if (ctx->type != BaseFunctionCtx::CtxType::kFtCtx) { + throw reindexer::Error(errLogic, "The existing calling context type '%d' does not allow this function", + int(ctx->type)); + } + break; + case SelectFuncType::Snippet: + case SelectFuncType::Highlight: + case SelectFuncType::SnippetN: + if (ctx->type != BaseFunctionCtx::CtxType::kFtArea) { + throw reindexer::Error(errLogic, "The existing calling context type '%d' does not allow this function", + int(ctx->type)); + } + break; + case SelectFuncType::DebugRank: + if (ctx->type != BaseFunctionCtx::CtxType::kFtAreaDebug) { + throw reindexer::Error(errLogic, "The existing calling context type '%d' does not allow this function", + int(ctx->type)); + } + break; + case SelectFuncType::Max: + throw reindexer::Error(errLogic, "incorrect function type 'Max'"); + } data.ctx = std::move(ctx); } const std::string& indexName = (data.indexNo >= nm_.getIndexesCount()) ? data.field : nm_.getIndexName(data.indexNo); diff --git a/cpp_src/core/selectfunc/selectfunc.h b/cpp_src/core/selectfunc/selectfunc.h index c263f54d1..e336fcbce 100644 --- a/cpp_src/core/selectfunc/selectfunc.h +++ b/cpp_src/core/selectfunc/selectfunc.h @@ -24,7 +24,6 @@ class SelectFunction : public intrusive_atomic_rc_base { /// @param indexNo - number of index. /// @return pointer to a function context or null if some error happened. BaseFunctionCtx::Ptr CreateCtx(int indexNo); - bool NeedArea(int indexNo) const; private: BaseFunctionCtx::Ptr createCtx(SelectFuncStruct& data, BaseFunctionCtx::Ptr ctx, IndexType index_type); @@ -32,7 +31,7 @@ class SelectFunction : public intrusive_atomic_rc_base { BaseFunctionCtx::Ptr createFuncForProc(int indexNo); /// Containers of functions by index number. - fast_hash_map functions_; + RHashMap functions_; /// Interface to NsSelector object. NsSelectFuncInterface nm_; diff --git a/cpp_src/core/selectfunc/selectfuncparser.cc b/cpp_src/core/selectfunc/selectfuncparser.cc index 797d7e295..4bd3872bf 100644 --- a/cpp_src/core/selectfunc/selectfuncparser.cc +++ b/cpp_src/core/selectfunc/selectfuncparser.cc @@ -191,38 +191,44 @@ SelectFuncStruct& SelectFuncParser::ParseFunction(tokenizer& parser, bool partOf static const Args args(4, {"pre_delim", "post_delim", "with_area", "left_bound", "right_bound"}); parsePositionalAndNamedArgs(parser, args); return selectFuncStruct_; + } else if (tok.text() == "debug_rank") { + selectFuncStruct_.func = DebugRank(); } selectFuncStruct_.funcName = std::string(tok.text()); tok = parser.next_token(tokenizer::flags::no_flags); if (tok.text() == "(") { - std::string arg; - while (!parser.end()) { - tok = parser.next_token(tokenizer::flags::no_flags); - if (tok.text() == ")") { - if (!partOfExpression) { - token nextTok = parser.next_token(tokenizer::flags::no_flags); - if (nextTok.text().length() > 0) { - throw Error(errParseDSL, "%s: Unexpected character `%s` after closing parenthesis", selectFuncStruct_.funcName, - nextTok.text()); + if (parser.peek_token(tokenizer::flags::no_flags).text() == ")") { + parser.next_token(tokenizer::flags::no_flags); + selectFuncStruct_.isFunction = true; + } else { + std::string arg; + while (!parser.end()) { + tok = parser.next_token(tokenizer::flags::no_flags); + if (tok.text() == ")") { + if (!partOfExpression) { + token nextTok = parser.next_token(tokenizer::flags::no_flags); + if (nextTok.text().length() > 0) { + throw Error(errParseDSL, "%s: Unexpected character `%s` after closing parenthesis", selectFuncStruct_.funcName, + nextTok.text()); + } } + selectFuncStruct_.funcArgs.emplace_back(std::move(arg)); + selectFuncStruct_.isFunction = true; + arg.clear(); + break; + } + if (tok.text() == "," && tok.type == TokenSymbol) { + selectFuncStruct_.funcArgs.emplace_back(std::move(arg)); + arg.clear(); + } else { + arg += tok.text(); } - selectFuncStruct_.funcArgs.emplace_back(std::move(arg)); - selectFuncStruct_.isFunction = true; - arg.clear(); - break; } - if (tok.text() == "," && tok.type == TokenSymbol) { - selectFuncStruct_.funcArgs.emplace_back(std::move(arg)); - arg.clear(); - } else { - arg += tok.text(); + if (!selectFuncStruct_.isFunction) { + throw Error(errParseDSL, "%s: The closing parenthesis is required, but found `%s`", selectFuncStruct_.funcName, tok.text()); } } - if (!selectFuncStruct_.isFunction) { - throw Error(errParseDSL, "%s: The closing parenthesis is required, but found `%s`. Select function name: `%s`", - selectFuncStruct_.funcName, tok.text(), selectFuncStruct_.funcName); - } } else { throw Error(errParseDSL, "%s: An open parenthesis is required, but found `%s`. Select function name: `%s`", selectFuncStruct_.funcName, tok.text(), selectFuncStruct_.funcName); diff --git a/cpp_src/core/selectfunc/selectfuncparser.h b/cpp_src/core/selectfunc/selectfuncparser.h index 0d7894f9e..ef5c45219 100644 --- a/cpp_src/core/selectfunc/selectfuncparser.h +++ b/cpp_src/core/selectfunc/selectfuncparser.h @@ -22,7 +22,7 @@ struct SelectFuncStruct { std::unordered_map namedArgs; BaseFunctionCtx::Ptr ctx; TagsPath tagsPath; - int indexNo = -1; + int indexNo = IndexValueType::NotSet; int fieldNo = 0; }; diff --git a/cpp_src/debug/backtrace.h b/cpp_src/debug/backtrace.h index d55d9bd38..29c629634 100644 --- a/cpp_src/debug/backtrace.h +++ b/cpp_src/debug/backtrace.h @@ -1,8 +1,8 @@ #pragma once #include -#include #include +#include namespace reindexer { namespace debug { diff --git a/cpp_src/estl/tokenizer.cc b/cpp_src/estl/tokenizer.cc index b6946ef58..6fd4c0945 100644 --- a/cpp_src/estl/tokenizer.cc +++ b/cpp_src/estl/tokenizer.cc @@ -1,4 +1,5 @@ #include "tokenizer.h" +#include "double-conversion/double-conversion.h" #include "tools/stringstools.h" namespace reindexer { @@ -182,4 +183,55 @@ std::string tokenizer::where() const { .append(std::to_string(q_.size())); } +Variant getVariantFromToken(const token& tok) { + const std::string_view str = tok.text(); + if (tok.type != TokenNumber || str.empty()) { + return Variant(make_key_string(str.data(), str.length())); + } + + if (!isdigit(str[0]) && (str.size() == 1 || (str[0] != '+' && str[0] != '-'))) { + return Variant(make_key_string(str.data(), str.length())); + } + + bool isFloat = false; + // INT64_MAX(9'223'372'036'854'775'807) contains 19 digits + 1 for possible sign + const size_t maxSignsInInt = 19 + (isdigit(str[0]) ? 0 : 1); + bool nullDecimalPart = true; + + size_t decPointPos = str.size(); + for (unsigned i = 1; i < str.size(); i++) { + if (str[i] == '.') { + if (isFloat) { + // second point - not a number + return Variant(make_key_string(str.data(), str.length())); + } + + decPointPos = i; + + isFloat = true; + continue; + } + + if (!isdigit(str[i])) { + return Variant(make_key_string(str.data(), str.length())); + } + + if (isFloat) { + nullDecimalPart = nullDecimalPart && str[i] == '0'; + } + } + + isFloat = !nullDecimalPart || (isFloat && decPointPos > maxSignsInInt); + + if (!isFloat) { + auto intPart = str.substr(0, decPointPos); + return intPart.size() <= maxSignsInInt ? Variant(stoll(intPart)) : Variant(make_key_string(str.data(), str.length())); + } + + using double_conversion::StringToDoubleConverter; + static const StringToDoubleConverter converter{StringToDoubleConverter::NO_FLAGS, NAN, NAN, nullptr, nullptr}; + int countOfCharsParsedAsDouble = 0; + return Variant(converter.StringToDouble(str.data(), str.size(), &countOfCharsParsedAsDouble)); +} + } // namespace reindexer diff --git a/cpp_src/estl/tokenizer.h b/cpp_src/estl/tokenizer.h index 5382e93d3..1304e7268 100644 --- a/cpp_src/estl/tokenizer.h +++ b/cpp_src/estl/tokenizer.h @@ -89,5 +89,6 @@ class tokenizer { enum class CompositeAllowed : bool { No = false, Yes = true }; enum class FieldAllowed : bool { No = false, Yes = true }; Variant token2kv(const token& currTok, tokenizer& parser, CompositeAllowed allowComposite, FieldAllowed allowField); +Variant getVariantFromToken(const token& tok); } // namespace reindexer diff --git a/cpp_src/gtests/bench/ft_bench.cc b/cpp_src/gtests/bench/ft_bench.cc index c0bdb667d..4d2b64b6e 100644 --- a/cpp_src/gtests/bench/ft_bench.cc +++ b/cpp_src/gtests/bench/ft_bench.cc @@ -9,8 +9,6 @@ #include "ft_fixture.h" #include "ft_merge_limit.h" -const std::string kStoragePath = "/tmp/reindex/ft_bench_test"; - using std::shared_ptr; using reindexer::Reindexer; @@ -23,15 +21,16 @@ const int kItemsInBenchDataset = 100'000; #endif int main(int argc, char** argv) { - if (reindexer::fs::RmDirAll(kStoragePath) < 0 && errno != ENOENT) { - std::cerr << "Could not clean working dir '" << kStoragePath << "'."; + const auto storagePath = reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "reindex/ft_bench_test"); + if (reindexer::fs::RmDirAll(storagePath) < 0 && errno != ENOENT) { + std::cerr << "Could not clean working dir '" << storagePath << "'."; std::cerr << "Reason: " << strerror(errno) << std::endl; return 1; } - shared_ptr DB = std::make_shared(); - auto err = DB->Connect("builtin://" + kStoragePath); + auto DB = std::make_shared(); + auto err = DB->Connect("builtin://" + storagePath); if (!err.ok()) { return err.code(); } diff --git a/cpp_src/gtests/bench/reindexer_bench.cc b/cpp_src/gtests/bench/reindexer_bench.cc index 669055241..1a094ac9b 100644 --- a/cpp_src/gtests/bench/reindexer_bench.cc +++ b/cpp_src/gtests/bench/reindexer_bench.cc @@ -16,8 +16,6 @@ #include "core/reindexer.h" -const std::string kStoragePath = "/tmp/reindex/bench_test"; - using std::shared_ptr; using reindexer::Reindexer; @@ -33,15 +31,16 @@ const int kItemsInComparatorsBenchDataset = 100'000; #endif int main(int argc, char** argv) { - if (reindexer::fs::RmDirAll(kStoragePath) < 0 && errno != ENOENT) { - std::cerr << "Could not clean working dir '" << kStoragePath << "'."; + const auto storagePath = reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "reindex/bench_test"); + if (reindexer::fs::RmDirAll(storagePath) < 0 && errno != ENOENT) { + std::cerr << "Could not clean working dir '" << storagePath << "'."; std::cerr << "Reason: " << strerror(errno) << std::endl; return 1; } - shared_ptr DB = std::make_shared(); - auto err = DB->Connect("builtin://" + kStoragePath); + auto DB = std::make_shared(); + auto err = DB->Connect("builtin://" + storagePath); if (!err.ok()) { return err.code(); } diff --git a/cpp_src/gtests/tests/API/base_tests.cc b/cpp_src/gtests/tests/API/base_tests.cc index c75694529..6436a7192 100644 --- a/cpp_src/gtests/tests/API/base_tests.cc +++ b/cpp_src/gtests/tests/API/base_tests.cc @@ -2045,11 +2045,11 @@ TEST_F(ReindexerApi, IntFieldConvertToStringIndexTest) { } TEST_F(ReindexerApi, MetaIndexTest) { - const std::string kStoragePath = reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "reindex/meta_index_test/"); - reindexer::fs::RmDirAll(kStoragePath); + const auto storagePath = reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "reindex/meta_index_test/"); + reindexer::fs::RmDirAll(storagePath); // ignore result auto rx = std::make_unique(); - auto err = rx->Connect("builtin://" + kStoragePath); + auto err = rx->Connect("builtin://" + storagePath); ASSERT_TRUE(err.ok()) << err.what(); err = rx->OpenNamespace(default_namespace, StorageOpts().Enabled().CreateIfMissing()); @@ -2152,3 +2152,75 @@ TEST_F(ReindexerApi, MetaIndexTest) { ASSERT_TRUE(err.ok()) << err.what(); ASSERT_EQ(readKeys, std::vector{}); } + +TEST_F(ReindexerApi, QueryResultsLSNTest) { + using namespace std::string_view_literals; + constexpr int kDataCount = 10; + + rt.OpenNamespace(default_namespace, StorageOpts().Enabled(false)); + rt.AddIndex(default_namespace, {"id", "hash", "int", IndexOpts().PK()}); + + for (int i = 0; i < kDataCount; ++i) { + auto item = rt.NewItem(default_namespace); + item["id"] = i; + rt.Upsert(default_namespace, item); + } + + // Select and save current LSNs + auto qr = rt.Select(Query(default_namespace)); + ASSERT_EQ(qr.Count(), kDataCount); + std::vector lsns; + lsns.reserve(kDataCount); + for (auto& it : qr) { + auto lsn = it.GetLSN(); + ASSERT_FALSE(reindexer::lsn_t{lsn}.isEmpty()); + lsns.emplace_back(lsn); + } + + { + // Modify data in different ways + const auto updated = rt.Update(Query(default_namespace).Where("id", CondEq, 0).Set("data", {Variant{"modified_0"sv}})); + ASSERT_EQ(updated, 1); + const auto deleted = rt.Delete(Query(default_namespace).Where("id", CondEq, 1)); + ASSERT_EQ(deleted, 1); + auto delItem = rt.NewItem(default_namespace); + delItem["id"] = 2; + rt.Delete(default_namespace, delItem); + rt.UpsertJSON(default_namespace, R"j({"id":3, "data":"modified_3"})j"); + } + + { + // Modify data via transaction + auto tx = rt.reindexer->NewTransaction(default_namespace); + ASSERT_TRUE(tx.Status().ok()) << tx.Status().what(); + + auto updQ = Query(default_namespace).Where("id", CondEq, 4).Set("data", {Variant{"modified_4"sv}}); + updQ.type_ = QueryUpdate; + tx.Modify(std::move(updQ)); + + auto delQ = Query(default_namespace).Where("id", CondEq, 5); + delQ.type_ = QueryDelete; + tx.Modify(std::move(delQ)); + + auto delItem = tx.NewItem(); + delItem["id"] = 6; + tx.Delete(std::move(delItem)); + auto updItem = tx.NewItem(); + updItem["id"] = 7; + updItem["data"] = "modified_7"; + tx.Update(std::move(updItem)); + QueryResults txQr; + auto err = rt.reindexer->CommitTransaction(tx, txQr); + ASSERT_TRUE(err.ok()) << err.what(); + } + + // Truncate all remaining data + auto err = rt.reindexer->TruncateNamespace(default_namespace); + ASSERT_TRUE(err.ok()) << err.what(); + + // Check that LSNs have not changed for the existing Qr + for (size_t i = 0; i < kDataCount; ++i) { + auto lsn = reindexer::lsn_t{(qr.begin() + i).GetLSN()}; + ASSERT_EQ(lsn, lsns[i]) << i; + } +} diff --git a/cpp_src/gtests/tests/fixtures/ft_api.cc b/cpp_src/gtests/tests/fixtures/ft_api.cc index 8db2d3aff..85efb7161 100644 --- a/cpp_src/gtests/tests/fixtures/ft_api.cc +++ b/cpp_src/gtests/tests/fixtures/ft_api.cc @@ -1,7 +1,7 @@ #include "ft_api.h" void FTApi::Init(const reindexer::FtFastConfig& ftCfg, unsigned nses, const std::string& storage) { - rt.reindexer.reset(new reindexer::Reindexer); + rt.reindexer = std::make_shared(); if (!storage.empty()) { auto err = rt.reindexer->Connect("builtin://" + storage); ASSERT_TRUE(err.ok()) << err.what(); @@ -154,11 +154,11 @@ void FTApi::AddInBothFields(std::string_view ns, std::string_view w1, std::strin rt.Commit(ns); } -reindexer::QueryResults FTApi::SimpleSelect(std::string word, bool withHighlight) { - auto q{reindexer::Query("nm1").Where("ft3", CondEq, std::move(word)).WithRank()}; +reindexer::QueryResults FTApi::SimpleSelect(std::string_view ns, std::string_view index, std::string_view dsl, bool withHighlight) { + auto q{reindexer::Query(ns).Where(index, CondEq, std::string(dsl)).WithRank()}; reindexer::QueryResults res; if (withHighlight) { - q.AddFunction("ft3 = highlight(!,!)"); + q.AddFunction(fmt::format("{} = highlight(!,!)", index)); } auto err = rt.reindexer->Select(q, res); EXPECT_TRUE(err.ok()) << err.what(); @@ -166,15 +166,6 @@ reindexer::QueryResults FTApi::SimpleSelect(std::string word, bool withHighlight return res; } -reindexer::QueryResults FTApi::SimpleSelect3(std::string word) { - auto qr{reindexer::Query("nm3").Where("ft", CondEq, std::move(word))}; - reindexer::QueryResults res; - qr.AddFunction("ft = highlight(!,!)"); - auto err = rt.reindexer->Select(qr, res); - EXPECT_TRUE(err.ok()) << err.what(); - return res; -} - reindexer::Error FTApi::Delete(int id) { reindexer::Item item = rt.NewItem("nm1"); item["id"] = id; diff --git a/cpp_src/gtests/tests/fixtures/ft_api.h b/cpp_src/gtests/tests/fixtures/ft_api.h index e4e1a7fa4..b9c4655f3 100644 --- a/cpp_src/gtests/tests/fixtures/ft_api.h +++ b/cpp_src/gtests/tests/fixtures/ft_api.h @@ -28,9 +28,11 @@ class FTApi : public ::testing::TestWithParam(); } Data randomItemData() { diff --git a/cpp_src/gtests/tests/fixtures/queries_api.h b/cpp_src/gtests/tests/fixtures/queries_api.h index bbca249b6..1a5326c69 100644 --- a/cpp_src/gtests/tests/fixtures/queries_api.h +++ b/cpp_src/gtests/tests/fixtures/queries_api.h @@ -743,11 +743,11 @@ class QueriesApi : public ReindexerApi, public QueriesVerifier { .Distinct(distinct.c_str()) .Sort(kFieldNameYear, true)); - ExecuteAndVerifyWithSql(Query(default_namespace) - .Select({distinct.c_str()}) - .Distinct(distinct.c_str()) - .Where(kFieldNameGenre, CondEq, randomGenre) - .Sort(kFieldNameYear, true)); + ExecuteAndVerifyWithSql(Query(default_namespace) + .Select({distinct.c_str()}) + .Distinct(distinct.c_str()) + .Where(kFieldNameGenre, CondEq, randomGenre) + .Sort(kFieldNameYear, true)); } } diff --git a/cpp_src/gtests/tests/fixtures/reindexertestapi.h b/cpp_src/gtests/tests/fixtures/reindexertestapi.h index 66f7b9c65..16c7e5a84 100644 --- a/cpp_src/gtests/tests/fixtures/reindexertestapi.h +++ b/cpp_src/gtests/tests/fixtures/reindexertestapi.h @@ -72,8 +72,8 @@ class ReindexerTestApi { auto err = reindexer->Commit(ns); ASSERT_TRUE(err.ok()) << err.what(); } - void OpenNamespace(std::string_view ns) { - auto err = reindexer->OpenNamespace(ns); + void OpenNamespace(std::string_view ns, const StorageOpts& storage = StorageOpts()) { + auto err = reindexer->OpenNamespace(ns, storage); ASSERT_TRUE(err.ok()) << err.what() << "; namespace: " << ns; } void AddIndex(std::string_view ns, const reindexer::IndexDef& idef) { @@ -135,6 +135,10 @@ class ReindexerTestApi { EXPECT_TRUE(err.ok()) << err.what() << "; " << q.GetSQL(QueryDelete); return qr.Count(); } + void Delete(const reindexer::Query& q, QueryResultsType& qr) { + auto err = reindexer->Delete(q, qr); + EXPECT_TRUE(err.ok()) << err.what() << "; " << q.GetSQL(QueryDelete); + } reindexer::Error DumpIndex(std::ostream& os, std::string_view ns, std::string_view index) { return reindexer->DumpIndex(os, ns, index); } diff --git a/cpp_src/gtests/tests/fixtures/servercontrol.cc b/cpp_src/gtests/tests/fixtures/servercontrol.cc index 11385372d..1f8fad48c 100644 --- a/cpp_src/gtests/tests/fixtures/servercontrol.cc +++ b/cpp_src/gtests/tests/fixtures/servercontrol.cc @@ -83,10 +83,13 @@ ServerControl::ServerControl(ServerControl&& rhs) noexcept { rhs.stopped_ = nullptr; } ServerControl& ServerControl::operator=(ServerControl&& rhs) noexcept { - WLock lock(rhs.mtx_); - interface = std::move(rhs.interface); - stopped_ = rhs.stopped_; - rhs.stopped_ = nullptr; + if (this != &rhs) { + WLock lock(rhs.mtx_); + interface = std::move(rhs.interface); + delete stopped_; + stopped_ = rhs.stopped_; + rhs.stopped_ = nullptr; + } return *this; } diff --git a/cpp_src/gtests/tests/fixtures/storage_lazy_load.h b/cpp_src/gtests/tests/fixtures/storage_lazy_load.h index c68e2c466..754c36f0e 100644 --- a/cpp_src/gtests/tests/fixtures/storage_lazy_load.h +++ b/cpp_src/gtests/tests/fixtures/storage_lazy_load.h @@ -5,7 +5,7 @@ class DISABLED_StorageLazyLoadApi : public ReindexerApi { public: - DISABLED_StorageLazyLoadApi() : pk_(0), inserted_(0) { rt.reindexer.reset(new Reindexer); } + DISABLED_StorageLazyLoadApi() : pk_(0), inserted_(0) { rt.reindexer = std::make_shared(); } ~DISABLED_StorageLazyLoadApi() { dropNs(); } void SetUp() override { diff --git a/cpp_src/gtests/tests/unit/ft/ft_generic.cc b/cpp_src/gtests/tests/unit/ft/ft_generic.cc index 6398ea66f..a727b1d10 100644 --- a/cpp_src/gtests/tests/unit/ft/ft_generic.cc +++ b/cpp_src/gtests/tests/unit/ft/ft_generic.cc @@ -70,7 +70,7 @@ TEST_P(FTGenericApi, CompositeSelect) { continue; } auto it = data.find(ritem[field].As()); - ASSERT_TRUE(it != data.end()); + ASSERT_TRUE(it != data.end()) << ritem[field].As(); data.erase(it); } } @@ -234,6 +234,7 @@ TEST_P(FTGenericApi, SelectWithDistance) { TEST_P(FTGenericApi, AreasOnSuffix) { auto ftCfg = GetDefaultConfig(); + ftCfg.optimization = reindexer::FtFastConfig::Optimization::CPU; Init(ftCfg); Add("the nos1 the nos2 the nosmn the nose"sv); @@ -249,6 +250,169 @@ TEST_P(FTGenericApi, AreasOnSuffix) { CheckResults("+nos* +*mask ", {{"the !nos1! the !mmask! stop !nos2! table", ""}}, false); } +TEST_P(FTGenericApi, DebugInfo) { + auto ftCfg = GetDefaultConfig(); + Init(ftCfg); + + Add("Маша ела кашу. Каша кушалась сама. Машу ругали."sv); + Add("Коля, Сеня гуляли."sv); + Add("слово простая фраза что то еще."sv); + Add("слово начало простая фраза конец что то еще простая фраза слово слово."sv); + Add("жил пил гулял"sv); + + auto removeLineEnd = [](std::vector& dataCompare) { + for (auto& s : dataCompare) { + s.erase(std::remove(s.begin(), s.end(), '\n'), s.end()); + } + }; + + { + reindexer::Query q("nm1"); + q.Where("ft3", CondEq, "маша"); + q.AddFunction("ft3 = debug_rank()"); + q.Select({"ft1"}); + reindexer::QueryResults res; + auto err = rt.reindexer->Select(q, res); + EXPECT_TRUE(err.ok()) << err.what(); + ASSERT_EQ(res.Count(), 1); + auto it = res.begin(); + reindexer::WrSerializer wrSer; + err = it.GetJSON(wrSer, false); + ASSERT_TRUE(err.ok()) << err.what(); + // clang-format off + std::vector dataCompare={R"({"ft1": +"{term_rank:97, term:маша, pattern:маша, bm25_norm:0.9798439468181269, term_len_boost:1, position_rank:1, norm_dist:0, proc:100, full_match_boost:0} Маша ела кашу. Каша кушалась сама. + {term_rank:77, term:маша, pattern:машу, bm25_norm:0.9798439468181269, term_len_boost:1, position_rank:0.994, norm_dist:0, proc:80, full_match_boost:0} Машу ругали."})"}; + // clang-format on + removeLineEnd(dataCompare); + ASSERT_EQ(wrSer.Slice(), dataCompare[0]); + } + + { + reindexer::Query q("nm1"); + q.Where("ft3", CondEq, "коля сеня"); + q.AddFunction("ft3 = debug_rank()"); + q.Select({"ft1"}); + reindexer::QueryResults res; + auto err = rt.reindexer->Select(q, res); + EXPECT_TRUE(err.ok()) << err.what(); + ASSERT_EQ(res.Count(), 1); + auto it = res.begin(); + reindexer::WrSerializer wrSer; + err = it.GetJSON(wrSer, false); + ASSERT_TRUE(err.ok()) << err.what(); + // clang-format off + std::vector dataCompare={R"({"ft1": +"{term_rank:102, term:коля, pattern:коля, bm25_norm:1.022314131295854, term_len_boost:1, position_rank:1, norm_dist:0, proc:100, full_match_boost:0} Коля, + {term_rank:102, term:сеня, pattern:сеня, bm25_norm:1.022314131295854, term_len_boost:1, position_rank:0.999, norm_dist:0, proc:100, full_match_boost:0} Сеня гуляли."})"}; + // clang-format on + removeLineEnd(dataCompare); + ASSERT_EQ(wrSer.Slice(), dataCompare[0]); + } + + { + reindexer::Query q("nm1"); + q.Where("ft3", CondEq, "'начало простая фраза конец' 'простая фраза'"); + q.AddFunction("ft3 = debug_rank()"); + q.Select({"ft1"}); + q.Sort("id", false); + q.WithRank(); + // clang-format off + std::vector dataCompare={ +R"###({"ft1":"слово + {term_rank:93, term:простая, pattern:простая, bm25_norm:0.9399331930048559, term_len_boost:1, position_rank:0.999, norm_dist:0, proc:100, full_match_boost:0} простая + {term_rank:85, term:фраза, pattern:фраза, bm25_norm:0.9399331930048559, term_len_boost:0.9142857193946838, position_rank:0.998, norm_dist:0, proc:100, full_match_boost:0} фраза + что то еще.","rank()":101.0})###", +R"##({"ft1":"слово + {term_rank:92, term:начало, pattern:начало, bm25_norm:0.9624865670750559, term_len_boost:0.9571428596973419, position_rank:0.999, norm_dist:0, proc:100, full_match_boost:0} начало + {term_rank:94, term:простая, pattern:простая, bm25_norm:0.9436916111700189, term_len_boost:1, position_rank:0.998, norm_dist:0, proc:100, full_match_boost:0} + {term_rank:94, term:простая, pattern:простая, bm25_norm:0.9436916111700189, term_len_boost:1, position_rank:0.998, norm_dist:0, proc:100, full_match_boost:0} простая + {term_rank:86, term:фраза, pattern:фраза, bm25_norm:0.9436916111700189, term_len_boost:0.9142857193946838, position_rank:0.997, norm_dist:0, proc:100, full_match_boost:0} + {term_rank:86, term:фраза, pattern:фраза, bm25_norm:0.9436916111700189, term_len_boost:0.9142857193946838, position_rank:0.997, norm_dist:0, proc:100, full_match_boost:0} фраза + {term_rank:87, term:конец, pattern:конец, bm25_norm:0.9624865670750559, term_len_boost:0.9142857193946838, position_rank:0.996, norm_dist:0, proc:100, full_match_boost:0} конец + что то еще + {term_rank:94, term:простая, pattern:простая, bm25_norm:0.9436916111700189, term_len_boost:1, position_rank:0.998, norm_dist:0, proc:100, full_match_boost:0} простая + {term_rank:86, term:фраза, pattern:фраза, bm25_norm:0.9436916111700189, term_len_boost:0.9142857193946838, position_rank:0.997, norm_dist:0, proc:100, full_match_boost:0} фраза + слово слово.","rank()":255.0})##" + }; + // clang-format on + removeLineEnd(dataCompare); + reindexer::QueryResults res; + auto err = rt.reindexer->Select(q, res); + EXPECT_TRUE(err.ok()) << err.what(); + ASSERT_EQ(res.Count(), 2); + + size_t i = 0; + for (auto it : res) { + reindexer::WrSerializer wrSer; + err = it.GetJSON(wrSer, false); + ASSERT_TRUE(err.ok()) << err.what(); + ASSERT_EQ(dataCompare[i], wrSer.Slice()); + i++; + } + } + + { + reindexer::Query q("nm1"); + q.Where("ft3", CondEq, "'простыми фразами'"); + q.AddFunction("ft3 = debug_rank()"); + q.Select({"ft1"}); + q.Sort("id", false); + // clang-format off + std::vector dataCompare={ +R"###({"ft1":"слово + {term_rank:74, term:простыми, pattern:простая, bm25_norm:0.9399331930048559, term_len_boost:1, position_rank:0.999, norm_dist:0, proc:79, full_match_boost:0} простая + {term_rank:74, term:фразами, pattern:фраза, bm25_norm:0.9399331930048559, term_len_boost:0.9624999999999999, position_rank:0.998, norm_dist:0, proc:82, full_match_boost:0} фраза + что то еще."})###", +R"###({"ft1":"слово начало + {term_rank:74, term:простыми, pattern:простая, bm25_norm:0.9436916111700189, term_len_boost:1, position_rank:0.998, norm_dist:0, proc:79, full_match_boost:0} простая + {term_rank:74, term:фразами, pattern:фраза, bm25_norm:0.9436916111700189, term_len_boost:0.9624999999999999, position_rank:0.997, norm_dist:0, proc:82, full_match_boost:0} фраза + конец что то еще + {term_rank:74, term:простыми, pattern:простая, bm25_norm:0.9436916111700189, term_len_boost:1, position_rank:0.998, norm_dist:0, proc:79, full_match_boost:0} простая + {term_rank:74, term:фразами, pattern:фраза, bm25_norm:0.9436916111700189, term_len_boost:0.9624999999999999, position_rank:0.997, norm_dist:0, proc:82, full_match_boost:0} фраза + слово слово."})###" + }; + // clang-format on + removeLineEnd(dataCompare); + + reindexer::QueryResults res; + auto err = rt.reindexer->Select(q, res); + EXPECT_TRUE(err.ok()) << err.what(); + ASSERT_EQ(res.Count(), 2); + size_t i = 0; + for (auto it : res) { + reindexer::WrSerializer wrSer; + err = it.GetJSON(wrSer, false); + EXPECT_TRUE(err.ok()) << err.what(); + ASSERT_EQ(dataCompare[i], wrSer.Slice()); + i++; + } + } + + { + reindexer::Query q("nm1"); + q.Where("ft3", CondEq, "жил~ пил"); + q.Select({"ft1"}); + q.AddFunction("ft3 = debug_rank()"); + reindexer::QueryResults res; + auto err = rt.reindexer->Select(q, res); + EXPECT_TRUE(err.ok()) << err.what(); + ASSERT_EQ(res.Count(), 1); + auto it = res.begin(); + reindexer::WrSerializer wrSer; + err = it.GetJSON(wrSer, false); + ASSERT_TRUE(err.ok()) << err.what(); + //clang-format off + std::vector dataCompare = { + R"({"ft1":"{term_rank:102, term:жил, pattern:жил, bm25_norm:1.022314131295854, term_len_boost:1, position_rank:1, norm_dist:0, proc:100, full_match_boost:0} жил + {term_rank:71, term:жил, pattern:ил, bm25_norm:1.022314131295854, term_len_boost:1, position_rank:0.999, norm_dist:0, proc:70, full_match_boost:0} + {term_rank:102, term:пил, pattern:пил, bm25_norm:1.022314131295854, term_len_boost:1, position_rank:0.999, norm_dist:0, proc:100, full_match_boost:0} пил гулял"})"}; + //clang-format on + removeLineEnd(dataCompare); + ASSERT_EQ(wrSer.Slice(), dataCompare[0]); + } +} + TEST_P(FTGenericApi, AreasMaxRank) { auto ftCfg = GetDefaultConfig(); ftCfg.maxAreasInDoc = 3; diff --git a/cpp_src/gtests/tests/unit/ft/ft_incremental_build.cc b/cpp_src/gtests/tests/unit/ft/ft_incremental_build.cc index 577422741..10b6c9c42 100644 --- a/cpp_src/gtests/tests/unit/ft/ft_incremental_build.cc +++ b/cpp_src/gtests/tests/unit/ft/ft_incremental_build.cc @@ -29,7 +29,7 @@ class FTIncrementalBuildApi : public FTApi { enum class StrictSuffixValidation { No, Yes }; void Init(const reindexer::FtFastConfig& ftCfg) { - rt.reindexer.reset(new reindexer::Reindexer); + rt.reindexer = std::make_shared(); auto err = rt.reindexer->OpenNamespace(GetDefaultNamespace()); ASSERT_TRUE(err.ok()) << err.what(); rt.DefineNamespaceDataset(GetDefaultNamespace(), {IndexDeclaration{"id", "hash", "int", IndexOpts().PK(), 0}, diff --git a/cpp_src/gtests/tests/unit/ft/ft_min_relevance.cc b/cpp_src/gtests/tests/unit/ft/ft_min_relevance.cc new file mode 100644 index 000000000..a1f831d5f --- /dev/null +++ b/cpp_src/gtests/tests/unit/ft/ft_min_relevance.cc @@ -0,0 +1,78 @@ +#include +#include "ft_api.h" + +class FTMinRelevanceApi : public FTApi { +protected: + std::string_view GetDefaultNamespace() noexcept override { return "ft_min_relevance"; } + void CreateNs() { + const std::string_view nmName = GetDefaultNamespace(); + rt.OpenNamespace(nmName); + rt.DefineNamespaceDataset(nmName, {IndexDeclaration{"id", "hash", "int", IndexOpts().PK(), 0}, + IndexDeclaration{"ft1", "text", "string", IndexOpts(), 0}}); + reindexer::FtFastConfig cfg(0); + cfg.enableNumbersSearch = true; + cfg.logLevel = 5; + cfg.maxStepSize = 100; + auto err = SetFTConfig(cfg, nmName, "ft1", {"ft1"}); + ASSERT_TRUE(err.ok()) << err.what(); + } + std::set SelectIDs(std::string_view str) { + auto qr = SimpleSelect(GetDefaultNamespace(), "ft1", str, false); + std::set selectDocs; + for (auto v : qr) { + reindexer::Item it = v.GetItem(); + selectDocs.insert(it["id"].As()); + } + return selectDocs; + } + void DelDocuments() { + auto deleted = rt.Delete(reindexer::Query(GetDefaultNamespace()).Where("ft1", CondEq, words_[deleteWordIndex_])); + ASSERT_GT(deleted, 0); + } + + const size_t deleteWordIndex_ = 1; + const std::vector words_{"машина", "стол", "велосипед", "автобус"}; +}; + +TEST_F(FTMinRelevanceApi, CorrectDocWithMinRelevanceAndEmptyDoc) { + CreateNs(); + + // Fill namespace + std::map>> docs; + std::set deleteDocs; + int id = 0; + constexpr int vDocCount = 300; + const std::string_view nmName = GetDefaultNamespace(); + for (int i = 0; i < vDocCount; i++) { + auto [it, _] = docs.insert(std::make_pair(i, std::map>())); + for (int k = 0; k < (i % 10) + 1; k++) { + const size_t w1 = rand() % words_.size(); + const size_t w2 = rand() % words_.size(); + if (w1 == deleteWordIndex_ || w2 == deleteWordIndex_) { + deleteDocs.insert(id); + } + std::string doc = words_[w1] + " " + words_[w2] + " " + std::to_string(i); + it->second.insert(std::make_pair(id, std::make_pair(doc, true))); + reindexer::Item item = rt.NewItem(nmName); + item["id"] = id; + item["ft1"] = doc; + rt.Upsert(nmName, item); + id++; + } + SelectIDs("build"); + } + // Delete documents with some unique word + DelDocuments(); + + // Check, that there are no deleted docs in results + const auto selectDocs = SelectIDs("машина автобус"); + std::vector intersection; + std::set_intersection(deleteDocs.begin(), deleteDocs.end(), selectDocs.begin(), selectDocs.end(), std::back_inserter(intersection)); + if (!intersection.empty()) { + std::stringstream ss; + for (auto& v : intersection) { + ss << v << " "; + } + ASSERT_TRUE(false) << "Intersection must be empty: " << ss.str(); + } +} diff --git a/cpp_src/gtests/tests/unit/index_tuple_test.cc b/cpp_src/gtests/tests/unit/index_tuple_test.cc deleted file mode 100644 index ce7729fe2..000000000 --- a/cpp_src/gtests/tests/unit/index_tuple_test.cc +++ /dev/null @@ -1,529 +0,0 @@ -#include -#include "reindexer_api.h" -#include "tools/fsops.h" - -class IndexTupleTest : public ReindexerApi { -public: - void SetUp() override { - reindexer::fs::RmDirAll(kStoragePath); - ReindexerApi::SetUp(); - } - - [[nodiscard]] std::string CreateEmptyNamespace(std::string_view ns) { return createNS(ns, R"json({"id":%d})json"); } - - [[nodiscard]] std::string CreateNamespace(std::string_view ns) { - static const char pattern[] = - R"json({"id":%d,"objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":0},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14}}},"arr":[{"nested_arr":[{"field":[3,2,1]},{"field":11},{"field":[9]}]}]})json"; - return createNS(ns, pattern); - } - - [[nodiscard]] std::string CreateSparseNamespace(std::string_view ns) { - return createNS(ns, R"json({"id":%d,"fld1":1,"fld2":{"nested":"test"}})json"); - } - - [[nodiscard]] std::string CreateArrayNamespace(std::string_view ns) { - static const char pattern[] = R"json({"id":%d,"obj":{"val":10},"arr":[1,2,3]})json"; - return createNS(ns, pattern); - } - - void DoTestDefault(const std::shared_ptr& reindexer, std::string_view ns, const reindexer::IndexDef& indexDef, - std::string_view pattern, std::string_view field, const VariantArray& expectedValues, - std::string_view description) const { - auto err = rt.reindexer->AddIndex(ns, indexDef); - ASSERT_TRUE(err.ok()) << err.what() << "\n" << description; - - validateResults(reindexer, ns, pattern, field, expectedValues, description); - } - - void DoTestEmpty(const std::shared_ptr& reindexer, std::string_view ns, const reindexer::IndexDef& indexDef, - std::string_view pattern, std::string_view description) const { - auto err = reindexer->AddIndex(ns, indexDef); - ASSERT_TRUE(err.ok()) << err.what(); - - checkExpectations(reindexer, ns, pattern, description); - } - - void DoCallAndCheckError(const std::shared_ptr& reindexer, std::string_view ns, - const reindexer::IndexDef& indexDef, std::string_view errMsg) const { - std::vector items; - getItems(reindexer, ns, items); - - auto err = reindexer->AddIndex(ns, indexDef); - ASSERT_FALSE(err.ok()); - ASSERT_EQ(err.what(), errMsg); - - checkItems(reindexer, ns, items); - } - - void ValidateReloadState(const std::shared_ptr& reindexer, std::string_view ns, std::string_view pattern, - std::string_view description, const std::string& storagePath) const { - auto err = rt.reindexer->CloseNamespace(ns); - ASSERT_TRUE(err.ok()) << err.what(); - - err = rt.reindexer->OpenNamespace(ns, StorageOpts().Enabled().CreateIfMissing().VerifyChecksums()); - ASSERT_TRUE(err.ok()) << err.what(); - - checkExpectations(reindexer, ns, pattern, description); - - // remove storage - err = rt.reindexer->CloseNamespace(ns); - ASSERT_TRUE(err.ok()) << err.what(); - - reindexer::fs::RmDirAll(storagePath); - } - - void SpecialCheckForNull(const std::shared_ptr& reindexer, std::string_view ns, std::string_view firstItemPattern, - std::string_view itemPattern, std::string_view description, const std::string& storagePath) const { - specialCheckForNull(reindexer, ns, firstItemPattern, itemPattern, description); - validateReloadStateForNull(reindexer, ns, firstItemPattern, itemPattern, description, storagePath); - } - - static constexpr uint32_t IdStart = 2000; - -private: - static constexpr char kStoragePath[] = "/tmp/reindex/"; - static constexpr uint32_t itemNumber_ = 5; // NOTE: minimum 2 - - [[nodiscard]] std::string createNS(std::string_view ns, std::string_view itemPattern) { - std::string storage; - createNamespace(ns, storage); - generateItems(ns, itemPattern); - return storage; - } - - void createNamespace(std::string_view ns, std::string& storagePath) { - storagePath = kStoragePath; - storagePath.append(ns); - - auto err = rt.reindexer->EnableStorage(storagePath); - ASSERT_TRUE(err.ok()) << err.what(); - - err = rt.reindexer->OpenNamespace(ns, StorageOpts().Enabled().CreateIfMissing()); - EXPECT_TRUE(err.ok()) << err.what(); - - DefineNamespaceDataset(ns, {IndexDeclaration{"id", "hash", "int", IndexOpts().PK(), 0}}); - } - - void generateItems(std::string_view ns, std::string_view pattern) { - for (uint32_t idx = IdStart, sz = IdStart + itemNumber_; idx < sz; ++idx) { - Item item = NewItem(ns); - EXPECT_TRUE(item.Status().ok()) << item.Status().what(); - - const auto json = fmt::sprintf(pattern.data(), idx); - auto err = item.FromJSON(json); - ASSERT_TRUE(err.ok()) << err.what(); - - Upsert(ns, item); - } - } - - void checkIfItemJSONValid(QueryResults::Iterator& it, bool print = false) const { - reindexer::WrSerializer wrser; - Error err = it.GetJSON(wrser, false); - EXPECT_TRUE(err.ok()) << err.what(); - if (err.ok() && print) { - std::cout << wrser.Slice() << std::endl; - } - } - - void validateResults(const std::shared_ptr& reindexer, std::string_view ns, std::string_view pattern, - std::string_view field, const VariantArray& expectedValues, std::string_view description) const { - SCOPED_TRACE(description); - - QueryResults qr; - auto err = reindexer->Select("SELECT * FROM " + std::string(ns), qr); - EXPECT_TRUE(err.ok()) << err.what(); - ASSERT_EQ(qr.Count(), itemNumber_); - - for (auto it : qr) { - Item item = it.GetItem(false); - checkIfItemJSONValid(it); - const auto json = item.GetJSON(); - ASSERT_NE(json.find(pattern), std::string::npos) << "JSON: " << json << ";\npattern: " << pattern; - const VariantArray values = item[field]; - ASSERT_EQ(values.size(), expectedValues.size()); - ASSERT_EQ(values.IsArrayValue(), expectedValues.IsArrayValue()); - for (size_t i = 0; i < values.size(); ++i) { - ASSERT_TRUE(values[i].Type().IsSame(expectedValues[i].Type())) - << values[i].Type().Name() << "!=" << expectedValues[i].Type().Name(); - if (values[i].Type().IsSame(reindexer::KeyValueType::Null())) { - continue; - } - - ASSERT_EQ(values[i], expectedValues[i]); - } - } - } - - void checkExpectations(const std::shared_ptr& reindexer, std::string_view ns, std::string_view pattern, - std::string_view description) const { - SCOPED_TRACE(description); - - QueryResults qr; - auto err = reindexer->Select("SELECT * FROM " + std::string(ns), qr); - EXPECT_TRUE(err.ok()) << err.what(); - ASSERT_EQ(qr.Count(), itemNumber_); - - uint32_t idx = IdStart; - for (auto it : qr) { - Item item = it.GetItem(false); - checkIfItemJSONValid(it); - - const auto json = item.GetJSON(); - const auto extJson = fmt::sprintf(pattern.data(), idx); - ASSERT_EQ(json, extJson); - - ++idx; - } - } - - void getItems(const std::shared_ptr& reindexer, std::string_view ns, std::vector& items) const { - QueryResults qr; - auto err = reindexer->Select("SELECT * FROM " + std::string(ns), qr); - ASSERT_TRUE(err.ok()) << err.what(); - - items.clear(); - items.reserve(qr.Count()); - for (auto& it : qr) { - auto item = it.GetItem(false); - items.emplace_back(item.GetJSON()); - } - } - - void checkItems(const std::shared_ptr& reindexer, std::string_view ns, - const std::vector& items) const { - QueryResults qr; - auto err = reindexer->Select("SELECT * FROM " + std::string(ns), qr); - ASSERT_TRUE(err.ok()) << err.what(); - - ASSERT_EQ(items.size(), qr.Count()); - auto itItems = items.cbegin(); - auto itQR = qr.begin(); - auto endItems = items.cend(); - auto endQR = qr.end(); - for (; (itItems != endItems) && (itQR != endQR); ++itItems, ++itQR) { - auto item = itQR.GetItem(false); - ASSERT_EQ(*itItems, item.GetJSON()); - } - } - - void specialCheckForNull(const std::shared_ptr& reindexer, std::string_view ns, std::string_view firstItemPattern, - std::string_view itemPattern, std::string_view description) const { - SCOPED_TRACE(description); - - // first element should not update values, all others should be initialized to default values - // Note: but index array updates element type - QueryResults qr; - auto err = reindexer->Select("SELECT * FROM " + std::string(ns), qr); - EXPECT_TRUE(err.ok()) << err.what(); - ASSERT_EQ(qr.Count(), itemNumber_); - - uint32_t idx = IdStart; - for (auto it : qr) { - Item item = it.GetItem(false); - checkIfItemJSONValid(it); - const auto json = item.GetJSON(); - const auto& pattern = (idx == IdStart) ? firstItemPattern : itemPattern; - const auto expJson = fmt::sprintf(pattern.data(), idx); - ASSERT_EQ(json, expJson); - - ++idx; - } - } - - void validateReloadStateForNull(const std::shared_ptr& reindexer, std::string_view ns, - std::string_view firstItemPattern, std::string_view itemPattern, std::string_view description, - const std::string& storagePath) const { - auto err = rt.reindexer->CloseNamespace(ns); - ASSERT_TRUE(err.ok()) << err.what(); - - err = rt.reindexer->OpenNamespace(ns, StorageOpts().Enabled().VerifyChecksums()); - ASSERT_TRUE(err.ok()) << err.what(); - - specialCheckForNull(reindexer, ns, firstItemPattern, itemPattern, description); - - // remove storage - err = rt.reindexer->CloseNamespace(ns); - ASSERT_TRUE(err.ok()) << err.what(); - - reindexer::fs::RmDirAll(storagePath); - } -}; - -TEST_F(IndexTupleTest, DISABLED_ScalarTest) { - static const std::string ns = "testNSScalar"; - const auto storage = CreateEmptyNamespace(ns); - - DoTestEmpty(rt.reindexer, ns, {"sparse", "text", "string", IndexOpts().Sparse()}, R"({"id":%d})", "add some sparse index. Do nothing"); - DoTestDefault(rt.reindexer, ns, {"text", "text", "string", IndexOpts()}, R"("text":"")", "text", {Variant("")}, - "add text scalar index. Add default value"); - DoTestEmpty(rt.reindexer, ns, {"text", "text", "string", IndexOpts()}, R"({"id":%d,"text":""})", "update text index. Do nothing"); - DoCallAndCheckError(rt.reindexer, ns, {"text", "hash", "int", IndexOpts()}, - "Index 'testNSScalar.text' already exists with different settings"); - DoTestDefault(rt.reindexer, ns, {"int", "hash", "int", IndexOpts()}, R"("int":0)", "int", {Variant(0)}, - "add int scalar index. Add default value"); - ValidateReloadState(rt.reindexer, ns, R"({"id":%d,"text":"","int":0})", "reload ns (ScalarTest)", storage); -} - -TEST_F(IndexTupleTest, DISABLED_ScalarNestedTest) { - static const std::string ns = "testNSNested"; - const auto storage = CreateEmptyNamespace(ns); - - DoTestDefault(rt.reindexer, ns, {"obj.more.nested", {"obj.more.nested"}, "hash", "int64", IndexOpts()}, - R"("obj":{"more":{"nested":0}})", "obj.more.nested", {Variant(int64_t(0))}, "add new nested scalar index"); - DoTestEmpty(rt.reindexer, ns, {"obj.more.nested", {"obj.more.nested"}, "hash", "int64", IndexOpts()}, - R"({"id":%d,"obj":{"more":{"nested":0}}})", "update nested index. Do nothing"); - DoTestEmpty(rt.reindexer, ns, {"id+obj.more.nested", {"id", "obj.more.nested"}, "tree", "composite", IndexOpts{}}, - R"({"id":%d,"obj":{"more":{"nested":0}}})", "add new composite index. Do nothing"); - DoCallAndCheckError(rt.reindexer, ns, {"obj.more", {"obj.more"}, "hash", "string", IndexOpts()}, - "Invalid tag type value for KeyValueType: ''"); - DoCallAndCheckError(rt.reindexer, ns, {"obj", "hash", "int64", IndexOpts()}, "Invalid tag type value for KeyValueType: ''"); - DoTestDefault(rt.reindexer, ns, {"obj.near", {"obj.near"}, "tree", "string", IndexOpts()}, R"("obj":{"more":{"nested":0},"near":""})", - "obj.near", {Variant("")}, "add nested scalar index to root"); - DoTestDefault(rt.reindexer, ns, {"obj.nested.text", {"obj.nested.text"}, "hash", "string", IndexOpts()}, - R"("obj":{"more":{"nested":0},"near":"","nested":{"text":""}}})", "obj.nested.text", {Variant("")}, - "add nested another path scalar index"); - DoTestDefault(rt.reindexer, ns, {"obj.idx", {"obj.idx"}, "hash", "int64", IndexOpts()}, - R"("obj":{"more":{"nested":0},"near":"","nested":{"text":""},"idx":0})", "obj.idx", {Variant(int64_t(0))}, - "add nested 2nd level path scalar index"); - DoTestDefault(rt.reindexer, ns, {"obj.new.another.one", {"obj.new.another.one"}, "tree", "double", IndexOpts()}, - R"("obj":{"more":{"nested":0},"near":"","nested":{"text":""},"idx":0,"new":{"another":{"one":0.0}}}})", - "obj.new.another.one", {Variant(0.0)}, "add nested scalar index with multiple new path levels"); - DoCallAndCheckError(rt.reindexer, ns, {"boom", {"obj.new.another.one"}, "tree", "string", IndexOpts()}, - "Cannot add field with name 'boom' to namespace 'testNSNested'. Json path 'obj.new.another.one' already used" - " in field 'obj.new.another.one'"); - DoCallAndCheckError(rt.reindexer, ns, {"boom", {"obj.new.another.one.two"}, "hash", "int64", IndexOpts()}, - "Cannot add field with name 'boom' (jsonpath 'obj.new.another.one.two') and type 'int64' to namespace" - " 'testNSNested'. Already exists json path 'obj.new.another.one' with type 'double' in field" - " 'obj.new.another.one'. Rewriting is impossible"); - DoTestDefault( - rt.reindexer, ns, {"root2.more.nested", {"root2.more.nested"}, "hash", "int64", IndexOpts()}, - R"("obj":{"more":{"nested":0},"near":"","nested":{"text":""},"idx":0,"new":{"another":{"one":0.0}}},"root2":{"more":{"nested":0}})", - "root2.more.nested", {Variant(int64_t(0))}, "add new root with nested"); - DoTestDefault( - rt.reindexer, ns, {"boom", {"obj.new.another.one_ext"}, "hash", "int64", IndexOpts()}, - R"("obj":{"more":{"nested":0},"near":"","nested":{"text":""},"idx":0,"new":{"another":{"one":0.0,"one_ext":0}}},"root2":{"more":{"nested":0}})", - "obj.new.another.one_ext", {Variant(int64_t(0))}, "add new nested scalar index with name extension in last part"); - DoTestDefault( - rt.reindexer, ns, {"a-ha", {"a.ha"}, "hash", "int64", IndexOpts()}, - R"("obj":{"more":{"nested":0},"near":"","nested":{"text":""},"idx":0,"new":{"another":{"one":0.0,"one_ext":0}}},"root2":{"more":{"nested":0}},"a":{"ha":0})", - "a.ha", {Variant(int64_t(0))}, "add another nested scalar index on top level"); - ValidateReloadState( - rt.reindexer, ns, - R"({"id":%d,"obj":{"more":{"nested":0},"near":"","nested":{"text":""},"idx":0,"new":{"another":{"one":0.0,"one_ext":0}}},"root2":{"more":{"nested":0}},"a":{"ha":0}})", - "reload ns (ScalarNestedTest)", storage); -} - -TEST_F(IndexTupleTest, SparseItemTest) { - static const std::string ns = "testNSSparse"; - const auto storage = CreateSparseNamespace(ns); - - DoTestEmpty(rt.reindexer, ns, {"sparse1", {"fld1"}, "hash", "int", IndexOpts().Sparse()}, - R"({"id":%d,"fld1":1,"fld2":{"nested":"test"}})", "add some sparse index to present nested field. Do nothing"); - DoCallAndCheckError(rt.reindexer, ns, {"sparse2", {"fld2"}, "hash", "int", IndexOpts().Sparse()}, "Can't convert 'test' to number"); - DoCallAndCheckError(rt.reindexer, ns, {"sparse3", {"fld2.nested"}, "hash", "int", IndexOpts().Sparse()}, - "Can't convert 'test' to number"); - DoTestEmpty(rt.reindexer, ns, {"sparse2", {"fld2"}, "hash", "string", IndexOpts().Sparse()}, - R"({"id":%d,"fld1":1,"fld2":{"nested":"test"}})", "add some sparse index to present part path field. Do nothing"); - ValidateReloadState(rt.reindexer, ns, R"({"id":%d,"fld1":1,"fld2":{"nested":"test"}})", "reload ns (SparseItemTest)", storage); -} - -TEST_F(IndexTupleTest, NestedUpdateTest) { - static const std::string ns = "testNSUpdate"; - const auto storage = CreateNamespace(ns); - - DoTestDefault( - rt.reindexer, ns, {"obj.nested", {"obj.nested"}, "hash", "string", IndexOpts()}, - R"("objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":"0"},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14}}},"arr":[{"nested_arr":[{"field":[3,2,1]},{"field":11},{"field":[9]}]}])", - "obj.nested", VariantArray{Variant{"0"}}, "add obj.nested index - update field type"); - DoCallAndCheckError(rt.reindexer, ns, {"try_change_type", {"last.text"}, "hash", "int", IndexOpts()}, "Can't convert 'OK' to number"); - ValidateReloadState( - rt.reindexer, ns, - R"({"id":%d,"objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":"0"},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14}}},"arr":[{"nested_arr":[{"field":[3,2,1]},{"field":11},{"field":[9]}]}]})", - "reload ns (NestedUpdateTest)", storage); -} - -// TODO: This test must be reenabled after #1353 -TEST_F(IndexTupleTest, DISABLED_ArrayTest) { - static const std::string ns = "testNSArray"; - const auto storage = CreateEmptyNamespace(ns); - - DoTestDefault(rt.reindexer, ns, {"array", "hash", "int", IndexOpts().Array()}, R"("array":[])", "array", {}, - "add int array index. Add empty array"); - DoTestDefault(rt.reindexer, ns, - {"obj.some.arr_1st", {"obj.some.array", "arr_fld", "obj.array"}, "hash", "int64", IndexOpts().Array(), 0}, - R"("array":[],"arr_fld":[])", "arr_fld", VariantArray{}.MarkArray(), "add array index. Add empty array"); - DoCallAndCheckError(rt.reindexer, ns, {"obj.some.array", {"obj.array"}, "hash", "int64", IndexOpts().Array(), 0}, - "Cannot add field with name 'obj.some.array' to namespace 'testNSArray'. Json path 'obj.array' already used in " - "field 'obj.some.arr_1st'"); - DoTestDefault(rt.reindexer, ns, - {"obj.some.new_array", {"obj.some.new_array", "arr_fld1", "arr_fld2"}, "hash", "int64", IndexOpts().Array(), 0}, - R"("array":[],"arr_fld":[],"arr_fld2":[])", "arr_fld2", VariantArray{}.MarkArray(), - "add another array index (chooses last of two). Add empty array"); - // TODO: This logic is disabled due to #1819 - DoTestDefault(rt.reindexer, ns, {"obj.new.array", {"obj.new.array"}, "hash", "int64", IndexOpts().Array(), 0}, - R"("array":[],"arr_fld":[],"arr_fld2":[]})" /*,"obj":{"new":{"array":[]}})"*/, "obj.new.array", VariantArray{}, - "add new nested (only) index. Add empty array"); - // TODO: This logic is disabled due to #1819 - DoTestDefault(rt.reindexer, ns, {"arr", "hash", "int64", IndexOpts().Array()}, - R"("array":[],"arr_fld":[],"arr_fld2":[],"arr":[]})" /*,"obj":{"new":{"array":[]}},"arr":[])"*/, "arr", VariantArray{}, - "add new field with nested (only) indexes. Add empty array"); - DoCallAndCheckError(rt.reindexer, ns, - {"arr_restriction", {"arr_fld3", "arr_fld4", "arr.some.arr_1st"}, "hash", "int64", IndexOpts().Array(), 0}, - "Cannot add field with name 'arr_restriction' (jsonpath 'arr.some.arr_1st') and type 'int64' to namespace" - " 'testNSArray'. Already exists json path 'arr' with type 'int64' in field 'arr'. Rewriting is impossible"); - DoTestEmpty(rt.reindexer, ns, {"new_sparse_array", {"new_sparse_array"}, "hash", "int64", IndexOpts().Array().Sparse(), 0}, - R"({"id":%d,"array":[],"arr_fld":[],"arr_fld2":[],"arr":[]})" /*,"obj":{"new":{"array":[]}},"arr":[]})"*/, - "add new sparse array index. Do nothing"); - ValidateReloadState(rt.reindexer, ns, - R"({"id":%d,"array":[],"arr_fld":[],"arr_fld2":[],"arr":[]})" /*,"obj":{"new":{"array":[]}},"arr":[]})"*/, - "reload ns (ArrayTest)", storage); -} - -// TODO: This test must be reenabled after #1353 -TEST_F(IndexTupleTest, DISABLED_ArrayNestedTest) { - static const std::string ns = "testNSArrayObj"; - const auto storage = CreateNamespace(ns); - - DoCallAndCheckError(rt.reindexer, ns, {"try_change_type", {"last.text"}, "hash", "int", IndexOpts().Array().Sparse()}, - "Can't convert 'OK' to number"); - DoCallAndCheckError(rt.reindexer, ns, {"try_change_type", {"last.text"}, "hash", "int", IndexOpts().Array()}, - "Can't convert 'OK' to number"); - // TODO: This logic is disabled due to #1819 - DoTestDefault( - rt.reindexer, ns, {"next.another.last", {"next.another.last"}, "hash", "string", IndexOpts().Array()}, - R"("objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":0},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14}}},"arr":[{"nested_arr":[{"field":[3,2,1]},{"field":11},{"field":[9]}]}]})" /*,"next":{"another":{"last":[]}})"*/ - , - "next.another.last", VariantArray{}, "add nested index to field by new path. Add empty array"); - DoTestDefault( - rt.reindexer, ns, {"obj.alternative", {"obj.alternative"}, "hash", "string", IndexOpts().Array()}, - R"("objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":0,"alternative":[]},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14}}},"arr":[{"nested_arr":[{"field":[3,2,1]},{"field":11},{"field":[9]}]}]})" /*,"next":{"another":{"last":[]}})"*/ - , - "obj.alternative", VariantArray{}, "add nested index to field. Add empty array"); - - DoTestDefault( - rt.reindexer, ns, {"last.1st.2nd.ext", {"last.1st.2nd.ext"}, "hash", "string", IndexOpts().Array()}, - R"("objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":0,"alternative":[]},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14,"ext":[]}}},"arr":[{"nested_arr":[{"field":[3,2,1]},{"field":11},{"field":[9]}]}]})" /*,"next":{"another":{"last":[]}})"*/ - , - "last.1st.2nd.ext.more", VariantArray{}, "add nested-nested index to field. Add empty array"); - DoCallAndCheckError(rt.reindexer, ns, {"last.1st.2nd.ext", {"last.alt", "last.1st.2nd.ext"}, "hash", "string", IndexOpts().Array()}, - "Index 'testNSArrayObj.last.1st.2nd.ext' already exists with different settings"); - // TODO: This logic is disabled due to #1819 - // DoTestDefault( - // rt.reindexer, ns, {"last.1st.2nd.ext.more", {"last.1st.2nd.ext.more"}, "hash", "string", IndexOpts().Array()}, - // R"("objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":0,"alternative":[]},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14,"ext":{"more":[]}}}},"arr":[{"nested_arr":[{"field":[3,2,1]},{"field":11},{"field":[9]}]}],"next":{"another":{"last":[]}})", - // "last.1st.2nd.ext.more", VariantArray{}, "add nested-nested index to field. Add empty array"); - // DoCallAndCheckError(rt.reindexer, ns, - // {"last.1st.2nd.ext.more", {"last.alt", "last.1st.2nd.ext.more"}, "hash", "string", IndexOpts().Array()}, - // "Index 'testNSArrayObj.last.1st.2nd.ext.more' already exists with different settings"); - DoTestDefault( - rt.reindexer, ns, {"last.1st.ext", {"last.1st.ext"}, "hash", "string", IndexOpts().Array()}, - R"("objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":0,"alternative":[]},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14,"ext":[]}},"ext":[]},"arr":[{"nested_arr":[{"field":[3,2,1]},{"field":11},{"field":[9]}]}]})" /*,"next":{"another":{"last":[]}})"*/ - , - "last.1st.ext", VariantArray{}, "add array index into the presented nested field. Add empty array"); - ValidateReloadState( - rt.reindexer, ns, - R"({"id":%d,"objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":0,"alternative":[]},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14,"ext":[]}},"ext":[]},"arr":[{"nested_arr":[{"field":[3,2,1]},{"field":11},{"field":[9]}]}]})" /*,"next":{"another":{"last":[]}}})"*/ - , - "reload ns (ArrayNestedTest)", storage); -} - -TEST_F(IndexTupleTest, ArrayInToArrayTest) { - static const std::string ns = "testNSArrayArr"; - const auto storage = CreateNamespace(ns); - - // TODO: This logic is disabled due to #1819 - DoTestDefault( - rt.reindexer, ns, {"objs.more", {"objs.more"}, "hash", "string", IndexOpts().Array()}, - R"("objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":0},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14}}},"arr":[{"nested_arr":[{"field":[3,2,1]},{"field":11},{"field":[9]}]}])", - "obj.more", VariantArray{}, "do not add anything into objects array"); - DoTestEmpty( - rt.reindexer, ns, {"arr.nested_arr.field", {"arr.nested_arr.field"}, "hash", "string", IndexOpts().Array()}, - R"({"id":%d,"objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":0},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14}}},"arr":[{"nested_arr":[{"field":["3","2","1"]},{"field":"11"},{"field":["9"]}]}]})", - "add nested index to array array (update). Do nothing"); - DoTestEmpty( - rt.reindexer, ns, {"arr.new_fld", {"arr.new_fld"}, "hash", "string", IndexOpts().Array()}, - R"({"id":%d,"objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":0},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14}}},"arr":[{"nested_arr":[{"field":["3","2","1"]},{"field":"11"},{"field":["9"]}]}]})", - "add nested index to array array. Do nothing"); - DoTestEmpty( - rt.reindexer, ns, {"arr.nested_arr.ext_fld", {"arr.nested_arr.ext_fld"}, "hash", "string", IndexOpts().Array()}, - R"({"id":%d,"objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":0},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14}}},"arr":[{"nested_arr":[{"field":["3","2","1"]},{"field":"11"},{"field":["9"]}]}]})", - "add nested nested index to array array. Do nothing"); - ValidateReloadState( - rt.reindexer, ns, - R"({"id":%d,"objs":[{"fld":1},{"fld":2},{"fld":5}],"obj":{"nested":0},"last":{"text":"OK","1st":{"2nd":{"3rd":3.14}}},"arr":[{"nested_arr":[{"field":["3","2","1"]},{"field":"11"},{"field":["9"]}]}]})", - "reload ns (ArrayInToArrayTest)", storage); -} - -// TODO: This test must be reenabled after #1353 -TEST_F(IndexTupleTest, DISABLED_NestedOrderingTest) { - static const std::string ns = "testNSNestedOrdering"; - const auto storage = CreateEmptyNamespace(ns); - - DoTestDefault(rt.reindexer, ns, {"nest1", {"obj.more.nested"}, "hash", "int", IndexOpts()}, R"("obj":{"more":{"nested":0}})", "nest1", - VariantArray{Variant{0}}, "add nest1. Add default value"); - DoTestDefault(rt.reindexer, ns, {"nest2", {"obj.near"}, "hash", "int", IndexOpts()}, R"("obj":{"more":{"nested":0},"near":0})", "nest2", - VariantArray{Variant{0}}, "add nest2. Add default value"); - DoTestDefault(rt.reindexer, ns, {"nest3", {"obj.nestd.text"}, "text", "string", IndexOpts()}, - R"("obj":{"more":{"nested":0},"near":0,"nestd":{"text":""}})", "nest3", VariantArray{Variant{""}}, - "add nest3. Add default value"); - DoTestDefault(rt.reindexer, ns, {"nest11", {"obj.more.nested2"}, "hash", "int", IndexOpts()}, - R"("obj":{"more":{"nested":0,"nested2":0},"near":0,"nestd":{"text":""}})", "nest11", VariantArray{Variant{0}}, - "add nest11. Add default value"); - ValidateReloadState(rt.reindexer, ns, R"({"id":%d,"obj":{"more":{"nested":0,"nested2":0},"near":0,"nestd":{"text":""}}})", - "reload ns (NestedDiffOrderingTest)", storage); -} - -// TODO: This test must be reenabled after #1353 -TEST_F(IndexTupleTest, DISABLED_NullTest) { - static const std::string ns = "testNSNull"; - const auto storage = CreateEmptyNamespace(ns); - - // update only one first item - { - const std::string sql = "UPDATE testNSNull SET fld1 = null, fld2 = [null, null] WHERE id = " + std::to_string(IdStart); - Query query = Query::FromSQL(sql); - QueryResults qr; - auto err = rt.reindexer->Update(query, qr); - ASSERT_TRUE(err.ok()) << err.what(); - ASSERT_EQ(qr.Count(), 1); - } - - // add indexes (simple and array) - { - auto err = rt.reindexer->AddIndex(ns, {"fld1", "hash", "int", IndexOpts()}); - ASSERT_TRUE(err.ok()) << err.what(); - err = rt.reindexer->AddIndex(ns, {"fld2", "hash", "string", IndexOpts().Array()}); - ASSERT_TRUE(err.ok()) << err.what(); - } - - SpecialCheckForNull(rt.reindexer, ns, R"({"id":%d,"fld1":null,"fld2":["null","null"]})", R"({"id":%d,"fld1":0,"fld2":[]})", - "null values test", storage); -} - -// TODO: This test must be reenabled after #1353 -TEST_F(IndexTupleTest, DISABLED_FailTest) { - static const std::string ns = "testNSFail"; - const auto storage = CreateEmptyNamespace(ns); - - DoTestDefault(rt.reindexer, ns, {"nest", {"obj.nest"}, "hash", "int", IndexOpts()}, R"("obj":{"nest":0})", "nest", - VariantArray{Variant{0}}, "add nest. Add default value"); - DoTestDefault(rt.reindexer, ns, {"idx", {"idx"}, "-", "bool", IndexOpts()}, R"("obj":{"nest":0},"idx":false)", "idx", - VariantArray{Variant{false}}, "add idx. Add default value"); - ValidateReloadState(rt.reindexer, ns, R"({"id":%d,"obj":{"nest":0},"idx":false})", "reload ns (FailTest)", storage); -} - -// TODO: This test must be reenabled after #1353 -TEST_F(IndexTupleTest, DISABLED_NestedArrayTest) { - static const std::string ns = "testNSNestedArray"; - const auto storage = CreateArrayNamespace(ns); - - // TODO: This logic is disabled due to #1819 - DoTestDefault(rt.reindexer, ns, {"obj.obj1.arr", {"obj.obj1.arr"}, "hash", "int", IndexOpts().Array()}, - R"("obj":{"val":10},"arr":[1,2,3])", "obj.obj1.arr", VariantArray{}, - // R"("obj":{"val":10,"obj1":{"arr":[]}},"arr":[1,2,3])", "obj.obj1.arr", VariantArray{}, - "add obj.obj1.arr. Add default value"); - DoTestDefault(rt.reindexer, ns, {"obj.arr", {"obj.arr"}, "hash", "int", IndexOpts().Array()}, - R"("obj":{"val":10,"arr":[]},"arr":[1,2,3])", "obj.arr", VariantArray{}, "add obj.arr. Add default value"); - ValidateReloadState(rt.reindexer, ns, R"({"id":%d,"obj":{"val":10,"arr":[]},"arr":[1,2,3]})", "reload ns (NestedArrayTest)", storage); -} diff --git a/cpp_src/gtests/tests/unit/namespace_test.cc b/cpp_src/gtests/tests/unit/namespace_test.cc index 28992e66d..47ca557a7 100644 --- a/cpp_src/gtests/tests/unit/namespace_test.cc +++ b/cpp_src/gtests/tests/unit/namespace_test.cc @@ -1516,13 +1516,13 @@ TEST_F(NsApi, ArrayRemoveWithSql) { Item item = it.GetItem(false); checkIfItemJSONValid(it); VariantArray values = item["array_field"]; - ASSERT_EQ(values.size(), 1 + 8 + 2); // [0] || [11,22,33,44,55,66,77,88] || [7,9] remove 99 - int i = 0; // 1 - for ( ; i < 9; ++i) { - ASSERT_EQ(values[i].As(), i * 11); // +8 + ASSERT_EQ(values.size(), 1 + 8 + 2); // [0] || [11,22,33,44,55,66,77,88] || [7,9] remove 99 + int i = 0; // 1 + for (; i < 9; ++i) { + ASSERT_EQ(values[i].As(), i * 11); // +8 } ASSERT_EQ(values[i++].As(), 7); - ASSERT_EQ(values[i].As(), 9); // +2 + ASSERT_EQ(values[i].As(), 9); // +2 } } @@ -1536,12 +1536,12 @@ TEST_F(NsApi, ArrayRemoveWithSql) { Item item = it.GetItem(false); checkIfItemJSONValid(it); VariantArray values = item["array_field"]; - ASSERT_EQ(values.size(), 1 + 8 + 1); // [0,11,22,33,44,55,66,77,88,9] remove 7 - int i = 0; // 1 - for ( ; i < 9; ++i) { - ASSERT_EQ(values[i].As(), i * 11); // +8 + ASSERT_EQ(values.size(), 1 + 8 + 1); // [0,11,22,33,44,55,66,77,88,9] remove 7 + int i = 0; // 1 + for (; i < 9; ++i) { + ASSERT_EQ(values[i].As(), i * 11); // +8 } - ASSERT_EQ(values[i].As(), 9); // +1 + ASSERT_EQ(values[i].As(), 9); // +1 } } @@ -1633,12 +1633,12 @@ TEST_F(NsApi, ArrayRemoveWithSql) { Item item = it.GetItem(false); checkIfItemJSONValid(it); VariantArray values = item["array_field"]; - ASSERT_EQ(values.size(), 9); // [11,22,33,44,55,66,77,88,9] remove 0 + ASSERT_EQ(values.size(), 9); // [11,22,33,44,55,66,77,88,9] remove 0 int i = 0; - for ( ; i < 8; ++i) { - ASSERT_EQ(values[i].As(), (i + 1) * 11); // +8 + for (; i < 8; ++i) { + ASSERT_EQ(values[i].As(), (i + 1) * 11); // +8 } - ASSERT_EQ(values[i].As(), 9); // +1 + ASSERT_EQ(values[i].As(), 9); // +1 } } @@ -1652,12 +1652,12 @@ TEST_F(NsApi, ArrayRemoveWithSql) { Item item = it.GetItem(false); checkIfItemJSONValid(it); VariantArray values = item["array_field"]; - ASSERT_EQ(values.size(), 8); // [11,22,33,44,55,66,77,9] remove 88 + ASSERT_EQ(values.size(), 8); // [11,22,33,44,55,66,77,9] remove 88 int i = 0; - for ( ; i < 7; ++i) { - ASSERT_EQ(values[i].As(), (i + 1) * 11); // +7 + for (; i < 7; ++i) { + ASSERT_EQ(values[i].As(), (i + 1) * 11); // +7 } - ASSERT_EQ(values[i].As(), 9); // +1 + ASSERT_EQ(values[i].As(), 9); // +1 } } diff --git a/cpp_src/gtests/tests/unit/protobuf_test.cc b/cpp_src/gtests/tests/unit/protobuf_test.cc index 885f0c65f..a53958b1f 100644 --- a/cpp_src/gtests/tests/unit/protobuf_test.cc +++ b/cpp_src/gtests/tests/unit/protobuf_test.cc @@ -19,10 +19,10 @@ const std::string kStreetValue = "Miracle Street, "; const std::string kPostalCodeValue = "9745 123 "; const double kSalaryValue = 11238761238768.232342342; -TEST_F(ReindexerApi, ProtobufConvesrionTest) { +TEST_F(ReindexerApi, ProtobufConversionTest) { // Check protobuf for basic types (int/double/array) and double <-> int conversion // !!! This test is using schema from cpp_src/gtests/tests/proto/conversion.proto. - // !!! Protobuf indexes are not constant and depend from the internal reindexer::Schema implementation. + // !!! Protobuf indexes are not persistent and depend on the internal implementation of reindexer::Schema. // clang-format off const std::string schema = R"z( { @@ -93,7 +93,7 @@ TEST_F(ReindexerApi, ProtobufConvesrionTest) { TEST_F(ReindexerApi, ProtobufEasyArrayTest) { // Check protobuf for arrays and nested objects // !!! This test is using schema from cpp_src/gtests/tests/proto/easyarrays.proto. - // !!! Protobuf indexes are not constant and depend from the internal reindexer::Schema implementation. + // !!! Protobuf indexes are not persistent and depend on the internal implementation of reindexer::Schema. // clang-format off const std::string schema = R"z( { diff --git a/cpp_src/gtests/tests/unit/replication_master_master_test.cc b/cpp_src/gtests/tests/unit/replication_master_master_test.cc index cba25beca..7e714012f 100644 --- a/cpp_src/gtests/tests/unit/replication_master_master_test.cc +++ b/cpp_src/gtests/tests/unit/replication_master_master_test.cc @@ -900,19 +900,37 @@ TEST_F(ReplicationSlaveSlaveApi, RenameSlaveNs) { ASSERT_TRUE(err.ok()) << err.what(); ASSERT_TRUE(r1.Count() == 1); } + TEST_F(ReplicationSlaveSlaveApi, Node3ApplyWal) { // Node configuration: // master // | // slave1 - // | - // slave2 + // | + // slave2 // Checks applying syncNamespaceByWAL on slave1 and slave2 node. const std::string kBaseDbPath(fs::JoinPath(kBaseTestsetDbPath, "Node3ApplyWal")); const std::string upDsn1 = "cproto://127.0.0.1:7770/db"; const std::string upDsn2 = "cproto://127.0.0.1:7771/db"; - const unsigned int n = 2000; // 11; + const unsigned n = 500; + const unsigned nTx = 500; + + auto modifyData = [&](ServerControl& sc, TestNamespace1& ns, int from) { + ns.AddRows(sc, from, n); + ns.AddRows(sc, from + n, nTx); + + auto& api = sc.Get()->api; + client::SyncCoroQueryResults qrUpd(api.reindexer.get()), qrDel(api.reindexer.get()); + api.Update(Query(ns.nsName_) + .Where("id", CondSet, {Variant{from + 1}, Variant{from + 2}, Variant{from + 5}, Variant{from + 10}}) + .Set("data", {Variant{"new value"}}), + qrUpd); + ASSERT_GT(qrUpd.Count(), 0); + api.Delete(Query(ns.nsName_).Where("id", CondSet, {Variant{from + 5}, Variant{from + 7}, Variant{from + 9}}), qrDel); + ASSERT_GT(qrDel.Count(), 0); + }; + { ServerControl master; ServerControl slave1; @@ -920,14 +938,14 @@ TEST_F(ReplicationSlaveSlaveApi, Node3ApplyWal) { master.InitServer(0, 7770, 7880, kBaseDbPath + "/master", "db", true); master.Get()->MakeMaster(); TestNamespace1 testns1(master, "ns1"); - testns1.AddRows(master, 3000, n); - // start init of slave + modifyData(master, testns1, 3000); + // Start init of slave { slave1.InitServer(1, 7771, 7881, kBaseDbPath + "/slave1", "db", true); slave2.InitServer(2, 7772, 7882, kBaseDbPath + "/slave2", "db", true); - ReplicationConfigTest configSlave1("slave", false, true, 1, upDsn1, "slave1"); + ReplicationConfigTest configSlave1("slave", false, false, 1, upDsn1, "slave1"); slave1.Get()->MakeSlave(configSlave1); - ReplicationConfigTest configSlave2("slave", false, true, 2, upDsn2, "slave2"); + ReplicationConfigTest configSlave2("slave", false, false, 2, upDsn2, "slave2"); slave2.Get()->MakeSlave(configSlave2); WaitSync(master, slave1, "ns1"); WaitSync(master, slave2, "ns1"); @@ -937,12 +955,13 @@ TEST_F(ReplicationSlaveSlaveApi, Node3ApplyWal) { slave2.Stop(); } + // Restart all nodes { ServerControl master; master.InitServer(0, 7770, 7880, kBaseDbPath + "/master", "db", true); master.Get()->MakeMaster(); TestNamespace1 testns1(master, "ns1"); - testns1.AddRows(master, 30000, n); + modifyData(master, testns1, 30000); } ServerControl master; master.InitServer(0, 7770, 7880, kBaseDbPath + "/master", "db", true); @@ -954,10 +973,21 @@ TEST_F(ReplicationSlaveSlaveApi, Node3ApplyWal) { ServerControl slave2; slave2.InitServer(2, 7772, 7882, kBaseDbPath + "/slave2", "db", true); - // std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + WaitSync(master, slave1, "ns1"); + WaitSync(master, slave2, "ns1"); + { + // Add more data and restart leader + TestNamespace1 testns1(master, "ns1"); + modifyData(master, testns1, 100000); + master.Stop(); + master = ServerControl(); + master.InitServer(0, 7770, 7880, kBaseDbPath + "/master", "db", true); + master.Get()->MakeMaster(); + } WaitSync(master, slave1, "ns1"); WaitSync(master, slave2, "ns1"); + master.Stop(); slave1.Stop(); slave2.Stop(); diff --git a/cpp_src/gtests/tests/unit/stringtools_test.cc b/cpp_src/gtests/tests/unit/stringtools_test.cc index 09b9f3623..9abdcdc79 100644 --- a/cpp_src/gtests/tests/unit/stringtools_test.cc +++ b/cpp_src/gtests/tests/unit/stringtools_test.cc @@ -1,4 +1,5 @@ #include +#include "estl/tokenizer.h" #include "gtest/gtest.h" #include "tools/stringstools.h" @@ -147,3 +148,114 @@ TEST_F(CustomStrCompareApi, IEqual) { ValidateEqualResult(res, cInverted); } } + +TEST(ConversionStringToNumber, DetectValueTypeTest) { + using namespace reindexer; + constexpr auto Int64V = KeyValueType{KeyValueType::Int64{}}; + constexpr auto DoubleV = KeyValueType{KeyValueType::Double{}}; + constexpr auto StringV = KeyValueType{KeyValueType::String{}}; + + struct TestCase { + struct Empty {}; + TestCase(std::string_view value, KeyValueType expectedType, std::variant expectedValue = Empty{}) + : value(value), + expectedType(expectedType), + expectedValue(std::visit(overloaded{[](auto v) { return Variant(v); }, + [value](Empty) { return Variant(make_key_string(value.data(), value.length())); }}, + expectedValue)) {} + + std::string_view value; + KeyValueType expectedType; + Variant expectedValue; + }; + + std::initializer_list values = { + {"9223372036854775807", Int64V, 9223372036854775807}, + {"9223372036854775807.", Int64V, 9223372036854775807}, + {"9223372036854775807.0", Int64V, 9223372036854775807}, + {"9223372036854775807.000", Int64V, 9223372036854775807}, + {"9223372036854775807.00000", Int64V, 9223372036854775807}, + + {"+9223372036854775807", Int64V, 9223372036854775807}, + {"+9223372036854775807.", Int64V, 9223372036854775807}, + {"+9223372036854775807.0", Int64V, 9223372036854775807}, + {"+9223372036854775807.000", Int64V, 9223372036854775807}, + {"+9223372036854775807.00000", Int64V, 9223372036854775807}, + + {"-9223372036854775807", Int64V, -9223372036854775807}, + {"-9223372036854775807.", Int64V, -9223372036854775807}, + {"-9223372036854775807.0", Int64V, -9223372036854775807}, + {"-9223372036854775807.000", Int64V, -9223372036854775807}, + {"-9223372036854775807.00000", Int64V, -9223372036854775807}, + + {"-922337203685477580.7", DoubleV, -922337203685477580.7}, + {"922337203685477580.7", DoubleV, 922337203685477580.7}, + {"92247758070.00456402", DoubleV, 92247758070.00456402}, + {"+92247758070.00456402", DoubleV, 92247758070.00456402}, + {"+922358070.000002", DoubleV, 922358070.000002}, + {"-922358070.000002", DoubleV, -922358070.000002}, + {"92547758070.1", DoubleV, 92547758070.1}, + + {"9223372036854775807.01", DoubleV, 9223372036854775807.01}, + {"92233720368547758070.0002", DoubleV, 92233720368547758070.0002}, + {"9223372036854775807.000002", DoubleV, 9223372036854775807.000002}, + {"92233720368547758070.1", DoubleV, 92233720368547758070.1}, + {"92233720368547758070.01", DoubleV, 92233720368547758070.01}, + {"92233720368547758070.0002", DoubleV, 92233720368547758070.0002}, + {"9223372036854775834257834562345234654324524070.00023452346452345234452", DoubleV, + 9223372036854775834257834562345234654324524070.00023452346452345234452}, + {"92233720368547758070.000012", DoubleV, 92233720368547758070.000012}, + + {"", StringV}, + {"-", StringV}, + {"+", StringV}, + {".", StringV}, + {" ", StringV}, + {"str", StringV}, + {"s", StringV}, + + {"92233720368547758070", StringV}, + {"92233720368547758070.", DoubleV, 92233720368547758070.0}, + {"92233720368547758070.0", DoubleV, 92233720368547758070.0}, + {"92233720368547758070.000", DoubleV, 92233720368547758070.0}, + {"92233720368547758070.00000", DoubleV, 92233720368547758070.0}, + + {"+92233720368547758070", StringV}, + {"+92233720368547758070.", DoubleV, 92233720368547758070.0}, + {"+92233720368547758070.0", DoubleV, 92233720368547758070.0}, + {"+92233720368547758070.000", DoubleV, 92233720368547758070.0}, + {"+92233720368547758070.00000", DoubleV, 92233720368547758070.0}, + + {"-92233720368547758070", StringV}, + {"-92233720368547758070.", DoubleV, -92233720368547758070.0}, + {"-92233720368547758070.0", DoubleV, -92233720368547758070.0}, + {"-92233720368547758070.000", DoubleV, -92233720368547758070.0}, + {"-92233720368547758070.00000", DoubleV, -92233720368547758070.0}, + + {"9'223'372'036'854'775'807", StringV}, + {"9223372802345370L", StringV}, + {"92233728070.0145L", StringV}, + + {"1.35e10", StringV}, + {"1.1e-2", StringV}, + {"123.456.7", StringV}, + }; + + auto genToken = [](std::string_view text) { + token tok{TokenNumber}; + tok.text_ = {text.begin(), text.end()}; + return tok; + }; + + for (const auto& testCase : values) { + auto res = getVariantFromToken(genToken(testCase.value)); + + std::stringstream expected, actual; + testCase.expectedValue.Dump(expected); + res.Dump(actual); + + auto errMessage = fmt::format("token value: {}; expected: {}; get: {}", testCase.value, expected.str(), actual.str()); + EXPECT_EQ(testCase.expectedValue, res) << errMessage; + EXPECT_TRUE(res.Type().IsSame(testCase.expectedType)) << errMessage; + } +} \ No newline at end of file diff --git a/cpp_src/net/cproto/dispatcher.h b/cpp_src/net/cproto/dispatcher.h index bf9c69cf9..c8b0c6d2a 100644 --- a/cpp_src/net/cproto/dispatcher.h +++ b/cpp_src/net/cproto/dispatcher.h @@ -89,7 +89,7 @@ class Dispatcher { /// Set closer notifier /// @param object close class object - /// @param func function, to be called on connecion close + /// @param func function, to be called on connection close template void OnClose(K* object, void (K::*func)(Context& ctx, const Error& err)) { onClose_ = [=](Context& ctx, const Error& err) { (static_cast(object)->*func)(ctx, err); }; @@ -113,7 +113,7 @@ class Dispatcher { /// @return OnResponse callback reference const std::function& OnResponseRef() const noexcept { return onResponse_; } - /// Handle RPC fron the context + /// Handle RPC from the context /// @param ctx - RPC context Error Handle(Context& ctx) { if rx_likely (uint32_t(ctx.call->cmd) < uint32_t(handlers_.size())) { @@ -141,7 +141,7 @@ class Dispatcher { template ::value, int> = 0> static T get_arg(const Args& args, size_t index, const Context& ctx) { if (index >= args.size()) { - throw Error(errParams, "Invalid args of %s call; argument %d is not submited", CmdName(ctx.call->cmd), static_cast(index)); + throw Error(errParams, "Invalid args of %s call; argument %d is not submitted", CmdName(ctx.call->cmd), static_cast(index)); } return T(args[index]); } @@ -172,7 +172,7 @@ class Dispatcher { std::function logger_; std::function onClose_; - // This should be called from the connection thread only to prevet access to other connection's ClientData + // This should be called from the connection thread only to prevent access to other connection's ClientData std::function onResponse_; }; } // namespace cproto diff --git a/cpp_src/net/iserverconnection.h b/cpp_src/net/iserverconnection.h index b005a788c..76f0a7beb 100644 --- a/cpp_src/net/iserverconnection.h +++ b/cpp_src/net/iserverconnection.h @@ -32,7 +32,7 @@ class IServerConnection { /// Restart connection /// @param s - socket of the accepted connection. - /// @return true - if successfuly restarted, false - if connection can't be restarted. + /// @return true - if successfully restarted, false - if connection can't be restarted. virtual bool Restart(socket&& s) = 0; /// Attach connection to another listener loop. Must be called from thread of loop /// @param loop - another loop to bind diff --git a/cpp_src/readme.md b/cpp_src/readme.md index acb9d4a5a..e4626811c 100644 --- a/cpp_src/readme.md +++ b/cpp_src/readme.md @@ -313,7 +313,7 @@ Reindexer supports the following data formats to communicate with other applicat There are no builtin mechanis for automatic log rotation, however `reindexer server` is able to reopen logfiles on `SIGHUP`. So, your external log manager (it may be even a simple `cron` script) have to move existing log files somewhere and then send `SIGHUP`-signal to the `reindexer server` process to recreate log files. -#### Protobuf +## Protobuf Protocol buffers are language-neutral, platform-neutral, extensible mechanism for serializing structured data. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages (https://developers.google.com/protocol-buffers). diff --git a/cpp_src/replicator/replicator.cc b/cpp_src/replicator/replicator.cc index 45a03376c..e7f478b1e 100644 --- a/cpp_src/replicator/replicator.cc +++ b/cpp_src/replicator/replicator.cc @@ -319,7 +319,7 @@ Replicator::SyncNsResult Replicator::syncNamespace(const NamespaceDef& ns, std:: rec.first.upstreamLSN_.Counter() > replState.lastUpstreamLSN.Counter() : false; if (terminate_) { - logPrintf(LogTrace, "[repl:%s:%s]:%d Terminationg updates applying cycle due to termination flag", ns.name, + logPrintf(LogTrace, "[repl:%s:%s]:%d Terminating updates applying cycle due to termination flag", ns.name, slave_->storagePath_, config_.serverId); break; } @@ -972,7 +972,7 @@ Error Replicator::applyWALRecord(LSNPair LSNs, std::string_view nsName, Namespac break; // force sync namespace case WalForceSync: - logPrintf(LogTrace, "[repl:%s]:%d WalForceSync: Scheduling force-sync for the namepsace", nsName, config_.serverId); + logPrintf(LogTrace, "[repl:%s]:%d WalForceSync: Scheduling force-sync for the namespace", nsName, config_.serverId); return sendSyncAsync(rec, true); break; case WalWALSync: @@ -980,7 +980,7 @@ Error Replicator::applyWALRecord(LSNPair LSNs, std::string_view nsName, Namespac return sendSyncAsync(rec, false); break; - // Replication state + // Replication state case WalReplState: { // last record in query stat.processed--; stat.masterState.FromJSON(giftStr(rec.data)); @@ -1344,8 +1344,8 @@ bool Replicator::canApplyUpdate(LSNPair LSNs, std::string_view nsName, const WAL std::lock_guard lck(syncMtx_); if (syncQueue_.Size() != 0 && syncQueue_.Contains(nsName)) { logPrintf(LogTrace, - "[repl:%s]:%d Skipping update due to scheduled namespace resync %s (%d). Pushin this update to the pending queue", nsName, - config_.serverId, LSNs.upstreamLSN_, int(wrec.type)); + "[repl:%s]:%d Skipping update due to scheduled namespace resync %s (%d). Submitting this update to the pending queue", + nsName, config_.serverId, LSNs.upstreamLSN_, int(wrec.type)); pushPendingUpdate(LSNs, nsName, wrec); return false; } @@ -1360,8 +1360,8 @@ bool Replicator::canApplyUpdate(LSNPair LSNs, std::string_view nsName, const WAL auto it = pendedUpdates_.find(nsName); if (it != pendedUpdates_.end()) { if (it->second.UpdatesLost) { - logPrintf(LogTrace, "[repl:%s]:%d NOT APPLY update lost %s (%d)", nsName, config_.serverId, LSNs.upstreamLSN_, - int(wrec.type)); + logPrintf(LogTrace, "[repl:%s]:%d Skipping update (lsn: %d; type: %d): there are lost updates for namespace", nsName, + config_.serverId, LSNs.upstreamLSN_, int(wrec.type)); return false; } else { logPrintf(LogTrace, "[repl:%s]:%d apply update pendeded not empty %s (%d)", nsName, config_.serverId, LSNs.upstreamLSN_, diff --git a/cpp_src/replicator/walselecter.cc b/cpp_src/replicator/walselecter.cc index 9be4d3248..895d662b6 100644 --- a/cpp_src/replicator/walselecter.cc +++ b/cpp_src/replicator/walselecter.cc @@ -6,6 +6,8 @@ #include "core/rdxcontext.h" #include "tools/semversion.h" +#include "tools/logger.h" + namespace reindexer { const SemVersion kMinUnknownReplSupportRxVersion("2.6.0"); @@ -19,6 +21,8 @@ void WALSelecter::operator()(QueryResults& result, SelectCtx& params) { int start = q.Offset(); result.totalCount = 0; + logFmt(LogInfo, "{}:{} WAL select (v3): {}", ns_->serverId_, ns_->name_, q.GetSQL(QuerySelect)); + if (!q.IsWALQuery()) { throw Error(errLogic, "Query to WAL should contain only 1 condition '#lsn > number'"); } diff --git a/cpp_src/replicator/waltracker.cc b/cpp_src/replicator/waltracker.cc index 159e9b9e8..1e2c52bf7 100644 --- a/cpp_src/replicator/waltracker.cc +++ b/cpp_src/replicator/waltracker.cc @@ -128,7 +128,7 @@ std::vector> WALTracker::readFromStorage(int64_t // Read LSN const int64_t lsn = *reinterpret_cast(dataSlice.data()); assertrx(lsn >= 0); - maxLSN = std::max(maxLSN, lsn); + maxLSN = std::max(maxLSN, lsn_t(lsn).Counter()); dataSlice = dataSlice.substr(sizeof(lsn)); data.emplace_back(lsn, std::string(dataSlice)); } diff --git a/cpp_src/server/CMakeLists.txt b/cpp_src/server/CMakeLists.txt index 6edd6c208..011ac90f6 100644 --- a/cpp_src/server/CMakeLists.txt +++ b/cpp_src/server/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.10) project(reindexer_server_library) set (SWAGGER_VERSION "2.x") -set (GH_FACE_VERSION "3.28.2") +set (GH_FACE_VERSION "3.29.0") set (GH_FACE_TAG "v${GH_FACE_VERSION}") set (TARGET reindexer_server_library) set (SERVER_LIB_DIR ${PROJECT_BINARY_DIR} PARENT_SCOPE) diff --git a/cpp_src/server/contrib/server.md b/cpp_src/server/contrib/server.md index e0f03a1ce..9ea554086 100644 --- a/cpp_src/server/contrib/server.md +++ b/cpp_src/server/contrib/server.md @@ -133,7 +133,7 @@ Reindexer is compact, fast and it does not have heavy dependencies. ### Version information -*Version* : 3.28.2 +*Version* : 3.29.0 ### License information diff --git a/cpp_src/server/contrib/server.yml b/cpp_src/server/contrib/server.yml index 65181abf6..ab5fc2bc8 100644 --- a/cpp_src/server/contrib/server.yml +++ b/cpp_src/server/contrib/server.yml @@ -4,7 +4,7 @@ info: **Reindexer** is an embeddable, in-memory, document-oriented database with a high-level Query builder interface. Reindexer's goal is to provide fast search with complex queries. Reindexer is compact, fast and it does not have heavy dependencies. - version: "3.28.2" + version: "3.29.0" title: "Reindexer REST API" license: name: "Apache 2.0" diff --git a/cpp_src/server/grpc/reindexerservice.cc b/cpp_src/server/grpc/reindexerservice.cc index adae54294..496417876 100644 --- a/cpp_src/server/grpc/reindexerservice.cc +++ b/cpp_src/server/grpc/reindexerservice.cc @@ -516,8 +516,6 @@ Error ReindexerService::buildItems(WrSerializer& wrser, const reindexer::QueryRe break; } case EncodingType::PROTOBUF: { - ProtobufBuilder builder(&wrser, ObjType::TypeObject); - ProtobufBuilder array = builder.Array("items"); for (auto& it : qr) { status = it.GetProtobuf(wrser, false); if (!status.ok()) { diff --git a/cpp_src/server/httpserver.cc b/cpp_src/server/httpserver.cc index bd59f8a18..c0ca367ed 100644 --- a/cpp_src/server/httpserver.cc +++ b/cpp_src/server/httpserver.cc @@ -1501,17 +1501,12 @@ int HTTPServer::queryResultsProtobuf(http::Context& ctx, const reindexer::QueryR WrSerializer wrSer(ctx.writer->GetChunk()); ProtobufBuilder protobufBuilder(&wrSer); - int itemsField = kProtoQueryResultsFields.at(kParamItems); for (size_t i = offset; i < res.Count() && i < offset + limit; i++) { - auto item = protobufBuilder.Object(itemsField); auto it = res[i]; - auto i1 = item.Object(res.getNsNumber(it.GetItemRef().Nsid()) + 1); const auto err = it.GetProtobuf(wrSer, false); if (!err.ok()) { return ctx.Protobuf(err.code(), wrSer.DetachChunk()); } - i1.End(); - item.End(); } int aggregationField = kProtoQueryResultsFields.at(kParamAggregations); diff --git a/cpp_src/tools/customlocal.cc b/cpp_src/tools/customlocal.cc index 4761e6cbe..fd42ced55 100644 --- a/cpp_src/tools/customlocal.cc +++ b/cpp_src/tools/customlocal.cc @@ -191,6 +191,3020 @@ constexpr std::pair kAlphabet[] = { {0x24D7, 0x24BD}, {0x24D8, 0x24BE}, {0x24D9, 0x24BF}, {0x24DA, 0x24C0}, {0x24DB, 0x24C1}, {0x24DC, 0x24C2}, {0x24DD, 0x24C3}, {0x24DE, 0x24C4}, {0x24DF, 0x24C5}, {0x24E0, 0x24C6}, {0x24E1, 0x24C7}, {0x24E2, 0x24C8}, {0x24E3, 0x24C9}, {0x24E4, 0x24CA}, {0x24E5, 0x24CB}, {0x24E6, 0x24CC}, {0x24E7, 0x24CD}, {0x24E8, 0x24CE}, {0x24E9, 0x24CF}, + //Hiragana + {0x3041, 0x3041}, {0x3042, 0x3042}, {0x3043, 0x3043}, {0x3044, 0x3044}, {0x3045, 0x3045}, {0x3046, 0x3046}, {0x3047, 0x3047}, + {0x3048, 0x3048}, {0x3049, 0x3049}, {0x304A, 0x304A}, {0x304B, 0x304B}, {0x304C, 0x304C}, {0x304D, 0x304D}, {0x304E, 0x304E}, + {0x304F, 0x304F}, {0x3050, 0x3050}, {0x3051, 0x3051}, {0x3052, 0x3052}, {0x3053, 0x3053}, {0x3054, 0x3054}, {0x3055, 0x3055}, + {0x3056, 0x3056}, {0x3057, 0x3057}, {0x3058, 0x3058}, {0x3059, 0x3059}, {0x305A, 0x305A}, {0x305B, 0x305B}, {0x305C, 0x305C}, + {0x305D, 0x305D}, {0x305E, 0x305E}, {0x305F, 0x305F}, {0x3060, 0x3060}, {0x3061, 0x3061}, {0x3062, 0x3062}, {0x3063, 0x3063}, + {0x3064, 0x3064}, {0x3065, 0x3065}, {0x3066, 0x3066}, {0x3067, 0x3067}, {0x3068, 0x3068}, {0x3069, 0x3069}, {0x306A, 0x306A}, + {0x306B, 0x306B}, {0x306C, 0x306C}, {0x306D, 0x306D}, {0x306E, 0x306E}, {0x306F, 0x306F}, {0x3070, 0x3070}, {0x3071, 0x3071}, + {0x3072, 0x3072}, {0x3073, 0x3073}, {0x3074, 0x3074}, {0x3075, 0x3075}, {0x3076, 0x3076}, {0x3077, 0x3077}, {0x3078, 0x3078}, + {0x3079, 0x3079}, {0x307A, 0x307A}, {0x307B, 0x307B}, {0x307C, 0x307C}, {0x307D, 0x307D}, {0x307E, 0x307E}, {0x307F, 0x307F}, + {0x3080, 0x3080}, {0x3081, 0x3081}, {0x3082, 0x3082}, {0x3083, 0x3083}, {0x3084, 0x3084}, {0x3085, 0x3085}, {0x3086, 0x3086}, + {0x3087, 0x3087}, {0x3088, 0x3088}, {0x3089, 0x3089}, {0x308A, 0x308A}, {0x308B, 0x308B}, {0x308C, 0x308C}, {0x308D, 0x308D}, + {0x308E, 0x308E}, {0x308F, 0x308F}, {0x3090, 0x3090}, {0x3091, 0x3091}, {0x3092, 0x3092}, {0x3093, 0x3093}, {0x3094, 0x3094}, + {0x3095, 0x3095}, {0x3096, 0x3096}, {0x3099, 0x3099}, {0x309A, 0x309A}, {0x309D, 0x309D}, {0x309E, 0x309E}, {0x309F, 0x309F}, + //CJK Unified Ideographs + {0x4E00, 0x4E00}, {0x4E01, 0x4E01}, {0x4E02, 0x4E02}, {0x4E03, 0x4E03}, {0x4E04, 0x4E04}, {0x4E05, 0x4E05}, {0x4E06, 0x4E06}, + {0x4E07, 0x4E07}, {0x4E08, 0x4E08}, {0x4E09, 0x4E09}, {0x4E0A, 0x4E0A}, {0x4E0B, 0x4E0B}, {0x4E0C, 0x4E0C}, {0x4E0D, 0x4E0D}, + {0x4E0E, 0x4E0E}, {0x4E0F, 0x4E0F}, {0x4E10, 0x4E10}, {0x4E11, 0x4E11}, {0x4E12, 0x4E12}, {0x4E13, 0x4E13}, {0x4E14, 0x4E14}, + {0x4E15, 0x4E15}, {0x4E16, 0x4E16}, {0x4E17, 0x4E17}, {0x4E18, 0x4E18}, {0x4E19, 0x4E19}, {0x4E1A, 0x4E1A}, {0x4E1B, 0x4E1B}, + {0x4E1C, 0x4E1C}, {0x4E1D, 0x4E1D}, {0x4E1E, 0x4E1E}, {0x4E1F, 0x4E1F}, {0x4E20, 0x4E20}, {0x4E21, 0x4E21}, {0x4E22, 0x4E22}, + {0x4E23, 0x4E23}, {0x4E24, 0x4E24}, {0x4E25, 0x4E25}, {0x4E26, 0x4E26}, {0x4E27, 0x4E27}, {0x4E28, 0x4E28}, {0x4E29, 0x4E29}, + {0x4E2A, 0x4E2A}, {0x4E2B, 0x4E2B}, {0x4E2C, 0x4E2C}, {0x4E2D, 0x4E2D}, {0x4E2E, 0x4E2E}, {0x4E2F, 0x4E2F}, {0x4E30, 0x4E30}, + {0x4E31, 0x4E31}, {0x4E32, 0x4E32}, {0x4E33, 0x4E33}, {0x4E34, 0x4E34}, {0x4E35, 0x4E35}, {0x4E36, 0x4E36}, {0x4E37, 0x4E37}, + {0x4E38, 0x4E38}, {0x4E39, 0x4E39}, {0x4E3A, 0x4E3A}, {0x4E3B, 0x4E3B}, {0x4E3C, 0x4E3C}, {0x4E3D, 0x4E3D}, {0x4E3E, 0x4E3E}, + {0x4E3F, 0x4E3F}, {0x4E40, 0x4E40}, {0x4E41, 0x4E41}, {0x4E42, 0x4E42}, {0x4E43, 0x4E43}, {0x4E44, 0x4E44}, {0x4E45, 0x4E45}, + {0x4E46, 0x4E46}, {0x4E47, 0x4E47}, {0x4E48, 0x4E48}, {0x4E49, 0x4E49}, {0x4E4A, 0x4E4A}, {0x4E4B, 0x4E4B}, {0x4E4C, 0x4E4C}, + {0x4E4D, 0x4E4D}, {0x4E4E, 0x4E4E}, {0x4E4F, 0x4E4F}, {0x4E50, 0x4E50}, {0x4E51, 0x4E51}, {0x4E52, 0x4E52}, {0x4E53, 0x4E53}, + {0x4E54, 0x4E54}, {0x4E55, 0x4E55}, {0x4E56, 0x4E56}, {0x4E57, 0x4E57}, {0x4E58, 0x4E58}, {0x4E59, 0x4E59}, {0x4E5A, 0x4E5A}, + {0x4E5B, 0x4E5B}, {0x4E5C, 0x4E5C}, {0x4E5D, 0x4E5D}, {0x4E5E, 0x4E5E}, {0x4E5F, 0x4E5F}, {0x4E60, 0x4E60}, {0x4E61, 0x4E61}, + {0x4E62, 0x4E62}, {0x4E63, 0x4E63}, {0x4E64, 0x4E64}, {0x4E65, 0x4E65}, {0x4E66, 0x4E66}, {0x4E67, 0x4E67}, {0x4E68, 0x4E68}, + {0x4E69, 0x4E69}, {0x4E6A, 0x4E6A}, {0x4E6B, 0x4E6B}, {0x4E6C, 0x4E6C}, {0x4E6D, 0x4E6D}, {0x4E6E, 0x4E6E}, {0x4E6F, 0x4E6F}, + {0x4E70, 0x4E70}, {0x4E71, 0x4E71}, {0x4E72, 0x4E72}, {0x4E73, 0x4E73}, {0x4E74, 0x4E74}, {0x4E75, 0x4E75}, {0x4E76, 0x4E76}, + {0x4E77, 0x4E77}, {0x4E78, 0x4E78}, {0x4E79, 0x4E79}, {0x4E7A, 0x4E7A}, {0x4E7B, 0x4E7B}, {0x4E7C, 0x4E7C}, {0x4E7D, 0x4E7D}, + {0x4E7E, 0x4E7E}, {0x4E7F, 0x4E7F}, {0x4E80, 0x4E80}, {0x4E81, 0x4E81}, {0x4E82, 0x4E82}, {0x4E83, 0x4E83}, {0x4E84, 0x4E84}, + {0x4E85, 0x4E85}, {0x4E86, 0x4E86}, {0x4E87, 0x4E87}, {0x4E88, 0x4E88}, {0x4E89, 0x4E89}, {0x4E8A, 0x4E8A}, {0x4E8B, 0x4E8B}, + {0x4E8C, 0x4E8C}, {0x4E8D, 0x4E8D}, {0x4E8E, 0x4E8E}, {0x4E8F, 0x4E8F}, {0x4E90, 0x4E90}, {0x4E91, 0x4E91}, {0x4E92, 0x4E92}, + {0x4E93, 0x4E93}, {0x4E94, 0x4E94}, {0x4E95, 0x4E95}, {0x4E96, 0x4E96}, {0x4E97, 0x4E97}, {0x4E98, 0x4E98}, {0x4E99, 0x4E99}, + {0x4E9A, 0x4E9A}, {0x4E9B, 0x4E9B}, {0x4E9C, 0x4E9C}, {0x4E9D, 0x4E9D}, {0x4E9E, 0x4E9E}, {0x4E9F, 0x4E9F}, {0x4EA0, 0x4EA0}, + {0x4EA1, 0x4EA1}, {0x4EA2, 0x4EA2}, {0x4EA3, 0x4EA3}, {0x4EA4, 0x4EA4}, {0x4EA5, 0x4EA5}, {0x4EA6, 0x4EA6}, {0x4EA7, 0x4EA7}, + {0x4EA8, 0x4EA8}, {0x4EA9, 0x4EA9}, {0x4EAA, 0x4EAA}, {0x4EAB, 0x4EAB}, {0x4EAC, 0x4EAC}, {0x4EAD, 0x4EAD}, {0x4EAE, 0x4EAE}, + {0x4EAF, 0x4EAF}, {0x4EB0, 0x4EB0}, {0x4EB1, 0x4EB1}, {0x4EB2, 0x4EB2}, {0x4EB3, 0x4EB3}, {0x4EB4, 0x4EB4}, {0x4EB5, 0x4EB5}, + {0x4EB6, 0x4EB6}, {0x4EB7, 0x4EB7}, {0x4EB8, 0x4EB8}, {0x4EB9, 0x4EB9}, {0x4EBA, 0x4EBA}, {0x4EBB, 0x4EBB}, {0x4EBC, 0x4EBC}, + {0x4EBD, 0x4EBD}, {0x4EBE, 0x4EBE}, {0x4EBF, 0x4EBF}, {0x4EC0, 0x4EC0}, {0x4EC1, 0x4EC1}, {0x4EC2, 0x4EC2}, {0x4EC3, 0x4EC3}, + {0x4EC4, 0x4EC4}, {0x4EC5, 0x4EC5}, {0x4EC6, 0x4EC6}, {0x4EC7, 0x4EC7}, {0x4EC8, 0x4EC8}, {0x4EC9, 0x4EC9}, {0x4ECA, 0x4ECA}, + {0x4ECB, 0x4ECB}, {0x4ECC, 0x4ECC}, {0x4ECD, 0x4ECD}, {0x4ECE, 0x4ECE}, {0x4ECF, 0x4ECF}, {0x4ED0, 0x4ED0}, {0x4ED1, 0x4ED1}, + {0x4ED2, 0x4ED2}, {0x4ED3, 0x4ED3}, {0x4ED4, 0x4ED4}, {0x4ED5, 0x4ED5}, {0x4ED6, 0x4ED6}, {0x4ED7, 0x4ED7}, {0x4ED8, 0x4ED8}, + {0x4ED9, 0x4ED9}, {0x4EDA, 0x4EDA}, {0x4EDB, 0x4EDB}, {0x4EDC, 0x4EDC}, {0x4EDD, 0x4EDD}, {0x4EDE, 0x4EDE}, {0x4EDF, 0x4EDF}, + {0x4EE0, 0x4EE0}, {0x4EE1, 0x4EE1}, {0x4EE2, 0x4EE2}, {0x4EE3, 0x4EE3}, {0x4EE4, 0x4EE4}, {0x4EE5, 0x4EE5}, {0x4EE6, 0x4EE6}, + {0x4EE7, 0x4EE7}, {0x4EE8, 0x4EE8}, {0x4EE9, 0x4EE9}, {0x4EEA, 0x4EEA}, {0x4EEB, 0x4EEB}, {0x4EEC, 0x4EEC}, {0x4EED, 0x4EED}, + {0x4EEE, 0x4EEE}, {0x4EEF, 0x4EEF}, {0x4EF0, 0x4EF0}, {0x4EF1, 0x4EF1}, {0x4EF2, 0x4EF2}, {0x4EF3, 0x4EF3}, {0x4EF4, 0x4EF4}, + {0x4EF5, 0x4EF5}, {0x4EF6, 0x4EF6}, {0x4EF7, 0x4EF7}, {0x4EF8, 0x4EF8}, {0x4EF9, 0x4EF9}, {0x4EFA, 0x4EFA}, {0x4EFB, 0x4EFB}, + {0x4EFC, 0x4EFC}, {0x4EFD, 0x4EFD}, {0x4EFE, 0x4EFE}, {0x4EFF, 0x4EFF}, {0x4F00, 0x4F00}, {0x4F01, 0x4F01}, {0x4F02, 0x4F02}, + {0x4F03, 0x4F03}, {0x4F04, 0x4F04}, {0x4F05, 0x4F05}, {0x4F06, 0x4F06}, {0x4F07, 0x4F07}, {0x4F08, 0x4F08}, {0x4F09, 0x4F09}, + {0x4F0A, 0x4F0A}, {0x4F0B, 0x4F0B}, {0x4F0C, 0x4F0C}, {0x4F0D, 0x4F0D}, {0x4F0E, 0x4F0E}, {0x4F0F, 0x4F0F}, {0x4F10, 0x4F10}, + {0x4F11, 0x4F11}, {0x4F12, 0x4F12}, {0x4F13, 0x4F13}, {0x4F14, 0x4F14}, {0x4F15, 0x4F15}, {0x4F16, 0x4F16}, {0x4F17, 0x4F17}, + {0x4F18, 0x4F18}, {0x4F19, 0x4F19}, {0x4F1A, 0x4F1A}, {0x4F1B, 0x4F1B}, {0x4F1C, 0x4F1C}, {0x4F1D, 0x4F1D}, {0x4F1E, 0x4F1E}, + {0x4F1F, 0x4F1F}, {0x4F20, 0x4F20}, {0x4F21, 0x4F21}, {0x4F22, 0x4F22}, {0x4F23, 0x4F23}, {0x4F24, 0x4F24}, {0x4F25, 0x4F25}, + {0x4F26, 0x4F26}, {0x4F27, 0x4F27}, {0x4F28, 0x4F28}, {0x4F29, 0x4F29}, {0x4F2A, 0x4F2A}, {0x4F2B, 0x4F2B}, {0x4F2C, 0x4F2C}, + {0x4F2D, 0x4F2D}, {0x4F2E, 0x4F2E}, {0x4F2F, 0x4F2F}, {0x4F30, 0x4F30}, {0x4F31, 0x4F31}, {0x4F32, 0x4F32}, {0x4F33, 0x4F33}, + {0x4F34, 0x4F34}, {0x4F35, 0x4F35}, {0x4F36, 0x4F36}, {0x4F37, 0x4F37}, {0x4F38, 0x4F38}, {0x4F39, 0x4F39}, {0x4F3A, 0x4F3A}, + {0x4F3B, 0x4F3B}, {0x4F3C, 0x4F3C}, {0x4F3D, 0x4F3D}, {0x4F3E, 0x4F3E}, {0x4F3F, 0x4F3F}, {0x4F40, 0x4F40}, {0x4F41, 0x4F41}, + {0x4F42, 0x4F42}, {0x4F43, 0x4F43}, {0x4F44, 0x4F44}, {0x4F45, 0x4F45}, {0x4F46, 0x4F46}, {0x4F47, 0x4F47}, {0x4F48, 0x4F48}, + {0x4F49, 0x4F49}, {0x4F4A, 0x4F4A}, {0x4F4B, 0x4F4B}, {0x4F4C, 0x4F4C}, {0x4F4D, 0x4F4D}, {0x4F4E, 0x4F4E}, {0x4F4F, 0x4F4F}, + {0x4F50, 0x4F50}, {0x4F51, 0x4F51}, {0x4F52, 0x4F52}, {0x4F53, 0x4F53}, {0x4F54, 0x4F54}, {0x4F55, 0x4F55}, {0x4F56, 0x4F56}, + {0x4F57, 0x4F57}, {0x4F58, 0x4F58}, {0x4F59, 0x4F59}, {0x4F5A, 0x4F5A}, {0x4F5B, 0x4F5B}, {0x4F5C, 0x4F5C}, {0x4F5D, 0x4F5D}, + {0x4F5E, 0x4F5E}, {0x4F5F, 0x4F5F}, {0x4F60, 0x4F60}, {0x4F61, 0x4F61}, {0x4F62, 0x4F62}, {0x4F63, 0x4F63}, {0x4F64, 0x4F64}, + {0x4F65, 0x4F65}, {0x4F66, 0x4F66}, {0x4F67, 0x4F67}, {0x4F68, 0x4F68}, {0x4F69, 0x4F69}, {0x4F6A, 0x4F6A}, {0x4F6B, 0x4F6B}, + {0x4F6C, 0x4F6C}, {0x4F6D, 0x4F6D}, {0x4F6E, 0x4F6E}, {0x4F6F, 0x4F6F}, {0x4F70, 0x4F70}, {0x4F71, 0x4F71}, {0x4F72, 0x4F72}, + {0x4F73, 0x4F73}, {0x4F74, 0x4F74}, {0x4F75, 0x4F75}, {0x4F76, 0x4F76}, {0x4F77, 0x4F77}, {0x4F78, 0x4F78}, {0x4F79, 0x4F79}, + {0x4F7A, 0x4F7A}, {0x4F7B, 0x4F7B}, {0x4F7C, 0x4F7C}, {0x4F7D, 0x4F7D}, {0x4F7E, 0x4F7E}, {0x4F7F, 0x4F7F}, {0x4F80, 0x4F80}, + {0x4F81, 0x4F81}, {0x4F82, 0x4F82}, {0x4F83, 0x4F83}, {0x4F84, 0x4F84}, {0x4F85, 0x4F85}, {0x4F86, 0x4F86}, {0x4F87, 0x4F87}, + {0x4F88, 0x4F88}, {0x4F89, 0x4F89}, {0x4F8A, 0x4F8A}, {0x4F8B, 0x4F8B}, {0x4F8C, 0x4F8C}, {0x4F8D, 0x4F8D}, {0x4F8E, 0x4F8E}, + {0x4F8F, 0x4F8F}, {0x4F90, 0x4F90}, {0x4F91, 0x4F91}, {0x4F92, 0x4F92}, {0x4F93, 0x4F93}, {0x4F94, 0x4F94}, {0x4F95, 0x4F95}, + {0x4F96, 0x4F96}, {0x4F97, 0x4F97}, {0x4F98, 0x4F98}, {0x4F99, 0x4F99}, {0x4F9A, 0x4F9A}, {0x4F9B, 0x4F9B}, {0x4F9C, 0x4F9C}, + {0x4F9D, 0x4F9D}, {0x4F9E, 0x4F9E}, {0x4F9F, 0x4F9F}, {0x4FA0, 0x4FA0}, {0x4FA1, 0x4FA1}, {0x4FA2, 0x4FA2}, {0x4FA3, 0x4FA3}, + {0x4FA4, 0x4FA4}, {0x4FA5, 0x4FA5}, {0x4FA6, 0x4FA6}, {0x4FA7, 0x4FA7}, {0x4FA8, 0x4FA8}, {0x4FA9, 0x4FA9}, {0x4FAA, 0x4FAA}, + {0x4FAB, 0x4FAB}, {0x4FAC, 0x4FAC}, {0x4FAD, 0x4FAD}, {0x4FAE, 0x4FAE}, {0x4FAF, 0x4FAF}, {0x4FB0, 0x4FB0}, {0x4FB1, 0x4FB1}, + {0x4FB2, 0x4FB2}, {0x4FB3, 0x4FB3}, {0x4FB4, 0x4FB4}, {0x4FB5, 0x4FB5}, {0x4FB6, 0x4FB6}, {0x4FB7, 0x4FB7}, {0x4FB8, 0x4FB8}, + {0x4FB9, 0x4FB9}, {0x4FBA, 0x4FBA}, {0x4FBB, 0x4FBB}, {0x4FBC, 0x4FBC}, {0x4FBD, 0x4FBD}, {0x4FBE, 0x4FBE}, {0x4FBF, 0x4FBF}, + {0x4FC0, 0x4FC0}, {0x4FC1, 0x4FC1}, {0x4FC2, 0x4FC2}, {0x4FC3, 0x4FC3}, {0x4FC4, 0x4FC4}, {0x4FC5, 0x4FC5}, {0x4FC6, 0x4FC6}, + {0x4FC7, 0x4FC7}, {0x4FC8, 0x4FC8}, {0x4FC9, 0x4FC9}, {0x4FCA, 0x4FCA}, {0x4FCB, 0x4FCB}, {0x4FCC, 0x4FCC}, {0x4FCD, 0x4FCD}, + {0x4FCE, 0x4FCE}, {0x4FCF, 0x4FCF}, {0x4FD0, 0x4FD0}, {0x4FD1, 0x4FD1}, {0x4FD2, 0x4FD2}, {0x4FD3, 0x4FD3}, {0x4FD4, 0x4FD4}, + {0x4FD5, 0x4FD5}, {0x4FD6, 0x4FD6}, {0x4FD7, 0x4FD7}, {0x4FD8, 0x4FD8}, {0x4FD9, 0x4FD9}, {0x4FDA, 0x4FDA}, {0x4FDB, 0x4FDB}, + {0x4FDC, 0x4FDC}, {0x4FDD, 0x4FDD}, {0x4FDE, 0x4FDE}, {0x4FDF, 0x4FDF}, {0x4FE0, 0x4FE0}, {0x4FE1, 0x4FE1}, {0x4FE2, 0x4FE2}, + {0x4FE3, 0x4FE3}, {0x4FE4, 0x4FE4}, {0x4FE5, 0x4FE5}, {0x4FE6, 0x4FE6}, {0x4FE7, 0x4FE7}, {0x4FE8, 0x4FE8}, {0x4FE9, 0x4FE9}, + {0x4FEA, 0x4FEA}, {0x4FEB, 0x4FEB}, {0x4FEC, 0x4FEC}, {0x4FED, 0x4FED}, {0x4FEE, 0x4FEE}, {0x4FEF, 0x4FEF}, {0x4FF0, 0x4FF0}, + {0x4FF1, 0x4FF1}, {0x4FF2, 0x4FF2}, {0x4FF3, 0x4FF3}, {0x4FF4, 0x4FF4}, {0x4FF5, 0x4FF5}, {0x4FF6, 0x4FF6}, {0x4FF7, 0x4FF7}, + {0x4FF8, 0x4FF8}, {0x4FF9, 0x4FF9}, {0x4FFA, 0x4FFA}, {0x4FFB, 0x4FFB}, {0x4FFC, 0x4FFC}, {0x4FFD, 0x4FFD}, {0x4FFE, 0x4FFE}, + {0x4FFF, 0x4FFF}, {0x5000, 0x5000}, {0x5001, 0x5001}, {0x5002, 0x5002}, {0x5003, 0x5003}, {0x5004, 0x5004}, {0x5005, 0x5005}, + {0x5006, 0x5006}, {0x5007, 0x5007}, {0x5008, 0x5008}, {0x5009, 0x5009}, {0x500A, 0x500A}, {0x500B, 0x500B}, {0x500C, 0x500C}, + {0x500D, 0x500D}, {0x500E, 0x500E}, {0x500F, 0x500F}, {0x5010, 0x5010}, {0x5011, 0x5011}, {0x5012, 0x5012}, {0x5013, 0x5013}, + {0x5014, 0x5014}, {0x5015, 0x5015}, {0x5016, 0x5016}, {0x5017, 0x5017}, {0x5018, 0x5018}, {0x5019, 0x5019}, {0x501A, 0x501A}, + {0x501B, 0x501B}, {0x501C, 0x501C}, {0x501D, 0x501D}, {0x501E, 0x501E}, {0x501F, 0x501F}, {0x5020, 0x5020}, {0x5021, 0x5021}, + {0x5022, 0x5022}, {0x5023, 0x5023}, {0x5024, 0x5024}, {0x5025, 0x5025}, {0x5026, 0x5026}, {0x5027, 0x5027}, {0x5028, 0x5028}, + {0x5029, 0x5029}, {0x502A, 0x502A}, {0x502B, 0x502B}, {0x502C, 0x502C}, {0x502D, 0x502D}, {0x502E, 0x502E}, {0x502F, 0x502F}, + {0x5030, 0x5030}, {0x5031, 0x5031}, {0x5032, 0x5032}, {0x5033, 0x5033}, {0x5034, 0x5034}, {0x5035, 0x5035}, {0x5036, 0x5036}, + {0x5037, 0x5037}, {0x5038, 0x5038}, {0x5039, 0x5039}, {0x503A, 0x503A}, {0x503B, 0x503B}, {0x503C, 0x503C}, {0x503D, 0x503D}, + {0x503E, 0x503E}, {0x503F, 0x503F}, {0x5040, 0x5040}, {0x5041, 0x5041}, {0x5042, 0x5042}, {0x5043, 0x5043}, {0x5044, 0x5044}, + {0x5045, 0x5045}, {0x5046, 0x5046}, {0x5047, 0x5047}, {0x5048, 0x5048}, {0x5049, 0x5049}, {0x504A, 0x504A}, {0x504B, 0x504B}, + {0x504C, 0x504C}, {0x504D, 0x504D}, {0x504E, 0x504E}, {0x504F, 0x504F}, {0x5050, 0x5050}, {0x5051, 0x5051}, {0x5052, 0x5052}, + {0x5053, 0x5053}, {0x5054, 0x5054}, {0x5055, 0x5055}, {0x5056, 0x5056}, {0x5057, 0x5057}, {0x5058, 0x5058}, {0x5059, 0x5059}, + {0x505A, 0x505A}, {0x505B, 0x505B}, {0x505C, 0x505C}, {0x505D, 0x505D}, {0x505E, 0x505E}, {0x505F, 0x505F}, {0x5060, 0x5060}, + {0x5061, 0x5061}, {0x5062, 0x5062}, {0x5063, 0x5063}, {0x5064, 0x5064}, {0x5065, 0x5065}, {0x5066, 0x5066}, {0x5067, 0x5067}, + {0x5068, 0x5068}, {0x5069, 0x5069}, {0x506A, 0x506A}, {0x506B, 0x506B}, {0x506C, 0x506C}, {0x506D, 0x506D}, {0x506E, 0x506E}, + {0x506F, 0x506F}, {0x5070, 0x5070}, {0x5071, 0x5071}, {0x5072, 0x5072}, {0x5073, 0x5073}, {0x5074, 0x5074}, {0x5075, 0x5075}, + {0x5076, 0x5076}, {0x5077, 0x5077}, {0x5078, 0x5078}, {0x5079, 0x5079}, {0x507A, 0x507A}, {0x507B, 0x507B}, {0x507C, 0x507C}, + {0x507D, 0x507D}, {0x507E, 0x507E}, {0x507F, 0x507F}, {0x5080, 0x5080}, {0x5081, 0x5081}, {0x5082, 0x5082}, {0x5083, 0x5083}, + {0x5084, 0x5084}, {0x5085, 0x5085}, {0x5086, 0x5086}, {0x5087, 0x5087}, {0x5088, 0x5088}, {0x5089, 0x5089}, {0x508A, 0x508A}, + {0x508B, 0x508B}, {0x508C, 0x508C}, {0x508D, 0x508D}, {0x508E, 0x508E}, {0x508F, 0x508F}, {0x5090, 0x5090}, {0x5091, 0x5091}, + {0x5092, 0x5092}, {0x5093, 0x5093}, {0x5094, 0x5094}, {0x5095, 0x5095}, {0x5096, 0x5096}, {0x5097, 0x5097}, {0x5098, 0x5098}, + {0x5099, 0x5099}, {0x509A, 0x509A}, {0x509B, 0x509B}, {0x509C, 0x509C}, {0x509D, 0x509D}, {0x509E, 0x509E}, {0x509F, 0x509F}, + {0x50A0, 0x50A0}, {0x50A1, 0x50A1}, {0x50A2, 0x50A2}, {0x50A3, 0x50A3}, {0x50A4, 0x50A4}, {0x50A5, 0x50A5}, {0x50A6, 0x50A6}, + {0x50A7, 0x50A7}, {0x50A8, 0x50A8}, {0x50A9, 0x50A9}, {0x50AA, 0x50AA}, {0x50AB, 0x50AB}, {0x50AC, 0x50AC}, {0x50AD, 0x50AD}, + {0x50AE, 0x50AE}, {0x50AF, 0x50AF}, {0x50B0, 0x50B0}, {0x50B1, 0x50B1}, {0x50B2, 0x50B2}, {0x50B3, 0x50B3}, {0x50B4, 0x50B4}, + {0x50B5, 0x50B5}, {0x50B6, 0x50B6}, {0x50B7, 0x50B7}, {0x50B8, 0x50B8}, {0x50B9, 0x50B9}, {0x50BA, 0x50BA}, {0x50BB, 0x50BB}, + {0x50BC, 0x50BC}, {0x50BD, 0x50BD}, {0x50BE, 0x50BE}, {0x50BF, 0x50BF}, {0x50C0, 0x50C0}, {0x50C1, 0x50C1}, {0x50C2, 0x50C2}, + {0x50C3, 0x50C3}, {0x50C4, 0x50C4}, {0x50C5, 0x50C5}, {0x50C6, 0x50C6}, {0x50C7, 0x50C7}, {0x50C8, 0x50C8}, {0x50C9, 0x50C9}, + {0x50CA, 0x50CA}, {0x50CB, 0x50CB}, {0x50CC, 0x50CC}, {0x50CD, 0x50CD}, {0x50CE, 0x50CE}, {0x50CF, 0x50CF}, {0x50D0, 0x50D0}, + {0x50D1, 0x50D1}, {0x50D2, 0x50D2}, {0x50D3, 0x50D3}, {0x50D4, 0x50D4}, {0x50D5, 0x50D5}, {0x50D6, 0x50D6}, {0x50D7, 0x50D7}, + {0x50D8, 0x50D8}, {0x50D9, 0x50D9}, {0x50DA, 0x50DA}, {0x50DB, 0x50DB}, {0x50DC, 0x50DC}, {0x50DD, 0x50DD}, {0x50DE, 0x50DE}, + {0x50DF, 0x50DF}, {0x50E0, 0x50E0}, {0x50E1, 0x50E1}, {0x50E2, 0x50E2}, {0x50E3, 0x50E3}, {0x50E4, 0x50E4}, {0x50E5, 0x50E5}, + {0x50E6, 0x50E6}, {0x50E7, 0x50E7}, {0x50E8, 0x50E8}, {0x50E9, 0x50E9}, {0x50EA, 0x50EA}, {0x50EB, 0x50EB}, {0x50EC, 0x50EC}, + {0x50ED, 0x50ED}, {0x50EE, 0x50EE}, {0x50EF, 0x50EF}, {0x50F0, 0x50F0}, {0x50F1, 0x50F1}, {0x50F2, 0x50F2}, {0x50F3, 0x50F3}, + {0x50F4, 0x50F4}, {0x50F5, 0x50F5}, {0x50F6, 0x50F6}, {0x50F7, 0x50F7}, {0x50F8, 0x50F8}, {0x50F9, 0x50F9}, {0x50FA, 0x50FA}, + {0x50FB, 0x50FB}, {0x50FC, 0x50FC}, {0x50FD, 0x50FD}, {0x50FE, 0x50FE}, {0x50FF, 0x50FF}, {0x5100, 0x5100}, {0x5101, 0x5101}, + {0x5102, 0x5102}, {0x5103, 0x5103}, {0x5104, 0x5104}, {0x5105, 0x5105}, {0x5106, 0x5106}, {0x5107, 0x5107}, {0x5108, 0x5108}, + {0x5109, 0x5109}, {0x510A, 0x510A}, {0x510B, 0x510B}, {0x510C, 0x510C}, {0x510D, 0x510D}, {0x510E, 0x510E}, {0x510F, 0x510F}, + {0x5110, 0x5110}, {0x5111, 0x5111}, {0x5112, 0x5112}, {0x5113, 0x5113}, {0x5114, 0x5114}, {0x5115, 0x5115}, {0x5116, 0x5116}, + {0x5117, 0x5117}, {0x5118, 0x5118}, {0x5119, 0x5119}, {0x511A, 0x511A}, {0x511B, 0x511B}, {0x511C, 0x511C}, {0x511D, 0x511D}, + {0x511E, 0x511E}, {0x511F, 0x511F}, {0x5120, 0x5120}, {0x5121, 0x5121}, {0x5122, 0x5122}, {0x5123, 0x5123}, {0x5124, 0x5124}, + {0x5125, 0x5125}, {0x5126, 0x5126}, {0x5127, 0x5127}, {0x5128, 0x5128}, {0x5129, 0x5129}, {0x512A, 0x512A}, {0x512B, 0x512B}, + {0x512C, 0x512C}, {0x512D, 0x512D}, {0x512E, 0x512E}, {0x512F, 0x512F}, {0x5130, 0x5130}, {0x5131, 0x5131}, {0x5132, 0x5132}, + {0x5133, 0x5133}, {0x5134, 0x5134}, {0x5135, 0x5135}, {0x5136, 0x5136}, {0x5137, 0x5137}, {0x5138, 0x5138}, {0x5139, 0x5139}, + {0x513A, 0x513A}, {0x513B, 0x513B}, {0x513C, 0x513C}, {0x513D, 0x513D}, {0x513E, 0x513E}, {0x513F, 0x513F}, {0x5140, 0x5140}, + {0x5141, 0x5141}, {0x5142, 0x5142}, {0x5143, 0x5143}, {0x5144, 0x5144}, {0x5145, 0x5145}, {0x5146, 0x5146}, {0x5147, 0x5147}, + {0x5148, 0x5148}, {0x5149, 0x5149}, {0x514A, 0x514A}, {0x514B, 0x514B}, {0x514C, 0x514C}, {0x514D, 0x514D}, {0x514E, 0x514E}, + {0x514F, 0x514F}, {0x5150, 0x5150}, {0x5151, 0x5151}, {0x5152, 0x5152}, {0x5153, 0x5153}, {0x5154, 0x5154}, {0x5155, 0x5155}, + {0x5156, 0x5156}, {0x5157, 0x5157}, {0x5158, 0x5158}, {0x5159, 0x5159}, {0x515A, 0x515A}, {0x515B, 0x515B}, {0x515C, 0x515C}, + {0x515D, 0x515D}, {0x515E, 0x515E}, {0x515F, 0x515F}, {0x5160, 0x5160}, {0x5161, 0x5161}, {0x5162, 0x5162}, {0x5163, 0x5163}, + {0x5164, 0x5164}, {0x5165, 0x5165}, {0x5166, 0x5166}, {0x5167, 0x5167}, {0x5168, 0x5168}, {0x5169, 0x5169}, {0x516A, 0x516A}, + {0x516B, 0x516B}, {0x516C, 0x516C}, {0x516D, 0x516D}, {0x516E, 0x516E}, {0x516F, 0x516F}, {0x5170, 0x5170}, {0x5171, 0x5171}, + {0x5172, 0x5172}, {0x5173, 0x5173}, {0x5174, 0x5174}, {0x5175, 0x5175}, {0x5176, 0x5176}, {0x5177, 0x5177}, {0x5178, 0x5178}, + {0x5179, 0x5179}, {0x517A, 0x517A}, {0x517B, 0x517B}, {0x517C, 0x517C}, {0x517D, 0x517D}, {0x517E, 0x517E}, {0x517F, 0x517F}, + {0x5180, 0x5180}, {0x5181, 0x5181}, {0x5182, 0x5182}, {0x5183, 0x5183}, {0x5184, 0x5184}, {0x5185, 0x5185}, {0x5186, 0x5186}, + {0x5187, 0x5187}, {0x5188, 0x5188}, {0x5189, 0x5189}, {0x518A, 0x518A}, {0x518B, 0x518B}, {0x518C, 0x518C}, {0x518D, 0x518D}, + {0x518E, 0x518E}, {0x518F, 0x518F}, {0x5190, 0x5190}, {0x5191, 0x5191}, {0x5192, 0x5192}, {0x5193, 0x5193}, {0x5194, 0x5194}, + {0x5195, 0x5195}, {0x5196, 0x5196}, {0x5197, 0x5197}, {0x5198, 0x5198}, {0x5199, 0x5199}, {0x519A, 0x519A}, {0x519B, 0x519B}, + {0x519C, 0x519C}, {0x519D, 0x519D}, {0x519E, 0x519E}, {0x519F, 0x519F}, {0x51A0, 0x51A0}, {0x51A1, 0x51A1}, {0x51A2, 0x51A2}, + {0x51A3, 0x51A3}, {0x51A4, 0x51A4}, {0x51A5, 0x51A5}, {0x51A6, 0x51A6}, {0x51A7, 0x51A7}, {0x51A8, 0x51A8}, {0x51A9, 0x51A9}, + {0x51AA, 0x51AA}, {0x51AB, 0x51AB}, {0x51AC, 0x51AC}, {0x51AD, 0x51AD}, {0x51AE, 0x51AE}, {0x51AF, 0x51AF}, {0x51B0, 0x51B0}, + {0x51B1, 0x51B1}, {0x51B2, 0x51B2}, {0x51B3, 0x51B3}, {0x51B4, 0x51B4}, {0x51B5, 0x51B5}, {0x51B6, 0x51B6}, {0x51B7, 0x51B7}, + {0x51B8, 0x51B8}, {0x51B9, 0x51B9}, {0x51BA, 0x51BA}, {0x51BB, 0x51BB}, {0x51BC, 0x51BC}, {0x51BD, 0x51BD}, {0x51BE, 0x51BE}, + {0x51BF, 0x51BF}, {0x51C0, 0x51C0}, {0x51C1, 0x51C1}, {0x51C2, 0x51C2}, {0x51C3, 0x51C3}, {0x51C4, 0x51C4}, {0x51C5, 0x51C5}, + {0x51C6, 0x51C6}, {0x51C7, 0x51C7}, {0x51C8, 0x51C8}, {0x51C9, 0x51C9}, {0x51CA, 0x51CA}, {0x51CB, 0x51CB}, {0x51CC, 0x51CC}, + {0x51CD, 0x51CD}, {0x51CE, 0x51CE}, {0x51CF, 0x51CF}, {0x51D0, 0x51D0}, {0x51D1, 0x51D1}, {0x51D2, 0x51D2}, {0x51D3, 0x51D3}, + {0x51D4, 0x51D4}, {0x51D5, 0x51D5}, {0x51D6, 0x51D6}, {0x51D7, 0x51D7}, {0x51D8, 0x51D8}, {0x51D9, 0x51D9}, {0x51DA, 0x51DA}, + {0x51DB, 0x51DB}, {0x51DC, 0x51DC}, {0x51DD, 0x51DD}, {0x51DE, 0x51DE}, {0x51DF, 0x51DF}, {0x51E0, 0x51E0}, {0x51E1, 0x51E1}, + {0x51E2, 0x51E2}, {0x51E3, 0x51E3}, {0x51E4, 0x51E4}, {0x51E5, 0x51E5}, {0x51E6, 0x51E6}, {0x51E7, 0x51E7}, {0x51E8, 0x51E8}, + {0x51E9, 0x51E9}, {0x51EA, 0x51EA}, {0x51EB, 0x51EB}, {0x51EC, 0x51EC}, {0x51ED, 0x51ED}, {0x51EE, 0x51EE}, {0x51EF, 0x51EF}, + {0x51F0, 0x51F0}, {0x51F1, 0x51F1}, {0x51F2, 0x51F2}, {0x51F3, 0x51F3}, {0x51F4, 0x51F4}, {0x51F5, 0x51F5}, {0x51F6, 0x51F6}, + {0x51F7, 0x51F7}, {0x51F8, 0x51F8}, {0x51F9, 0x51F9}, {0x51FA, 0x51FA}, {0x51FB, 0x51FB}, {0x51FC, 0x51FC}, {0x51FD, 0x51FD}, + {0x51FE, 0x51FE}, {0x51FF, 0x51FF}, {0x5200, 0x5200}, {0x5201, 0x5201}, {0x5202, 0x5202}, {0x5203, 0x5203}, {0x5204, 0x5204}, + {0x5205, 0x5205}, {0x5206, 0x5206}, {0x5207, 0x5207}, {0x5208, 0x5208}, {0x5209, 0x5209}, {0x520A, 0x520A}, {0x520B, 0x520B}, + {0x520C, 0x520C}, {0x520D, 0x520D}, {0x520E, 0x520E}, {0x520F, 0x520F}, {0x5210, 0x5210}, {0x5211, 0x5211}, {0x5212, 0x5212}, + {0x5213, 0x5213}, {0x5214, 0x5214}, {0x5215, 0x5215}, {0x5216, 0x5216}, {0x5217, 0x5217}, {0x5218, 0x5218}, {0x5219, 0x5219}, + {0x521A, 0x521A}, {0x521B, 0x521B}, {0x521C, 0x521C}, {0x521D, 0x521D}, {0x521E, 0x521E}, {0x521F, 0x521F}, {0x5220, 0x5220}, + {0x5221, 0x5221}, {0x5222, 0x5222}, {0x5223, 0x5223}, {0x5224, 0x5224}, {0x5225, 0x5225}, {0x5226, 0x5226}, {0x5227, 0x5227}, + {0x5228, 0x5228}, {0x5229, 0x5229}, {0x522A, 0x522A}, {0x522B, 0x522B}, {0x522C, 0x522C}, {0x522D, 0x522D}, {0x522E, 0x522E}, + {0x522F, 0x522F}, {0x5230, 0x5230}, {0x5231, 0x5231}, {0x5232, 0x5232}, {0x5233, 0x5233}, {0x5234, 0x5234}, {0x5235, 0x5235}, + {0x5236, 0x5236}, {0x5237, 0x5237}, {0x5238, 0x5238}, {0x5239, 0x5239}, {0x523A, 0x523A}, {0x523B, 0x523B}, {0x523C, 0x523C}, + {0x523D, 0x523D}, {0x523E, 0x523E}, {0x523F, 0x523F}, {0x5240, 0x5240}, {0x5241, 0x5241}, {0x5242, 0x5242}, {0x5243, 0x5243}, + {0x5244, 0x5244}, {0x5245, 0x5245}, {0x5246, 0x5246}, {0x5247, 0x5247}, {0x5248, 0x5248}, {0x5249, 0x5249}, {0x524A, 0x524A}, + {0x524B, 0x524B}, {0x524C, 0x524C}, {0x524D, 0x524D}, {0x524E, 0x524E}, {0x524F, 0x524F}, {0x5250, 0x5250}, {0x5251, 0x5251}, + {0x5252, 0x5252}, {0x5253, 0x5253}, {0x5254, 0x5254}, {0x5255, 0x5255}, {0x5256, 0x5256}, {0x5257, 0x5257}, {0x5258, 0x5258}, + {0x5259, 0x5259}, {0x525A, 0x525A}, {0x525B, 0x525B}, {0x525C, 0x525C}, {0x525D, 0x525D}, {0x525E, 0x525E}, {0x525F, 0x525F}, + {0x5260, 0x5260}, {0x5261, 0x5261}, {0x5262, 0x5262}, {0x5263, 0x5263}, {0x5264, 0x5264}, {0x5265, 0x5265}, {0x5266, 0x5266}, + {0x5267, 0x5267}, {0x5268, 0x5268}, {0x5269, 0x5269}, {0x526A, 0x526A}, {0x526B, 0x526B}, {0x526C, 0x526C}, {0x526D, 0x526D}, + {0x526E, 0x526E}, {0x526F, 0x526F}, {0x5270, 0x5270}, {0x5271, 0x5271}, {0x5272, 0x5272}, {0x5273, 0x5273}, {0x5274, 0x5274}, + {0x5275, 0x5275}, {0x5276, 0x5276}, {0x5277, 0x5277}, {0x5278, 0x5278}, {0x5279, 0x5279}, {0x527A, 0x527A}, {0x527B, 0x527B}, + {0x527C, 0x527C}, {0x527D, 0x527D}, {0x527E, 0x527E}, {0x527F, 0x527F}, {0x5280, 0x5280}, {0x5281, 0x5281}, {0x5282, 0x5282}, + {0x5283, 0x5283}, {0x5284, 0x5284}, {0x5285, 0x5285}, {0x5286, 0x5286}, {0x5287, 0x5287}, {0x5288, 0x5288}, {0x5289, 0x5289}, + {0x528A, 0x528A}, {0x528B, 0x528B}, {0x528C, 0x528C}, {0x528D, 0x528D}, {0x528E, 0x528E}, {0x528F, 0x528F}, {0x5290, 0x5290}, + {0x5291, 0x5291}, {0x5292, 0x5292}, {0x5293, 0x5293}, {0x5294, 0x5294}, {0x5295, 0x5295}, {0x5296, 0x5296}, {0x5297, 0x5297}, + {0x5298, 0x5298}, {0x5299, 0x5299}, {0x529A, 0x529A}, {0x529B, 0x529B}, {0x529C, 0x529C}, {0x529D, 0x529D}, {0x529E, 0x529E}, + {0x529F, 0x529F}, {0x52A0, 0x52A0}, {0x52A1, 0x52A1}, {0x52A2, 0x52A2}, {0x52A3, 0x52A3}, {0x52A4, 0x52A4}, {0x52A5, 0x52A5}, + {0x52A6, 0x52A6}, {0x52A7, 0x52A7}, {0x52A8, 0x52A8}, {0x52A9, 0x52A9}, {0x52AA, 0x52AA}, {0x52AB, 0x52AB}, {0x52AC, 0x52AC}, + {0x52AD, 0x52AD}, {0x52AE, 0x52AE}, {0x52AF, 0x52AF}, {0x52B0, 0x52B0}, {0x52B1, 0x52B1}, {0x52B2, 0x52B2}, {0x52B3, 0x52B3}, + {0x52B4, 0x52B4}, {0x52B5, 0x52B5}, {0x52B6, 0x52B6}, {0x52B7, 0x52B7}, {0x52B8, 0x52B8}, {0x52B9, 0x52B9}, {0x52BA, 0x52BA}, + {0x52BB, 0x52BB}, {0x52BC, 0x52BC}, {0x52BD, 0x52BD}, {0x52BE, 0x52BE}, {0x52BF, 0x52BF}, {0x52C0, 0x52C0}, {0x52C1, 0x52C1}, + {0x52C2, 0x52C2}, {0x52C3, 0x52C3}, {0x52C4, 0x52C4}, {0x52C5, 0x52C5}, {0x52C6, 0x52C6}, {0x52C7, 0x52C7}, {0x52C8, 0x52C8}, + {0x52C9, 0x52C9}, {0x52CA, 0x52CA}, {0x52CB, 0x52CB}, {0x52CC, 0x52CC}, {0x52CD, 0x52CD}, {0x52CE, 0x52CE}, {0x52CF, 0x52CF}, + {0x52D0, 0x52D0}, {0x52D1, 0x52D1}, {0x52D2, 0x52D2}, {0x52D3, 0x52D3}, {0x52D4, 0x52D4}, {0x52D5, 0x52D5}, {0x52D6, 0x52D6}, + {0x52D7, 0x52D7}, {0x52D8, 0x52D8}, {0x52D9, 0x52D9}, {0x52DA, 0x52DA}, {0x52DB, 0x52DB}, {0x52DC, 0x52DC}, {0x52DD, 0x52DD}, + {0x52DE, 0x52DE}, {0x52DF, 0x52DF}, {0x52E0, 0x52E0}, {0x52E1, 0x52E1}, {0x52E2, 0x52E2}, {0x52E3, 0x52E3}, {0x52E4, 0x52E4}, + {0x52E5, 0x52E5}, {0x52E6, 0x52E6}, {0x52E7, 0x52E7}, {0x52E8, 0x52E8}, {0x52E9, 0x52E9}, {0x52EA, 0x52EA}, {0x52EB, 0x52EB}, + {0x52EC, 0x52EC}, {0x52ED, 0x52ED}, {0x52EE, 0x52EE}, {0x52EF, 0x52EF}, {0x52F0, 0x52F0}, {0x52F1, 0x52F1}, {0x52F2, 0x52F2}, + {0x52F3, 0x52F3}, {0x52F4, 0x52F4}, {0x52F5, 0x52F5}, {0x52F6, 0x52F6}, {0x52F7, 0x52F7}, {0x52F8, 0x52F8}, {0x52F9, 0x52F9}, + {0x52FA, 0x52FA}, {0x52FB, 0x52FB}, {0x52FC, 0x52FC}, {0x52FD, 0x52FD}, {0x52FE, 0x52FE}, {0x52FF, 0x52FF}, {0x5300, 0x5300}, + {0x5301, 0x5301}, {0x5302, 0x5302}, {0x5303, 0x5303}, {0x5304, 0x5304}, {0x5305, 0x5305}, {0x5306, 0x5306}, {0x5307, 0x5307}, + {0x5308, 0x5308}, {0x5309, 0x5309}, {0x530A, 0x530A}, {0x530B, 0x530B}, {0x530C, 0x530C}, {0x530D, 0x530D}, {0x530E, 0x530E}, + {0x530F, 0x530F}, {0x5310, 0x5310}, {0x5311, 0x5311}, {0x5312, 0x5312}, {0x5313, 0x5313}, {0x5314, 0x5314}, {0x5315, 0x5315}, + {0x5316, 0x5316}, {0x5317, 0x5317}, {0x5318, 0x5318}, {0x5319, 0x5319}, {0x531A, 0x531A}, {0x531B, 0x531B}, {0x531C, 0x531C}, + {0x531D, 0x531D}, {0x531E, 0x531E}, {0x531F, 0x531F}, {0x5320, 0x5320}, {0x5321, 0x5321}, {0x5322, 0x5322}, {0x5323, 0x5323}, + {0x5324, 0x5324}, {0x5325, 0x5325}, {0x5326, 0x5326}, {0x5327, 0x5327}, {0x5328, 0x5328}, {0x5329, 0x5329}, {0x532A, 0x532A}, + {0x532B, 0x532B}, {0x532C, 0x532C}, {0x532D, 0x532D}, {0x532E, 0x532E}, {0x532F, 0x532F}, {0x5330, 0x5330}, {0x5331, 0x5331}, + {0x5332, 0x5332}, {0x5333, 0x5333}, {0x5334, 0x5334}, {0x5335, 0x5335}, {0x5336, 0x5336}, {0x5337, 0x5337}, {0x5338, 0x5338}, + {0x5339, 0x5339}, {0x533A, 0x533A}, {0x533B, 0x533B}, {0x533C, 0x533C}, {0x533D, 0x533D}, {0x533E, 0x533E}, {0x533F, 0x533F}, + {0x5340, 0x5340}, {0x5341, 0x5341}, {0x5342, 0x5342}, {0x5343, 0x5343}, {0x5344, 0x5344}, {0x5345, 0x5345}, {0x5346, 0x5346}, + {0x5347, 0x5347}, {0x5348, 0x5348}, {0x5349, 0x5349}, {0x534A, 0x534A}, {0x534B, 0x534B}, {0x534C, 0x534C}, {0x534D, 0x534D}, + {0x534E, 0x534E}, {0x534F, 0x534F}, {0x5350, 0x5350}, {0x5351, 0x5351}, {0x5352, 0x5352}, {0x5353, 0x5353}, {0x5354, 0x5354}, + {0x5355, 0x5355}, {0x5356, 0x5356}, {0x5357, 0x5357}, {0x5358, 0x5358}, {0x5359, 0x5359}, {0x535A, 0x535A}, {0x535B, 0x535B}, + {0x535C, 0x535C}, {0x535D, 0x535D}, {0x535E, 0x535E}, {0x535F, 0x535F}, {0x5360, 0x5360}, {0x5361, 0x5361}, {0x5362, 0x5362}, + {0x5363, 0x5363}, {0x5364, 0x5364}, {0x5365, 0x5365}, {0x5366, 0x5366}, {0x5367, 0x5367}, {0x5368, 0x5368}, {0x5369, 0x5369}, + {0x536A, 0x536A}, {0x536B, 0x536B}, {0x536C, 0x536C}, {0x536D, 0x536D}, {0x536E, 0x536E}, {0x536F, 0x536F}, {0x5370, 0x5370}, + {0x5371, 0x5371}, {0x5372, 0x5372}, {0x5373, 0x5373}, {0x5374, 0x5374}, {0x5375, 0x5375}, {0x5376, 0x5376}, {0x5377, 0x5377}, + {0x5378, 0x5378}, {0x5379, 0x5379}, {0x537A, 0x537A}, {0x537B, 0x537B}, {0x537C, 0x537C}, {0x537D, 0x537D}, {0x537E, 0x537E}, + {0x537F, 0x537F}, {0x5380, 0x5380}, {0x5381, 0x5381}, {0x5382, 0x5382}, {0x5383, 0x5383}, {0x5384, 0x5384}, {0x5385, 0x5385}, + {0x5386, 0x5386}, {0x5387, 0x5387}, {0x5388, 0x5388}, {0x5389, 0x5389}, {0x538A, 0x538A}, {0x538B, 0x538B}, {0x538C, 0x538C}, + {0x538D, 0x538D}, {0x538E, 0x538E}, {0x538F, 0x538F}, {0x5390, 0x5390}, {0x5391, 0x5391}, {0x5392, 0x5392}, {0x5393, 0x5393}, + {0x5394, 0x5394}, {0x5395, 0x5395}, {0x5396, 0x5396}, {0x5397, 0x5397}, {0x5398, 0x5398}, {0x5399, 0x5399}, {0x539A, 0x539A}, + {0x539B, 0x539B}, {0x539C, 0x539C}, {0x539D, 0x539D}, {0x539E, 0x539E}, {0x539F, 0x539F}, {0x53A0, 0x53A0}, {0x53A1, 0x53A1}, + {0x53A2, 0x53A2}, {0x53A3, 0x53A3}, {0x53A4, 0x53A4}, {0x53A5, 0x53A5}, {0x53A6, 0x53A6}, {0x53A7, 0x53A7}, {0x53A8, 0x53A8}, + {0x53A9, 0x53A9}, {0x53AA, 0x53AA}, {0x53AB, 0x53AB}, {0x53AC, 0x53AC}, {0x53AD, 0x53AD}, {0x53AE, 0x53AE}, {0x53AF, 0x53AF}, + {0x53B0, 0x53B0}, {0x53B1, 0x53B1}, {0x53B2, 0x53B2}, {0x53B3, 0x53B3}, {0x53B4, 0x53B4}, {0x53B5, 0x53B5}, {0x53B6, 0x53B6}, + {0x53B7, 0x53B7}, {0x53B8, 0x53B8}, {0x53B9, 0x53B9}, {0x53BA, 0x53BA}, {0x53BB, 0x53BB}, {0x53BC, 0x53BC}, {0x53BD, 0x53BD}, + {0x53BE, 0x53BE}, {0x53BF, 0x53BF}, {0x53C0, 0x53C0}, {0x53C1, 0x53C1}, {0x53C2, 0x53C2}, {0x53C3, 0x53C3}, {0x53C4, 0x53C4}, + {0x53C5, 0x53C5}, {0x53C6, 0x53C6}, {0x53C7, 0x53C7}, {0x53C8, 0x53C8}, {0x53C9, 0x53C9}, {0x53CA, 0x53CA}, {0x53CB, 0x53CB}, + {0x53CC, 0x53CC}, {0x53CD, 0x53CD}, {0x53CE, 0x53CE}, {0x53CF, 0x53CF}, {0x53D0, 0x53D0}, {0x53D1, 0x53D1}, {0x53D2, 0x53D2}, + {0x53D3, 0x53D3}, {0x53D4, 0x53D4}, {0x53D5, 0x53D5}, {0x53D6, 0x53D6}, {0x53D7, 0x53D7}, {0x53D8, 0x53D8}, {0x53D9, 0x53D9}, + {0x53DA, 0x53DA}, {0x53DB, 0x53DB}, {0x53DC, 0x53DC}, {0x53DD, 0x53DD}, {0x53DE, 0x53DE}, {0x53DF, 0x53DF}, {0x53E0, 0x53E0}, + {0x53E1, 0x53E1}, {0x53E2, 0x53E2}, {0x53E3, 0x53E3}, {0x53E4, 0x53E4}, {0x53E5, 0x53E5}, {0x53E6, 0x53E6}, {0x53E7, 0x53E7}, + {0x53E8, 0x53E8}, {0x53E9, 0x53E9}, {0x53EA, 0x53EA}, {0x53EB, 0x53EB}, {0x53EC, 0x53EC}, {0x53ED, 0x53ED}, {0x53EE, 0x53EE}, + {0x53EF, 0x53EF}, {0x53F0, 0x53F0}, {0x53F1, 0x53F1}, {0x53F2, 0x53F2}, {0x53F3, 0x53F3}, {0x53F4, 0x53F4}, {0x53F5, 0x53F5}, + {0x53F6, 0x53F6}, {0x53F7, 0x53F7}, {0x53F8, 0x53F8}, {0x53F9, 0x53F9}, {0x53FA, 0x53FA}, {0x53FB, 0x53FB}, {0x53FC, 0x53FC}, + {0x53FD, 0x53FD}, {0x53FE, 0x53FE}, {0x53FF, 0x53FF}, {0x5400, 0x5400}, {0x5401, 0x5401}, {0x5402, 0x5402}, {0x5403, 0x5403}, + {0x5404, 0x5404}, {0x5405, 0x5405}, {0x5406, 0x5406}, {0x5407, 0x5407}, {0x5408, 0x5408}, {0x5409, 0x5409}, {0x540A, 0x540A}, + {0x540B, 0x540B}, {0x540C, 0x540C}, {0x540D, 0x540D}, {0x540E, 0x540E}, {0x540F, 0x540F}, {0x5410, 0x5410}, {0x5411, 0x5411}, + {0x5412, 0x5412}, {0x5413, 0x5413}, {0x5414, 0x5414}, {0x5415, 0x5415}, {0x5416, 0x5416}, {0x5417, 0x5417}, {0x5418, 0x5418}, + {0x5419, 0x5419}, {0x541A, 0x541A}, {0x541B, 0x541B}, {0x541C, 0x541C}, {0x541D, 0x541D}, {0x541E, 0x541E}, {0x541F, 0x541F}, + {0x5420, 0x5420}, {0x5421, 0x5421}, {0x5422, 0x5422}, {0x5423, 0x5423}, {0x5424, 0x5424}, {0x5425, 0x5425}, {0x5426, 0x5426}, + {0x5427, 0x5427}, {0x5428, 0x5428}, {0x5429, 0x5429}, {0x542A, 0x542A}, {0x542B, 0x542B}, {0x542C, 0x542C}, {0x542D, 0x542D}, + {0x542E, 0x542E}, {0x542F, 0x542F}, {0x5430, 0x5430}, {0x5431, 0x5431}, {0x5432, 0x5432}, {0x5433, 0x5433}, {0x5434, 0x5434}, + {0x5435, 0x5435}, {0x5436, 0x5436}, {0x5437, 0x5437}, {0x5438, 0x5438}, {0x5439, 0x5439}, {0x543A, 0x543A}, {0x543B, 0x543B}, + {0x543C, 0x543C}, {0x543D, 0x543D}, {0x543E, 0x543E}, {0x543F, 0x543F}, {0x5440, 0x5440}, {0x5441, 0x5441}, {0x5442, 0x5442}, + {0x5443, 0x5443}, {0x5444, 0x5444}, {0x5445, 0x5445}, {0x5446, 0x5446}, {0x5447, 0x5447}, {0x5448, 0x5448}, {0x5449, 0x5449}, + {0x544A, 0x544A}, {0x544B, 0x544B}, {0x544C, 0x544C}, {0x544D, 0x544D}, {0x544E, 0x544E}, {0x544F, 0x544F}, {0x5450, 0x5450}, + {0x5451, 0x5451}, {0x5452, 0x5452}, {0x5453, 0x5453}, {0x5454, 0x5454}, {0x5455, 0x5455}, {0x5456, 0x5456}, {0x5457, 0x5457}, + {0x5458, 0x5458}, {0x5459, 0x5459}, {0x545A, 0x545A}, {0x545B, 0x545B}, {0x545C, 0x545C}, {0x545D, 0x545D}, {0x545E, 0x545E}, + {0x545F, 0x545F}, {0x5460, 0x5460}, {0x5461, 0x5461}, {0x5462, 0x5462}, {0x5463, 0x5463}, {0x5464, 0x5464}, {0x5465, 0x5465}, + {0x5466, 0x5466}, {0x5467, 0x5467}, {0x5468, 0x5468}, {0x5469, 0x5469}, {0x546A, 0x546A}, {0x546B, 0x546B}, {0x546C, 0x546C}, + {0x546D, 0x546D}, {0x546E, 0x546E}, {0x546F, 0x546F}, {0x5470, 0x5470}, {0x5471, 0x5471}, {0x5472, 0x5472}, {0x5473, 0x5473}, + {0x5474, 0x5474}, {0x5475, 0x5475}, {0x5476, 0x5476}, {0x5477, 0x5477}, {0x5478, 0x5478}, {0x5479, 0x5479}, {0x547A, 0x547A}, + {0x547B, 0x547B}, {0x547C, 0x547C}, {0x547D, 0x547D}, {0x547E, 0x547E}, {0x547F, 0x547F}, {0x5480, 0x5480}, {0x5481, 0x5481}, + {0x5482, 0x5482}, {0x5483, 0x5483}, {0x5484, 0x5484}, {0x5485, 0x5485}, {0x5486, 0x5486}, {0x5487, 0x5487}, {0x5488, 0x5488}, + {0x5489, 0x5489}, {0x548A, 0x548A}, {0x548B, 0x548B}, {0x548C, 0x548C}, {0x548D, 0x548D}, {0x548E, 0x548E}, {0x548F, 0x548F}, + {0x5490, 0x5490}, {0x5491, 0x5491}, {0x5492, 0x5492}, {0x5493, 0x5493}, {0x5494, 0x5494}, {0x5495, 0x5495}, {0x5496, 0x5496}, + {0x5497, 0x5497}, {0x5498, 0x5498}, {0x5499, 0x5499}, {0x549A, 0x549A}, {0x549B, 0x549B}, {0x549C, 0x549C}, {0x549D, 0x549D}, + {0x549E, 0x549E}, {0x549F, 0x549F}, {0x54A0, 0x54A0}, {0x54A1, 0x54A1}, {0x54A2, 0x54A2}, {0x54A3, 0x54A3}, {0x54A4, 0x54A4}, + {0x54A5, 0x54A5}, {0x54A6, 0x54A6}, {0x54A7, 0x54A7}, {0x54A8, 0x54A8}, {0x54A9, 0x54A9}, {0x54AA, 0x54AA}, {0x54AB, 0x54AB}, + {0x54AC, 0x54AC}, {0x54AD, 0x54AD}, {0x54AE, 0x54AE}, {0x54AF, 0x54AF}, {0x54B0, 0x54B0}, {0x54B1, 0x54B1}, {0x54B2, 0x54B2}, + {0x54B3, 0x54B3}, {0x54B4, 0x54B4}, {0x54B5, 0x54B5}, {0x54B6, 0x54B6}, {0x54B7, 0x54B7}, {0x54B8, 0x54B8}, {0x54B9, 0x54B9}, + {0x54BA, 0x54BA}, {0x54BB, 0x54BB}, {0x54BC, 0x54BC}, {0x54BD, 0x54BD}, {0x54BE, 0x54BE}, {0x54BF, 0x54BF}, {0x54C0, 0x54C0}, + {0x54C1, 0x54C1}, {0x54C2, 0x54C2}, {0x54C3, 0x54C3}, {0x54C4, 0x54C4}, {0x54C5, 0x54C5}, {0x54C6, 0x54C6}, {0x54C7, 0x54C7}, + {0x54C8, 0x54C8}, {0x54C9, 0x54C9}, {0x54CA, 0x54CA}, {0x54CB, 0x54CB}, {0x54CC, 0x54CC}, {0x54CD, 0x54CD}, {0x54CE, 0x54CE}, + {0x54CF, 0x54CF}, {0x54D0, 0x54D0}, {0x54D1, 0x54D1}, {0x54D2, 0x54D2}, {0x54D3, 0x54D3}, {0x54D4, 0x54D4}, {0x54D5, 0x54D5}, + {0x54D6, 0x54D6}, {0x54D7, 0x54D7}, {0x54D8, 0x54D8}, {0x54D9, 0x54D9}, {0x54DA, 0x54DA}, {0x54DB, 0x54DB}, {0x54DC, 0x54DC}, + {0x54DD, 0x54DD}, {0x54DE, 0x54DE}, {0x54DF, 0x54DF}, {0x54E0, 0x54E0}, {0x54E1, 0x54E1}, {0x54E2, 0x54E2}, {0x54E3, 0x54E3}, + {0x54E4, 0x54E4}, {0x54E5, 0x54E5}, {0x54E6, 0x54E6}, {0x54E7, 0x54E7}, {0x54E8, 0x54E8}, {0x54E9, 0x54E9}, {0x54EA, 0x54EA}, + {0x54EB, 0x54EB}, {0x54EC, 0x54EC}, {0x54ED, 0x54ED}, {0x54EE, 0x54EE}, {0x54EF, 0x54EF}, {0x54F0, 0x54F0}, {0x54F1, 0x54F1}, + {0x54F2, 0x54F2}, {0x54F3, 0x54F3}, {0x54F4, 0x54F4}, {0x54F5, 0x54F5}, {0x54F6, 0x54F6}, {0x54F7, 0x54F7}, {0x54F8, 0x54F8}, + {0x54F9, 0x54F9}, {0x54FA, 0x54FA}, {0x54FB, 0x54FB}, {0x54FC, 0x54FC}, {0x54FD, 0x54FD}, {0x54FE, 0x54FE}, {0x54FF, 0x54FF}, + {0x5500, 0x5500}, {0x5501, 0x5501}, {0x5502, 0x5502}, {0x5503, 0x5503}, {0x5504, 0x5504}, {0x5505, 0x5505}, {0x5506, 0x5506}, + {0x5507, 0x5507}, {0x5508, 0x5508}, {0x5509, 0x5509}, {0x550A, 0x550A}, {0x550B, 0x550B}, {0x550C, 0x550C}, {0x550D, 0x550D}, + {0x550E, 0x550E}, {0x550F, 0x550F}, {0x5510, 0x5510}, {0x5511, 0x5511}, {0x5512, 0x5512}, {0x5513, 0x5513}, {0x5514, 0x5514}, + {0x5515, 0x5515}, {0x5516, 0x5516}, {0x5517, 0x5517}, {0x5518, 0x5518}, {0x5519, 0x5519}, {0x551A, 0x551A}, {0x551B, 0x551B}, + {0x551C, 0x551C}, {0x551D, 0x551D}, {0x551E, 0x551E}, {0x551F, 0x551F}, {0x5520, 0x5520}, {0x5521, 0x5521}, {0x5522, 0x5522}, + {0x5523, 0x5523}, {0x5524, 0x5524}, {0x5525, 0x5525}, {0x5526, 0x5526}, {0x5527, 0x5527}, {0x5528, 0x5528}, {0x5529, 0x5529}, + {0x552A, 0x552A}, {0x552B, 0x552B}, {0x552C, 0x552C}, {0x552D, 0x552D}, {0x552E, 0x552E}, {0x552F, 0x552F}, {0x5530, 0x5530}, + {0x5531, 0x5531}, {0x5532, 0x5532}, {0x5533, 0x5533}, {0x5534, 0x5534}, {0x5535, 0x5535}, {0x5536, 0x5536}, {0x5537, 0x5537}, + {0x5538, 0x5538}, {0x5539, 0x5539}, {0x553A, 0x553A}, {0x553B, 0x553B}, {0x553C, 0x553C}, {0x553D, 0x553D}, {0x553E, 0x553E}, + {0x553F, 0x553F}, {0x5540, 0x5540}, {0x5541, 0x5541}, {0x5542, 0x5542}, {0x5543, 0x5543}, {0x5544, 0x5544}, {0x5545, 0x5545}, + {0x5546, 0x5546}, {0x5547, 0x5547}, {0x5548, 0x5548}, {0x5549, 0x5549}, {0x554A, 0x554A}, {0x554B, 0x554B}, {0x554C, 0x554C}, + {0x554D, 0x554D}, {0x554E, 0x554E}, {0x554F, 0x554F}, {0x5550, 0x5550}, {0x5551, 0x5551}, {0x5552, 0x5552}, {0x5553, 0x5553}, + {0x5554, 0x5554}, {0x5555, 0x5555}, {0x5556, 0x5556}, {0x5557, 0x5557}, {0x5558, 0x5558}, {0x5559, 0x5559}, {0x555A, 0x555A}, + {0x555B, 0x555B}, {0x555C, 0x555C}, {0x555D, 0x555D}, {0x555E, 0x555E}, {0x555F, 0x555F}, {0x5560, 0x5560}, {0x5561, 0x5561}, + {0x5562, 0x5562}, {0x5563, 0x5563}, {0x5564, 0x5564}, {0x5565, 0x5565}, {0x5566, 0x5566}, {0x5567, 0x5567}, {0x5568, 0x5568}, + {0x5569, 0x5569}, {0x556A, 0x556A}, {0x556B, 0x556B}, {0x556C, 0x556C}, {0x556D, 0x556D}, {0x556E, 0x556E}, {0x556F, 0x556F}, + {0x5570, 0x5570}, {0x5571, 0x5571}, {0x5572, 0x5572}, {0x5573, 0x5573}, {0x5574, 0x5574}, {0x5575, 0x5575}, {0x5576, 0x5576}, + {0x5577, 0x5577}, {0x5578, 0x5578}, {0x5579, 0x5579}, {0x557A, 0x557A}, {0x557B, 0x557B}, {0x557C, 0x557C}, {0x557D, 0x557D}, + {0x557E, 0x557E}, {0x557F, 0x557F}, {0x5580, 0x5580}, {0x5581, 0x5581}, {0x5582, 0x5582}, {0x5583, 0x5583}, {0x5584, 0x5584}, + {0x5585, 0x5585}, {0x5586, 0x5586}, {0x5587, 0x5587}, {0x5588, 0x5588}, {0x5589, 0x5589}, {0x558A, 0x558A}, {0x558B, 0x558B}, + {0x558C, 0x558C}, {0x558D, 0x558D}, {0x558E, 0x558E}, {0x558F, 0x558F}, {0x5590, 0x5590}, {0x5591, 0x5591}, {0x5592, 0x5592}, + {0x5593, 0x5593}, {0x5594, 0x5594}, {0x5595, 0x5595}, {0x5596, 0x5596}, {0x5597, 0x5597}, {0x5598, 0x5598}, {0x5599, 0x5599}, + {0x559A, 0x559A}, {0x559B, 0x559B}, {0x559C, 0x559C}, {0x559D, 0x559D}, {0x559E, 0x559E}, {0x559F, 0x559F}, {0x55A0, 0x55A0}, + {0x55A1, 0x55A1}, {0x55A2, 0x55A2}, {0x55A3, 0x55A3}, {0x55A4, 0x55A4}, {0x55A5, 0x55A5}, {0x55A6, 0x55A6}, {0x55A7, 0x55A7}, + {0x55A8, 0x55A8}, {0x55A9, 0x55A9}, {0x55AA, 0x55AA}, {0x55AB, 0x55AB}, {0x55AC, 0x55AC}, {0x55AD, 0x55AD}, {0x55AE, 0x55AE}, + {0x55AF, 0x55AF}, {0x55B0, 0x55B0}, {0x55B1, 0x55B1}, {0x55B2, 0x55B2}, {0x55B3, 0x55B3}, {0x55B4, 0x55B4}, {0x55B5, 0x55B5}, + {0x55B6, 0x55B6}, {0x55B7, 0x55B7}, {0x55B8, 0x55B8}, {0x55B9, 0x55B9}, {0x55BA, 0x55BA}, {0x55BB, 0x55BB}, {0x55BC, 0x55BC}, + {0x55BD, 0x55BD}, {0x55BE, 0x55BE}, {0x55BF, 0x55BF}, {0x55C0, 0x55C0}, {0x55C1, 0x55C1}, {0x55C2, 0x55C2}, {0x55C3, 0x55C3}, + {0x55C4, 0x55C4}, {0x55C5, 0x55C5}, {0x55C6, 0x55C6}, {0x55C7, 0x55C7}, {0x55C8, 0x55C8}, {0x55C9, 0x55C9}, {0x55CA, 0x55CA}, + {0x55CB, 0x55CB}, {0x55CC, 0x55CC}, {0x55CD, 0x55CD}, {0x55CE, 0x55CE}, {0x55CF, 0x55CF}, {0x55D0, 0x55D0}, {0x55D1, 0x55D1}, + {0x55D2, 0x55D2}, {0x55D3, 0x55D3}, {0x55D4, 0x55D4}, {0x55D5, 0x55D5}, {0x55D6, 0x55D6}, {0x55D7, 0x55D7}, {0x55D8, 0x55D8}, + {0x55D9, 0x55D9}, {0x55DA, 0x55DA}, {0x55DB, 0x55DB}, {0x55DC, 0x55DC}, {0x55DD, 0x55DD}, {0x55DE, 0x55DE}, {0x55DF, 0x55DF}, + {0x55E0, 0x55E0}, {0x55E1, 0x55E1}, {0x55E2, 0x55E2}, {0x55E3, 0x55E3}, {0x55E4, 0x55E4}, {0x55E5, 0x55E5}, {0x55E6, 0x55E6}, + {0x55E7, 0x55E7}, {0x55E8, 0x55E8}, {0x55E9, 0x55E9}, {0x55EA, 0x55EA}, {0x55EB, 0x55EB}, {0x55EC, 0x55EC}, {0x55ED, 0x55ED}, + {0x55EE, 0x55EE}, {0x55EF, 0x55EF}, {0x55F0, 0x55F0}, {0x55F1, 0x55F1}, {0x55F2, 0x55F2}, {0x55F3, 0x55F3}, {0x55F4, 0x55F4}, + {0x55F5, 0x55F5}, {0x55F6, 0x55F6}, {0x55F7, 0x55F7}, {0x55F8, 0x55F8}, {0x55F9, 0x55F9}, {0x55FA, 0x55FA}, {0x55FB, 0x55FB}, + {0x55FC, 0x55FC}, {0x55FD, 0x55FD}, {0x55FE, 0x55FE}, {0x55FF, 0x55FF}, {0x5600, 0x5600}, {0x5601, 0x5601}, {0x5602, 0x5602}, + {0x5603, 0x5603}, {0x5604, 0x5604}, {0x5605, 0x5605}, {0x5606, 0x5606}, {0x5607, 0x5607}, {0x5608, 0x5608}, {0x5609, 0x5609}, + {0x560A, 0x560A}, {0x560B, 0x560B}, {0x560C, 0x560C}, {0x560D, 0x560D}, {0x560E, 0x560E}, {0x560F, 0x560F}, {0x5610, 0x5610}, + {0x5611, 0x5611}, {0x5612, 0x5612}, {0x5613, 0x5613}, {0x5614, 0x5614}, {0x5615, 0x5615}, {0x5616, 0x5616}, {0x5617, 0x5617}, + {0x5618, 0x5618}, {0x5619, 0x5619}, {0x561A, 0x561A}, {0x561B, 0x561B}, {0x561C, 0x561C}, {0x561D, 0x561D}, {0x561E, 0x561E}, + {0x561F, 0x561F}, {0x5620, 0x5620}, {0x5621, 0x5621}, {0x5622, 0x5622}, {0x5623, 0x5623}, {0x5624, 0x5624}, {0x5625, 0x5625}, + {0x5626, 0x5626}, {0x5627, 0x5627}, {0x5628, 0x5628}, {0x5629, 0x5629}, {0x562A, 0x562A}, {0x562B, 0x562B}, {0x562C, 0x562C}, + {0x562D, 0x562D}, {0x562E, 0x562E}, {0x562F, 0x562F}, {0x5630, 0x5630}, {0x5631, 0x5631}, {0x5632, 0x5632}, {0x5633, 0x5633}, + {0x5634, 0x5634}, {0x5635, 0x5635}, {0x5636, 0x5636}, {0x5637, 0x5637}, {0x5638, 0x5638}, {0x5639, 0x5639}, {0x563A, 0x563A}, + {0x563B, 0x563B}, {0x563C, 0x563C}, {0x563D, 0x563D}, {0x563E, 0x563E}, {0x563F, 0x563F}, {0x5640, 0x5640}, {0x5641, 0x5641}, + {0x5642, 0x5642}, {0x5643, 0x5643}, {0x5644, 0x5644}, {0x5645, 0x5645}, {0x5646, 0x5646}, {0x5647, 0x5647}, {0x5648, 0x5648}, + {0x5649, 0x5649}, {0x564A, 0x564A}, {0x564B, 0x564B}, {0x564C, 0x564C}, {0x564D, 0x564D}, {0x564E, 0x564E}, {0x564F, 0x564F}, + {0x5650, 0x5650}, {0x5651, 0x5651}, {0x5652, 0x5652}, {0x5653, 0x5653}, {0x5654, 0x5654}, {0x5655, 0x5655}, {0x5656, 0x5656}, + {0x5657, 0x5657}, {0x5658, 0x5658}, {0x5659, 0x5659}, {0x565A, 0x565A}, {0x565B, 0x565B}, {0x565C, 0x565C}, {0x565D, 0x565D}, + {0x565E, 0x565E}, {0x565F, 0x565F}, {0x5660, 0x5660}, {0x5661, 0x5661}, {0x5662, 0x5662}, {0x5663, 0x5663}, {0x5664, 0x5664}, + {0x5665, 0x5665}, {0x5666, 0x5666}, {0x5667, 0x5667}, {0x5668, 0x5668}, {0x5669, 0x5669}, {0x566A, 0x566A}, {0x566B, 0x566B}, + {0x566C, 0x566C}, {0x566D, 0x566D}, {0x566E, 0x566E}, {0x566F, 0x566F}, {0x5670, 0x5670}, {0x5671, 0x5671}, {0x5672, 0x5672}, + {0x5673, 0x5673}, {0x5674, 0x5674}, {0x5675, 0x5675}, {0x5676, 0x5676}, {0x5677, 0x5677}, {0x5678, 0x5678}, {0x5679, 0x5679}, + {0x567A, 0x567A}, {0x567B, 0x567B}, {0x567C, 0x567C}, {0x567D, 0x567D}, {0x567E, 0x567E}, {0x567F, 0x567F}, {0x5680, 0x5680}, + {0x5681, 0x5681}, {0x5682, 0x5682}, {0x5683, 0x5683}, {0x5684, 0x5684}, {0x5685, 0x5685}, {0x5686, 0x5686}, {0x5687, 0x5687}, + {0x5688, 0x5688}, {0x5689, 0x5689}, {0x568A, 0x568A}, {0x568B, 0x568B}, {0x568C, 0x568C}, {0x568D, 0x568D}, {0x568E, 0x568E}, + {0x568F, 0x568F}, {0x5690, 0x5690}, {0x5691, 0x5691}, {0x5692, 0x5692}, {0x5693, 0x5693}, {0x5694, 0x5694}, {0x5695, 0x5695}, + {0x5696, 0x5696}, {0x5697, 0x5697}, {0x5698, 0x5698}, {0x5699, 0x5699}, {0x569A, 0x569A}, {0x569B, 0x569B}, {0x569C, 0x569C}, + {0x569D, 0x569D}, {0x569E, 0x569E}, {0x569F, 0x569F}, {0x56A0, 0x56A0}, {0x56A1, 0x56A1}, {0x56A2, 0x56A2}, {0x56A3, 0x56A3}, + {0x56A4, 0x56A4}, {0x56A5, 0x56A5}, {0x56A6, 0x56A6}, {0x56A7, 0x56A7}, {0x56A8, 0x56A8}, {0x56A9, 0x56A9}, {0x56AA, 0x56AA}, + {0x56AB, 0x56AB}, {0x56AC, 0x56AC}, {0x56AD, 0x56AD}, {0x56AE, 0x56AE}, {0x56AF, 0x56AF}, {0x56B0, 0x56B0}, {0x56B1, 0x56B1}, + {0x56B2, 0x56B2}, {0x56B3, 0x56B3}, {0x56B4, 0x56B4}, {0x56B5, 0x56B5}, {0x56B6, 0x56B6}, {0x56B7, 0x56B7}, {0x56B8, 0x56B8}, + {0x56B9, 0x56B9}, {0x56BA, 0x56BA}, {0x56BB, 0x56BB}, {0x56BC, 0x56BC}, {0x56BD, 0x56BD}, {0x56BE, 0x56BE}, {0x56BF, 0x56BF}, + {0x56C0, 0x56C0}, {0x56C1, 0x56C1}, {0x56C2, 0x56C2}, {0x56C3, 0x56C3}, {0x56C4, 0x56C4}, {0x56C5, 0x56C5}, {0x56C6, 0x56C6}, + {0x56C7, 0x56C7}, {0x56C8, 0x56C8}, {0x56C9, 0x56C9}, {0x56CA, 0x56CA}, {0x56CB, 0x56CB}, {0x56CC, 0x56CC}, {0x56CD, 0x56CD}, + {0x56CE, 0x56CE}, {0x56CF, 0x56CF}, {0x56D0, 0x56D0}, {0x56D1, 0x56D1}, {0x56D2, 0x56D2}, {0x56D3, 0x56D3}, {0x56D4, 0x56D4}, + {0x56D5, 0x56D5}, {0x56D6, 0x56D6}, {0x56D7, 0x56D7}, {0x56D8, 0x56D8}, {0x56D9, 0x56D9}, {0x56DA, 0x56DA}, {0x56DB, 0x56DB}, + {0x56DC, 0x56DC}, {0x56DD, 0x56DD}, {0x56DE, 0x56DE}, {0x56DF, 0x56DF}, {0x56E0, 0x56E0}, {0x56E1, 0x56E1}, {0x56E2, 0x56E2}, + {0x56E3, 0x56E3}, {0x56E4, 0x56E4}, {0x56E5, 0x56E5}, {0x56E6, 0x56E6}, {0x56E7, 0x56E7}, {0x56E8, 0x56E8}, {0x56E9, 0x56E9}, + {0x56EA, 0x56EA}, {0x56EB, 0x56EB}, {0x56EC, 0x56EC}, {0x56ED, 0x56ED}, {0x56EE, 0x56EE}, {0x56EF, 0x56EF}, {0x56F0, 0x56F0}, + {0x56F1, 0x56F1}, {0x56F2, 0x56F2}, {0x56F3, 0x56F3}, {0x56F4, 0x56F4}, {0x56F5, 0x56F5}, {0x56F6, 0x56F6}, {0x56F7, 0x56F7}, + {0x56F8, 0x56F8}, {0x56F9, 0x56F9}, {0x56FA, 0x56FA}, {0x56FB, 0x56FB}, {0x56FC, 0x56FC}, {0x56FD, 0x56FD}, {0x56FE, 0x56FE}, + {0x56FF, 0x56FF}, {0x5700, 0x5700}, {0x5701, 0x5701}, {0x5702, 0x5702}, {0x5703, 0x5703}, {0x5704, 0x5704}, {0x5705, 0x5705}, + {0x5706, 0x5706}, {0x5707, 0x5707}, {0x5708, 0x5708}, {0x5709, 0x5709}, {0x570A, 0x570A}, {0x570B, 0x570B}, {0x570C, 0x570C}, + {0x570D, 0x570D}, {0x570E, 0x570E}, {0x570F, 0x570F}, {0x5710, 0x5710}, {0x5711, 0x5711}, {0x5712, 0x5712}, {0x5713, 0x5713}, + {0x5714, 0x5714}, {0x5715, 0x5715}, {0x5716, 0x5716}, {0x5717, 0x5717}, {0x5718, 0x5718}, {0x5719, 0x5719}, {0x571A, 0x571A}, + {0x571B, 0x571B}, {0x571C, 0x571C}, {0x571D, 0x571D}, {0x571E, 0x571E}, {0x571F, 0x571F}, {0x5720, 0x5720}, {0x5721, 0x5721}, + {0x5722, 0x5722}, {0x5723, 0x5723}, {0x5724, 0x5724}, {0x5725, 0x5725}, {0x5726, 0x5726}, {0x5727, 0x5727}, {0x5728, 0x5728}, + {0x5729, 0x5729}, {0x572A, 0x572A}, {0x572B, 0x572B}, {0x572C, 0x572C}, {0x572D, 0x572D}, {0x572E, 0x572E}, {0x572F, 0x572F}, + {0x5730, 0x5730}, {0x5731, 0x5731}, {0x5732, 0x5732}, {0x5733, 0x5733}, {0x5734, 0x5734}, {0x5735, 0x5735}, {0x5736, 0x5736}, + {0x5737, 0x5737}, {0x5738, 0x5738}, {0x5739, 0x5739}, {0x573A, 0x573A}, {0x573B, 0x573B}, {0x573C, 0x573C}, {0x573D, 0x573D}, + {0x573E, 0x573E}, {0x573F, 0x573F}, {0x5740, 0x5740}, {0x5741, 0x5741}, {0x5742, 0x5742}, {0x5743, 0x5743}, {0x5744, 0x5744}, + {0x5745, 0x5745}, {0x5746, 0x5746}, {0x5747, 0x5747}, {0x5748, 0x5748}, {0x5749, 0x5749}, {0x574A, 0x574A}, {0x574B, 0x574B}, + {0x574C, 0x574C}, {0x574D, 0x574D}, {0x574E, 0x574E}, {0x574F, 0x574F}, {0x5750, 0x5750}, {0x5751, 0x5751}, {0x5752, 0x5752}, + {0x5753, 0x5753}, {0x5754, 0x5754}, {0x5755, 0x5755}, {0x5756, 0x5756}, {0x5757, 0x5757}, {0x5758, 0x5758}, {0x5759, 0x5759}, + {0x575A, 0x575A}, {0x575B, 0x575B}, {0x575C, 0x575C}, {0x575D, 0x575D}, {0x575E, 0x575E}, {0x575F, 0x575F}, {0x5760, 0x5760}, + {0x5761, 0x5761}, {0x5762, 0x5762}, {0x5763, 0x5763}, {0x5764, 0x5764}, {0x5765, 0x5765}, {0x5766, 0x5766}, {0x5767, 0x5767}, + {0x5768, 0x5768}, {0x5769, 0x5769}, {0x576A, 0x576A}, {0x576B, 0x576B}, {0x576C, 0x576C}, {0x576D, 0x576D}, {0x576E, 0x576E}, + {0x576F, 0x576F}, {0x5770, 0x5770}, {0x5771, 0x5771}, {0x5772, 0x5772}, {0x5773, 0x5773}, {0x5774, 0x5774}, {0x5775, 0x5775}, + {0x5776, 0x5776}, {0x5777, 0x5777}, {0x5778, 0x5778}, {0x5779, 0x5779}, {0x577A, 0x577A}, {0x577B, 0x577B}, {0x577C, 0x577C}, + {0x577D, 0x577D}, {0x577E, 0x577E}, {0x577F, 0x577F}, {0x5780, 0x5780}, {0x5781, 0x5781}, {0x5782, 0x5782}, {0x5783, 0x5783}, + {0x5784, 0x5784}, {0x5785, 0x5785}, {0x5786, 0x5786}, {0x5787, 0x5787}, {0x5788, 0x5788}, {0x5789, 0x5789}, {0x578A, 0x578A}, + {0x578B, 0x578B}, {0x578C, 0x578C}, {0x578D, 0x578D}, {0x578E, 0x578E}, {0x578F, 0x578F}, {0x5790, 0x5790}, {0x5791, 0x5791}, + {0x5792, 0x5792}, {0x5793, 0x5793}, {0x5794, 0x5794}, {0x5795, 0x5795}, {0x5796, 0x5796}, {0x5797, 0x5797}, {0x5798, 0x5798}, + {0x5799, 0x5799}, {0x579A, 0x579A}, {0x579B, 0x579B}, {0x579C, 0x579C}, {0x579D, 0x579D}, {0x579E, 0x579E}, {0x579F, 0x579F}, + {0x57A0, 0x57A0}, {0x57A1, 0x57A1}, {0x57A2, 0x57A2}, {0x57A3, 0x57A3}, {0x57A4, 0x57A4}, {0x57A5, 0x57A5}, {0x57A6, 0x57A6}, + {0x57A7, 0x57A7}, {0x57A8, 0x57A8}, {0x57A9, 0x57A9}, {0x57AA, 0x57AA}, {0x57AB, 0x57AB}, {0x57AC, 0x57AC}, {0x57AD, 0x57AD}, + {0x57AE, 0x57AE}, {0x57AF, 0x57AF}, {0x57B0, 0x57B0}, {0x57B1, 0x57B1}, {0x57B2, 0x57B2}, {0x57B3, 0x57B3}, {0x57B4, 0x57B4}, + {0x57B5, 0x57B5}, {0x57B6, 0x57B6}, {0x57B7, 0x57B7}, {0x57B8, 0x57B8}, {0x57B9, 0x57B9}, {0x57BA, 0x57BA}, {0x57BB, 0x57BB}, + {0x57BC, 0x57BC}, {0x57BD, 0x57BD}, {0x57BE, 0x57BE}, {0x57BF, 0x57BF}, {0x57C0, 0x57C0}, {0x57C1, 0x57C1}, {0x57C2, 0x57C2}, + {0x57C3, 0x57C3}, {0x57C4, 0x57C4}, {0x57C5, 0x57C5}, {0x57C6, 0x57C6}, {0x57C7, 0x57C7}, {0x57C8, 0x57C8}, {0x57C9, 0x57C9}, + {0x57CA, 0x57CA}, {0x57CB, 0x57CB}, {0x57CC, 0x57CC}, {0x57CD, 0x57CD}, {0x57CE, 0x57CE}, {0x57CF, 0x57CF}, {0x57D0, 0x57D0}, + {0x57D1, 0x57D1}, {0x57D2, 0x57D2}, {0x57D3, 0x57D3}, {0x57D4, 0x57D4}, {0x57D5, 0x57D5}, {0x57D6, 0x57D6}, {0x57D7, 0x57D7}, + {0x57D8, 0x57D8}, {0x57D9, 0x57D9}, {0x57DA, 0x57DA}, {0x57DB, 0x57DB}, {0x57DC, 0x57DC}, {0x57DD, 0x57DD}, {0x57DE, 0x57DE}, + {0x57DF, 0x57DF}, {0x57E0, 0x57E0}, {0x57E1, 0x57E1}, {0x57E2, 0x57E2}, {0x57E3, 0x57E3}, {0x57E4, 0x57E4}, {0x57E5, 0x57E5}, + {0x57E6, 0x57E6}, {0x57E7, 0x57E7}, {0x57E8, 0x57E8}, {0x57E9, 0x57E9}, {0x57EA, 0x57EA}, {0x57EB, 0x57EB}, {0x57EC, 0x57EC}, + {0x57ED, 0x57ED}, {0x57EE, 0x57EE}, {0x57EF, 0x57EF}, {0x57F0, 0x57F0}, {0x57F1, 0x57F1}, {0x57F2, 0x57F2}, {0x57F3, 0x57F3}, + {0x57F4, 0x57F4}, {0x57F5, 0x57F5}, {0x57F6, 0x57F6}, {0x57F7, 0x57F7}, {0x57F8, 0x57F8}, {0x57F9, 0x57F9}, {0x57FA, 0x57FA}, + {0x57FB, 0x57FB}, {0x57FC, 0x57FC}, {0x57FD, 0x57FD}, {0x57FE, 0x57FE}, {0x57FF, 0x57FF}, {0x5800, 0x5800}, {0x5801, 0x5801}, + {0x5802, 0x5802}, {0x5803, 0x5803}, {0x5804, 0x5804}, {0x5805, 0x5805}, {0x5806, 0x5806}, {0x5807, 0x5807}, {0x5808, 0x5808}, + {0x5809, 0x5809}, {0x580A, 0x580A}, {0x580B, 0x580B}, {0x580C, 0x580C}, {0x580D, 0x580D}, {0x580E, 0x580E}, {0x580F, 0x580F}, + {0x5810, 0x5810}, {0x5811, 0x5811}, {0x5812, 0x5812}, {0x5813, 0x5813}, {0x5814, 0x5814}, {0x5815, 0x5815}, {0x5816, 0x5816}, + {0x5817, 0x5817}, {0x5818, 0x5818}, {0x5819, 0x5819}, {0x581A, 0x581A}, {0x581B, 0x581B}, {0x581C, 0x581C}, {0x581D, 0x581D}, + {0x581E, 0x581E}, {0x581F, 0x581F}, {0x5820, 0x5820}, {0x5821, 0x5821}, {0x5822, 0x5822}, {0x5823, 0x5823}, {0x5824, 0x5824}, + {0x5825, 0x5825}, {0x5826, 0x5826}, {0x5827, 0x5827}, {0x5828, 0x5828}, {0x5829, 0x5829}, {0x582A, 0x582A}, {0x582B, 0x582B}, + {0x582C, 0x582C}, {0x582D, 0x582D}, {0x582E, 0x582E}, {0x582F, 0x582F}, {0x5830, 0x5830}, {0x5831, 0x5831}, {0x5832, 0x5832}, + {0x5833, 0x5833}, {0x5834, 0x5834}, {0x5835, 0x5835}, {0x5836, 0x5836}, {0x5837, 0x5837}, {0x5838, 0x5838}, {0x5839, 0x5839}, + {0x583A, 0x583A}, {0x583B, 0x583B}, {0x583C, 0x583C}, {0x583D, 0x583D}, {0x583E, 0x583E}, {0x583F, 0x583F}, {0x5840, 0x5840}, + {0x5841, 0x5841}, {0x5842, 0x5842}, {0x5843, 0x5843}, {0x5844, 0x5844}, {0x5845, 0x5845}, {0x5846, 0x5846}, {0x5847, 0x5847}, + {0x5848, 0x5848}, {0x5849, 0x5849}, {0x584A, 0x584A}, {0x584B, 0x584B}, {0x584C, 0x584C}, {0x584D, 0x584D}, {0x584E, 0x584E}, + {0x584F, 0x584F}, {0x5850, 0x5850}, {0x5851, 0x5851}, {0x5852, 0x5852}, {0x5853, 0x5853}, {0x5854, 0x5854}, {0x5855, 0x5855}, + {0x5856, 0x5856}, {0x5857, 0x5857}, {0x5858, 0x5858}, {0x5859, 0x5859}, {0x585A, 0x585A}, {0x585B, 0x585B}, {0x585C, 0x585C}, + {0x585D, 0x585D}, {0x585E, 0x585E}, {0x585F, 0x585F}, {0x5860, 0x5860}, {0x5861, 0x5861}, {0x5862, 0x5862}, {0x5863, 0x5863}, + {0x5864, 0x5864}, {0x5865, 0x5865}, {0x5866, 0x5866}, {0x5867, 0x5867}, {0x5868, 0x5868}, {0x5869, 0x5869}, {0x586A, 0x586A}, + {0x586B, 0x586B}, {0x586C, 0x586C}, {0x586D, 0x586D}, {0x586E, 0x586E}, {0x586F, 0x586F}, {0x5870, 0x5870}, {0x5871, 0x5871}, + {0x5872, 0x5872}, {0x5873, 0x5873}, {0x5874, 0x5874}, {0x5875, 0x5875}, {0x5876, 0x5876}, {0x5877, 0x5877}, {0x5878, 0x5878}, + {0x5879, 0x5879}, {0x587A, 0x587A}, {0x587B, 0x587B}, {0x587C, 0x587C}, {0x587D, 0x587D}, {0x587E, 0x587E}, {0x587F, 0x587F}, + {0x5880, 0x5880}, {0x5881, 0x5881}, {0x5882, 0x5882}, {0x5883, 0x5883}, {0x5884, 0x5884}, {0x5885, 0x5885}, {0x5886, 0x5886}, + {0x5887, 0x5887}, {0x5888, 0x5888}, {0x5889, 0x5889}, {0x588A, 0x588A}, {0x588B, 0x588B}, {0x588C, 0x588C}, {0x588D, 0x588D}, + {0x588E, 0x588E}, {0x588F, 0x588F}, {0x5890, 0x5890}, {0x5891, 0x5891}, {0x5892, 0x5892}, {0x5893, 0x5893}, {0x5894, 0x5894}, + {0x5895, 0x5895}, {0x5896, 0x5896}, {0x5897, 0x5897}, {0x5898, 0x5898}, {0x5899, 0x5899}, {0x589A, 0x589A}, {0x589B, 0x589B}, + {0x589C, 0x589C}, {0x589D, 0x589D}, {0x589E, 0x589E}, {0x589F, 0x589F}, {0x58A0, 0x58A0}, {0x58A1, 0x58A1}, {0x58A2, 0x58A2}, + {0x58A3, 0x58A3}, {0x58A4, 0x58A4}, {0x58A5, 0x58A5}, {0x58A6, 0x58A6}, {0x58A7, 0x58A7}, {0x58A8, 0x58A8}, {0x58A9, 0x58A9}, + {0x58AA, 0x58AA}, {0x58AB, 0x58AB}, {0x58AC, 0x58AC}, {0x58AD, 0x58AD}, {0x58AE, 0x58AE}, {0x58AF, 0x58AF}, {0x58B0, 0x58B0}, + {0x58B1, 0x58B1}, {0x58B2, 0x58B2}, {0x58B3, 0x58B3}, {0x58B4, 0x58B4}, {0x58B5, 0x58B5}, {0x58B6, 0x58B6}, {0x58B7, 0x58B7}, + {0x58B8, 0x58B8}, {0x58B9, 0x58B9}, {0x58BA, 0x58BA}, {0x58BB, 0x58BB}, {0x58BC, 0x58BC}, {0x58BD, 0x58BD}, {0x58BE, 0x58BE}, + {0x58BF, 0x58BF}, {0x58C0, 0x58C0}, {0x58C1, 0x58C1}, {0x58C2, 0x58C2}, {0x58C3, 0x58C3}, {0x58C4, 0x58C4}, {0x58C5, 0x58C5}, + {0x58C6, 0x58C6}, {0x58C7, 0x58C7}, {0x58C8, 0x58C8}, {0x58C9, 0x58C9}, {0x58CA, 0x58CA}, {0x58CB, 0x58CB}, {0x58CC, 0x58CC}, + {0x58CD, 0x58CD}, {0x58CE, 0x58CE}, {0x58CF, 0x58CF}, {0x58D0, 0x58D0}, {0x58D1, 0x58D1}, {0x58D2, 0x58D2}, {0x58D3, 0x58D3}, + {0x58D4, 0x58D4}, {0x58D5, 0x58D5}, {0x58D6, 0x58D6}, {0x58D7, 0x58D7}, {0x58D8, 0x58D8}, {0x58D9, 0x58D9}, {0x58DA, 0x58DA}, + {0x58DB, 0x58DB}, {0x58DC, 0x58DC}, {0x58DD, 0x58DD}, {0x58DE, 0x58DE}, {0x58DF, 0x58DF}, {0x58E0, 0x58E0}, {0x58E1, 0x58E1}, + {0x58E2, 0x58E2}, {0x58E3, 0x58E3}, {0x58E4, 0x58E4}, {0x58E5, 0x58E5}, {0x58E6, 0x58E6}, {0x58E7, 0x58E7}, {0x58E8, 0x58E8}, + {0x58E9, 0x58E9}, {0x58EA, 0x58EA}, {0x58EB, 0x58EB}, {0x58EC, 0x58EC}, {0x58ED, 0x58ED}, {0x58EE, 0x58EE}, {0x58EF, 0x58EF}, + {0x58F0, 0x58F0}, {0x58F1, 0x58F1}, {0x58F2, 0x58F2}, {0x58F3, 0x58F3}, {0x58F4, 0x58F4}, {0x58F5, 0x58F5}, {0x58F6, 0x58F6}, + {0x58F7, 0x58F7}, {0x58F8, 0x58F8}, {0x58F9, 0x58F9}, {0x58FA, 0x58FA}, {0x58FB, 0x58FB}, {0x58FC, 0x58FC}, {0x58FD, 0x58FD}, + {0x58FE, 0x58FE}, {0x58FF, 0x58FF}, {0x5900, 0x5900}, {0x5901, 0x5901}, {0x5902, 0x5902}, {0x5903, 0x5903}, {0x5904, 0x5904}, + {0x5905, 0x5905}, {0x5906, 0x5906}, {0x5907, 0x5907}, {0x5908, 0x5908}, {0x5909, 0x5909}, {0x590A, 0x590A}, {0x590B, 0x590B}, + {0x590C, 0x590C}, {0x590D, 0x590D}, {0x590E, 0x590E}, {0x590F, 0x590F}, {0x5910, 0x5910}, {0x5911, 0x5911}, {0x5912, 0x5912}, + {0x5913, 0x5913}, {0x5914, 0x5914}, {0x5915, 0x5915}, {0x5916, 0x5916}, {0x5917, 0x5917}, {0x5918, 0x5918}, {0x5919, 0x5919}, + {0x591A, 0x591A}, {0x591B, 0x591B}, {0x591C, 0x591C}, {0x591D, 0x591D}, {0x591E, 0x591E}, {0x591F, 0x591F}, {0x5920, 0x5920}, + {0x5921, 0x5921}, {0x5922, 0x5922}, {0x5923, 0x5923}, {0x5924, 0x5924}, {0x5925, 0x5925}, {0x5926, 0x5926}, {0x5927, 0x5927}, + {0x5928, 0x5928}, {0x5929, 0x5929}, {0x592A, 0x592A}, {0x592B, 0x592B}, {0x592C, 0x592C}, {0x592D, 0x592D}, {0x592E, 0x592E}, + {0x592F, 0x592F}, {0x5930, 0x5930}, {0x5931, 0x5931}, {0x5932, 0x5932}, {0x5933, 0x5933}, {0x5934, 0x5934}, {0x5935, 0x5935}, + {0x5936, 0x5936}, {0x5937, 0x5937}, {0x5938, 0x5938}, {0x5939, 0x5939}, {0x593A, 0x593A}, {0x593B, 0x593B}, {0x593C, 0x593C}, + {0x593D, 0x593D}, {0x593E, 0x593E}, {0x593F, 0x593F}, {0x5940, 0x5940}, {0x5941, 0x5941}, {0x5942, 0x5942}, {0x5943, 0x5943}, + {0x5944, 0x5944}, {0x5945, 0x5945}, {0x5946, 0x5946}, {0x5947, 0x5947}, {0x5948, 0x5948}, {0x5949, 0x5949}, {0x594A, 0x594A}, + {0x594B, 0x594B}, {0x594C, 0x594C}, {0x594D, 0x594D}, {0x594E, 0x594E}, {0x594F, 0x594F}, {0x5950, 0x5950}, {0x5951, 0x5951}, + {0x5952, 0x5952}, {0x5953, 0x5953}, {0x5954, 0x5954}, {0x5955, 0x5955}, {0x5956, 0x5956}, {0x5957, 0x5957}, {0x5958, 0x5958}, + {0x5959, 0x5959}, {0x595A, 0x595A}, {0x595B, 0x595B}, {0x595C, 0x595C}, {0x595D, 0x595D}, {0x595E, 0x595E}, {0x595F, 0x595F}, + {0x5960, 0x5960}, {0x5961, 0x5961}, {0x5962, 0x5962}, {0x5963, 0x5963}, {0x5964, 0x5964}, {0x5965, 0x5965}, {0x5966, 0x5966}, + {0x5967, 0x5967}, {0x5968, 0x5968}, {0x5969, 0x5969}, {0x596A, 0x596A}, {0x596B, 0x596B}, {0x596C, 0x596C}, {0x596D, 0x596D}, + {0x596E, 0x596E}, {0x596F, 0x596F}, {0x5970, 0x5970}, {0x5971, 0x5971}, {0x5972, 0x5972}, {0x5973, 0x5973}, {0x5974, 0x5974}, + {0x5975, 0x5975}, {0x5976, 0x5976}, {0x5977, 0x5977}, {0x5978, 0x5978}, {0x5979, 0x5979}, {0x597A, 0x597A}, {0x597B, 0x597B}, + {0x597C, 0x597C}, {0x597D, 0x597D}, {0x597E, 0x597E}, {0x597F, 0x597F}, {0x5980, 0x5980}, {0x5981, 0x5981}, {0x5982, 0x5982}, + {0x5983, 0x5983}, {0x5984, 0x5984}, {0x5985, 0x5985}, {0x5986, 0x5986}, {0x5987, 0x5987}, {0x5988, 0x5988}, {0x5989, 0x5989}, + {0x598A, 0x598A}, {0x598B, 0x598B}, {0x598C, 0x598C}, {0x598D, 0x598D}, {0x598E, 0x598E}, {0x598F, 0x598F}, {0x5990, 0x5990}, + {0x5991, 0x5991}, {0x5992, 0x5992}, {0x5993, 0x5993}, {0x5994, 0x5994}, {0x5995, 0x5995}, {0x5996, 0x5996}, {0x5997, 0x5997}, + {0x5998, 0x5998}, {0x5999, 0x5999}, {0x599A, 0x599A}, {0x599B, 0x599B}, {0x599C, 0x599C}, {0x599D, 0x599D}, {0x599E, 0x599E}, + {0x599F, 0x599F}, {0x59A0, 0x59A0}, {0x59A1, 0x59A1}, {0x59A2, 0x59A2}, {0x59A3, 0x59A3}, {0x59A4, 0x59A4}, {0x59A5, 0x59A5}, + {0x59A6, 0x59A6}, {0x59A7, 0x59A7}, {0x59A8, 0x59A8}, {0x59A9, 0x59A9}, {0x59AA, 0x59AA}, {0x59AB, 0x59AB}, {0x59AC, 0x59AC}, + {0x59AD, 0x59AD}, {0x59AE, 0x59AE}, {0x59AF, 0x59AF}, {0x59B0, 0x59B0}, {0x59B1, 0x59B1}, {0x59B2, 0x59B2}, {0x59B3, 0x59B3}, + {0x59B4, 0x59B4}, {0x59B5, 0x59B5}, {0x59B6, 0x59B6}, {0x59B7, 0x59B7}, {0x59B8, 0x59B8}, {0x59B9, 0x59B9}, {0x59BA, 0x59BA}, + {0x59BB, 0x59BB}, {0x59BC, 0x59BC}, {0x59BD, 0x59BD}, {0x59BE, 0x59BE}, {0x59BF, 0x59BF}, {0x59C0, 0x59C0}, {0x59C1, 0x59C1}, + {0x59C2, 0x59C2}, {0x59C3, 0x59C3}, {0x59C4, 0x59C4}, {0x59C5, 0x59C5}, {0x59C6, 0x59C6}, {0x59C7, 0x59C7}, {0x59C8, 0x59C8}, + {0x59C9, 0x59C9}, {0x59CA, 0x59CA}, {0x59CB, 0x59CB}, {0x59CC, 0x59CC}, {0x59CD, 0x59CD}, {0x59CE, 0x59CE}, {0x59CF, 0x59CF}, + {0x59D0, 0x59D0}, {0x59D1, 0x59D1}, {0x59D2, 0x59D2}, {0x59D3, 0x59D3}, {0x59D4, 0x59D4}, {0x59D5, 0x59D5}, {0x59D6, 0x59D6}, + {0x59D7, 0x59D7}, {0x59D8, 0x59D8}, {0x59D9, 0x59D9}, {0x59DA, 0x59DA}, {0x59DB, 0x59DB}, {0x59DC, 0x59DC}, {0x59DD, 0x59DD}, + {0x59DE, 0x59DE}, {0x59DF, 0x59DF}, {0x59E0, 0x59E0}, {0x59E1, 0x59E1}, {0x59E2, 0x59E2}, {0x59E3, 0x59E3}, {0x59E4, 0x59E4}, + {0x59E5, 0x59E5}, {0x59E6, 0x59E6}, {0x59E7, 0x59E7}, {0x59E8, 0x59E8}, {0x59E9, 0x59E9}, {0x59EA, 0x59EA}, {0x59EB, 0x59EB}, + {0x59EC, 0x59EC}, {0x59ED, 0x59ED}, {0x59EE, 0x59EE}, {0x59EF, 0x59EF}, {0x59F0, 0x59F0}, {0x59F1, 0x59F1}, {0x59F2, 0x59F2}, + {0x59F3, 0x59F3}, {0x59F4, 0x59F4}, {0x59F5, 0x59F5}, {0x59F6, 0x59F6}, {0x59F7, 0x59F7}, {0x59F8, 0x59F8}, {0x59F9, 0x59F9}, + {0x59FA, 0x59FA}, {0x59FB, 0x59FB}, {0x59FC, 0x59FC}, {0x59FD, 0x59FD}, {0x59FE, 0x59FE}, {0x59FF, 0x59FF}, {0x5A00, 0x5A00}, + {0x5A01, 0x5A01}, {0x5A02, 0x5A02}, {0x5A03, 0x5A03}, {0x5A04, 0x5A04}, {0x5A05, 0x5A05}, {0x5A06, 0x5A06}, {0x5A07, 0x5A07}, + {0x5A08, 0x5A08}, {0x5A09, 0x5A09}, {0x5A0A, 0x5A0A}, {0x5A0B, 0x5A0B}, {0x5A0C, 0x5A0C}, {0x5A0D, 0x5A0D}, {0x5A0E, 0x5A0E}, + {0x5A0F, 0x5A0F}, {0x5A10, 0x5A10}, {0x5A11, 0x5A11}, {0x5A12, 0x5A12}, {0x5A13, 0x5A13}, {0x5A14, 0x5A14}, {0x5A15, 0x5A15}, + {0x5A16, 0x5A16}, {0x5A17, 0x5A17}, {0x5A18, 0x5A18}, {0x5A19, 0x5A19}, {0x5A1A, 0x5A1A}, {0x5A1B, 0x5A1B}, {0x5A1C, 0x5A1C}, + {0x5A1D, 0x5A1D}, {0x5A1E, 0x5A1E}, {0x5A1F, 0x5A1F}, {0x5A20, 0x5A20}, {0x5A21, 0x5A21}, {0x5A22, 0x5A22}, {0x5A23, 0x5A23}, + {0x5A24, 0x5A24}, {0x5A25, 0x5A25}, {0x5A26, 0x5A26}, {0x5A27, 0x5A27}, {0x5A28, 0x5A28}, {0x5A29, 0x5A29}, {0x5A2A, 0x5A2A}, + {0x5A2B, 0x5A2B}, {0x5A2C, 0x5A2C}, {0x5A2D, 0x5A2D}, {0x5A2E, 0x5A2E}, {0x5A2F, 0x5A2F}, {0x5A30, 0x5A30}, {0x5A31, 0x5A31}, + {0x5A32, 0x5A32}, {0x5A33, 0x5A33}, {0x5A34, 0x5A34}, {0x5A35, 0x5A35}, {0x5A36, 0x5A36}, {0x5A37, 0x5A37}, {0x5A38, 0x5A38}, + {0x5A39, 0x5A39}, {0x5A3A, 0x5A3A}, {0x5A3B, 0x5A3B}, {0x5A3C, 0x5A3C}, {0x5A3D, 0x5A3D}, {0x5A3E, 0x5A3E}, {0x5A3F, 0x5A3F}, + {0x5A40, 0x5A40}, {0x5A41, 0x5A41}, {0x5A42, 0x5A42}, {0x5A43, 0x5A43}, {0x5A44, 0x5A44}, {0x5A45, 0x5A45}, {0x5A46, 0x5A46}, + {0x5A47, 0x5A47}, {0x5A48, 0x5A48}, {0x5A49, 0x5A49}, {0x5A4A, 0x5A4A}, {0x5A4B, 0x5A4B}, {0x5A4C, 0x5A4C}, {0x5A4D, 0x5A4D}, + {0x5A4E, 0x5A4E}, {0x5A4F, 0x5A4F}, {0x5A50, 0x5A50}, {0x5A51, 0x5A51}, {0x5A52, 0x5A52}, {0x5A53, 0x5A53}, {0x5A54, 0x5A54}, + {0x5A55, 0x5A55}, {0x5A56, 0x5A56}, {0x5A57, 0x5A57}, {0x5A58, 0x5A58}, {0x5A59, 0x5A59}, {0x5A5A, 0x5A5A}, {0x5A5B, 0x5A5B}, + {0x5A5C, 0x5A5C}, {0x5A5D, 0x5A5D}, {0x5A5E, 0x5A5E}, {0x5A5F, 0x5A5F}, {0x5A60, 0x5A60}, {0x5A61, 0x5A61}, {0x5A62, 0x5A62}, + {0x5A63, 0x5A63}, {0x5A64, 0x5A64}, {0x5A65, 0x5A65}, {0x5A66, 0x5A66}, {0x5A67, 0x5A67}, {0x5A68, 0x5A68}, {0x5A69, 0x5A69}, + {0x5A6A, 0x5A6A}, {0x5A6B, 0x5A6B}, {0x5A6C, 0x5A6C}, {0x5A6D, 0x5A6D}, {0x5A6E, 0x5A6E}, {0x5A6F, 0x5A6F}, {0x5A70, 0x5A70}, + {0x5A71, 0x5A71}, {0x5A72, 0x5A72}, {0x5A73, 0x5A73}, {0x5A74, 0x5A74}, {0x5A75, 0x5A75}, {0x5A76, 0x5A76}, {0x5A77, 0x5A77}, + {0x5A78, 0x5A78}, {0x5A79, 0x5A79}, {0x5A7A, 0x5A7A}, {0x5A7B, 0x5A7B}, {0x5A7C, 0x5A7C}, {0x5A7D, 0x5A7D}, {0x5A7E, 0x5A7E}, + {0x5A7F, 0x5A7F}, {0x5A80, 0x5A80}, {0x5A81, 0x5A81}, {0x5A82, 0x5A82}, {0x5A83, 0x5A83}, {0x5A84, 0x5A84}, {0x5A85, 0x5A85}, + {0x5A86, 0x5A86}, {0x5A87, 0x5A87}, {0x5A88, 0x5A88}, {0x5A89, 0x5A89}, {0x5A8A, 0x5A8A}, {0x5A8B, 0x5A8B}, {0x5A8C, 0x5A8C}, + {0x5A8D, 0x5A8D}, {0x5A8E, 0x5A8E}, {0x5A8F, 0x5A8F}, {0x5A90, 0x5A90}, {0x5A91, 0x5A91}, {0x5A92, 0x5A92}, {0x5A93, 0x5A93}, + {0x5A94, 0x5A94}, {0x5A95, 0x5A95}, {0x5A96, 0x5A96}, {0x5A97, 0x5A97}, {0x5A98, 0x5A98}, {0x5A99, 0x5A99}, {0x5A9A, 0x5A9A}, + {0x5A9B, 0x5A9B}, {0x5A9C, 0x5A9C}, {0x5A9D, 0x5A9D}, {0x5A9E, 0x5A9E}, {0x5A9F, 0x5A9F}, {0x5AA0, 0x5AA0}, {0x5AA1, 0x5AA1}, + {0x5AA2, 0x5AA2}, {0x5AA3, 0x5AA3}, {0x5AA4, 0x5AA4}, {0x5AA5, 0x5AA5}, {0x5AA6, 0x5AA6}, {0x5AA7, 0x5AA7}, {0x5AA8, 0x5AA8}, + {0x5AA9, 0x5AA9}, {0x5AAA, 0x5AAA}, {0x5AAB, 0x5AAB}, {0x5AAC, 0x5AAC}, {0x5AAD, 0x5AAD}, {0x5AAE, 0x5AAE}, {0x5AAF, 0x5AAF}, + {0x5AB0, 0x5AB0}, {0x5AB1, 0x5AB1}, {0x5AB2, 0x5AB2}, {0x5AB3, 0x5AB3}, {0x5AB4, 0x5AB4}, {0x5AB5, 0x5AB5}, {0x5AB6, 0x5AB6}, + {0x5AB7, 0x5AB7}, {0x5AB8, 0x5AB8}, {0x5AB9, 0x5AB9}, {0x5ABA, 0x5ABA}, {0x5ABB, 0x5ABB}, {0x5ABC, 0x5ABC}, {0x5ABD, 0x5ABD}, + {0x5ABE, 0x5ABE}, {0x5ABF, 0x5ABF}, {0x5AC0, 0x5AC0}, {0x5AC1, 0x5AC1}, {0x5AC2, 0x5AC2}, {0x5AC3, 0x5AC3}, {0x5AC4, 0x5AC4}, + {0x5AC5, 0x5AC5}, {0x5AC6, 0x5AC6}, {0x5AC7, 0x5AC7}, {0x5AC8, 0x5AC8}, {0x5AC9, 0x5AC9}, {0x5ACA, 0x5ACA}, {0x5ACB, 0x5ACB}, + {0x5ACC, 0x5ACC}, {0x5ACD, 0x5ACD}, {0x5ACE, 0x5ACE}, {0x5ACF, 0x5ACF}, {0x5AD0, 0x5AD0}, {0x5AD1, 0x5AD1}, {0x5AD2, 0x5AD2}, + {0x5AD3, 0x5AD3}, {0x5AD4, 0x5AD4}, {0x5AD5, 0x5AD5}, {0x5AD6, 0x5AD6}, {0x5AD7, 0x5AD7}, {0x5AD8, 0x5AD8}, {0x5AD9, 0x5AD9}, + {0x5ADA, 0x5ADA}, {0x5ADB, 0x5ADB}, {0x5ADC, 0x5ADC}, {0x5ADD, 0x5ADD}, {0x5ADE, 0x5ADE}, {0x5ADF, 0x5ADF}, {0x5AE0, 0x5AE0}, + {0x5AE1, 0x5AE1}, {0x5AE2, 0x5AE2}, {0x5AE3, 0x5AE3}, {0x5AE4, 0x5AE4}, {0x5AE5, 0x5AE5}, {0x5AE6, 0x5AE6}, {0x5AE7, 0x5AE7}, + {0x5AE8, 0x5AE8}, {0x5AE9, 0x5AE9}, {0x5AEA, 0x5AEA}, {0x5AEB, 0x5AEB}, {0x5AEC, 0x5AEC}, {0x5AED, 0x5AED}, {0x5AEE, 0x5AEE}, + {0x5AEF, 0x5AEF}, {0x5AF0, 0x5AF0}, {0x5AF1, 0x5AF1}, {0x5AF2, 0x5AF2}, {0x5AF3, 0x5AF3}, {0x5AF4, 0x5AF4}, {0x5AF5, 0x5AF5}, + {0x5AF6, 0x5AF6}, {0x5AF7, 0x5AF7}, {0x5AF8, 0x5AF8}, {0x5AF9, 0x5AF9}, {0x5AFA, 0x5AFA}, {0x5AFB, 0x5AFB}, {0x5AFC, 0x5AFC}, + {0x5AFD, 0x5AFD}, {0x5AFE, 0x5AFE}, {0x5AFF, 0x5AFF}, {0x5B00, 0x5B00}, {0x5B01, 0x5B01}, {0x5B02, 0x5B02}, {0x5B03, 0x5B03}, + {0x5B04, 0x5B04}, {0x5B05, 0x5B05}, {0x5B06, 0x5B06}, {0x5B07, 0x5B07}, {0x5B08, 0x5B08}, {0x5B09, 0x5B09}, {0x5B0A, 0x5B0A}, + {0x5B0B, 0x5B0B}, {0x5B0C, 0x5B0C}, {0x5B0D, 0x5B0D}, {0x5B0E, 0x5B0E}, {0x5B0F, 0x5B0F}, {0x5B10, 0x5B10}, {0x5B11, 0x5B11}, + {0x5B12, 0x5B12}, {0x5B13, 0x5B13}, {0x5B14, 0x5B14}, {0x5B15, 0x5B15}, {0x5B16, 0x5B16}, {0x5B17, 0x5B17}, {0x5B18, 0x5B18}, + {0x5B19, 0x5B19}, {0x5B1A, 0x5B1A}, {0x5B1B, 0x5B1B}, {0x5B1C, 0x5B1C}, {0x5B1D, 0x5B1D}, {0x5B1E, 0x5B1E}, {0x5B1F, 0x5B1F}, + {0x5B20, 0x5B20}, {0x5B21, 0x5B21}, {0x5B22, 0x5B22}, {0x5B23, 0x5B23}, {0x5B24, 0x5B24}, {0x5B25, 0x5B25}, {0x5B26, 0x5B26}, + {0x5B27, 0x5B27}, {0x5B28, 0x5B28}, {0x5B29, 0x5B29}, {0x5B2A, 0x5B2A}, {0x5B2B, 0x5B2B}, {0x5B2C, 0x5B2C}, {0x5B2D, 0x5B2D}, + {0x5B2E, 0x5B2E}, {0x5B2F, 0x5B2F}, {0x5B30, 0x5B30}, {0x5B31, 0x5B31}, {0x5B32, 0x5B32}, {0x5B33, 0x5B33}, {0x5B34, 0x5B34}, + {0x5B35, 0x5B35}, {0x5B36, 0x5B36}, {0x5B37, 0x5B37}, {0x5B38, 0x5B38}, {0x5B39, 0x5B39}, {0x5B3A, 0x5B3A}, {0x5B3B, 0x5B3B}, + {0x5B3C, 0x5B3C}, {0x5B3D, 0x5B3D}, {0x5B3E, 0x5B3E}, {0x5B3F, 0x5B3F}, {0x5B40, 0x5B40}, {0x5B41, 0x5B41}, {0x5B42, 0x5B42}, + {0x5B43, 0x5B43}, {0x5B44, 0x5B44}, {0x5B45, 0x5B45}, {0x5B46, 0x5B46}, {0x5B47, 0x5B47}, {0x5B48, 0x5B48}, {0x5B49, 0x5B49}, + {0x5B4A, 0x5B4A}, {0x5B4B, 0x5B4B}, {0x5B4C, 0x5B4C}, {0x5B4D, 0x5B4D}, {0x5B4E, 0x5B4E}, {0x5B4F, 0x5B4F}, {0x5B50, 0x5B50}, + {0x5B51, 0x5B51}, {0x5B52, 0x5B52}, {0x5B53, 0x5B53}, {0x5B54, 0x5B54}, {0x5B55, 0x5B55}, {0x5B56, 0x5B56}, {0x5B57, 0x5B57}, + {0x5B58, 0x5B58}, {0x5B59, 0x5B59}, {0x5B5A, 0x5B5A}, {0x5B5B, 0x5B5B}, {0x5B5C, 0x5B5C}, {0x5B5D, 0x5B5D}, {0x5B5E, 0x5B5E}, + {0x5B5F, 0x5B5F}, {0x5B60, 0x5B60}, {0x5B61, 0x5B61}, {0x5B62, 0x5B62}, {0x5B63, 0x5B63}, {0x5B64, 0x5B64}, {0x5B65, 0x5B65}, + {0x5B66, 0x5B66}, {0x5B67, 0x5B67}, {0x5B68, 0x5B68}, {0x5B69, 0x5B69}, {0x5B6A, 0x5B6A}, {0x5B6B, 0x5B6B}, {0x5B6C, 0x5B6C}, + {0x5B6D, 0x5B6D}, {0x5B6E, 0x5B6E}, {0x5B6F, 0x5B6F}, {0x5B70, 0x5B70}, {0x5B71, 0x5B71}, {0x5B72, 0x5B72}, {0x5B73, 0x5B73}, + {0x5B74, 0x5B74}, {0x5B75, 0x5B75}, {0x5B76, 0x5B76}, {0x5B77, 0x5B77}, {0x5B78, 0x5B78}, {0x5B79, 0x5B79}, {0x5B7A, 0x5B7A}, + {0x5B7B, 0x5B7B}, {0x5B7C, 0x5B7C}, {0x5B7D, 0x5B7D}, {0x5B7E, 0x5B7E}, {0x5B7F, 0x5B7F}, {0x5B80, 0x5B80}, {0x5B81, 0x5B81}, + {0x5B82, 0x5B82}, {0x5B83, 0x5B83}, {0x5B84, 0x5B84}, {0x5B85, 0x5B85}, {0x5B86, 0x5B86}, {0x5B87, 0x5B87}, {0x5B88, 0x5B88}, + {0x5B89, 0x5B89}, {0x5B8A, 0x5B8A}, {0x5B8B, 0x5B8B}, {0x5B8C, 0x5B8C}, {0x5B8D, 0x5B8D}, {0x5B8E, 0x5B8E}, {0x5B8F, 0x5B8F}, + {0x5B90, 0x5B90}, {0x5B91, 0x5B91}, {0x5B92, 0x5B92}, {0x5B93, 0x5B93}, {0x5B94, 0x5B94}, {0x5B95, 0x5B95}, {0x5B96, 0x5B96}, + {0x5B97, 0x5B97}, {0x5B98, 0x5B98}, {0x5B99, 0x5B99}, {0x5B9A, 0x5B9A}, {0x5B9B, 0x5B9B}, {0x5B9C, 0x5B9C}, {0x5B9D, 0x5B9D}, + {0x5B9E, 0x5B9E}, {0x5B9F, 0x5B9F}, {0x5BA0, 0x5BA0}, {0x5BA1, 0x5BA1}, {0x5BA2, 0x5BA2}, {0x5BA3, 0x5BA3}, {0x5BA4, 0x5BA4}, + {0x5BA5, 0x5BA5}, {0x5BA6, 0x5BA6}, {0x5BA7, 0x5BA7}, {0x5BA8, 0x5BA8}, {0x5BA9, 0x5BA9}, {0x5BAA, 0x5BAA}, {0x5BAB, 0x5BAB}, + {0x5BAC, 0x5BAC}, {0x5BAD, 0x5BAD}, {0x5BAE, 0x5BAE}, {0x5BAF, 0x5BAF}, {0x5BB0, 0x5BB0}, {0x5BB1, 0x5BB1}, {0x5BB2, 0x5BB2}, + {0x5BB3, 0x5BB3}, {0x5BB4, 0x5BB4}, {0x5BB5, 0x5BB5}, {0x5BB6, 0x5BB6}, {0x5BB7, 0x5BB7}, {0x5BB8, 0x5BB8}, {0x5BB9, 0x5BB9}, + {0x5BBA, 0x5BBA}, {0x5BBB, 0x5BBB}, {0x5BBC, 0x5BBC}, {0x5BBD, 0x5BBD}, {0x5BBE, 0x5BBE}, {0x5BBF, 0x5BBF}, {0x5BC0, 0x5BC0}, + {0x5BC1, 0x5BC1}, {0x5BC2, 0x5BC2}, {0x5BC3, 0x5BC3}, {0x5BC4, 0x5BC4}, {0x5BC5, 0x5BC5}, {0x5BC6, 0x5BC6}, {0x5BC7, 0x5BC7}, + {0x5BC8, 0x5BC8}, {0x5BC9, 0x5BC9}, {0x5BCA, 0x5BCA}, {0x5BCB, 0x5BCB}, {0x5BCC, 0x5BCC}, {0x5BCD, 0x5BCD}, {0x5BCE, 0x5BCE}, + {0x5BCF, 0x5BCF}, {0x5BD0, 0x5BD0}, {0x5BD1, 0x5BD1}, {0x5BD2, 0x5BD2}, {0x5BD3, 0x5BD3}, {0x5BD4, 0x5BD4}, {0x5BD5, 0x5BD5}, + {0x5BD6, 0x5BD6}, {0x5BD7, 0x5BD7}, {0x5BD8, 0x5BD8}, {0x5BD9, 0x5BD9}, {0x5BDA, 0x5BDA}, {0x5BDB, 0x5BDB}, {0x5BDC, 0x5BDC}, + {0x5BDD, 0x5BDD}, {0x5BDE, 0x5BDE}, {0x5BDF, 0x5BDF}, {0x5BE0, 0x5BE0}, {0x5BE1, 0x5BE1}, {0x5BE2, 0x5BE2}, {0x5BE3, 0x5BE3}, + {0x5BE4, 0x5BE4}, {0x5BE5, 0x5BE5}, {0x5BE6, 0x5BE6}, {0x5BE7, 0x5BE7}, {0x5BE8, 0x5BE8}, {0x5BE9, 0x5BE9}, {0x5BEA, 0x5BEA}, + {0x5BEB, 0x5BEB}, {0x5BEC, 0x5BEC}, {0x5BED, 0x5BED}, {0x5BEE, 0x5BEE}, {0x5BEF, 0x5BEF}, {0x5BF0, 0x5BF0}, {0x5BF1, 0x5BF1}, + {0x5BF2, 0x5BF2}, {0x5BF3, 0x5BF3}, {0x5BF4, 0x5BF4}, {0x5BF5, 0x5BF5}, {0x5BF6, 0x5BF6}, {0x5BF7, 0x5BF7}, {0x5BF8, 0x5BF8}, + {0x5BF9, 0x5BF9}, {0x5BFA, 0x5BFA}, {0x5BFB, 0x5BFB}, {0x5BFC, 0x5BFC}, {0x5BFD, 0x5BFD}, {0x5BFE, 0x5BFE}, {0x5BFF, 0x5BFF}, + {0x5C00, 0x5C00}, {0x5C01, 0x5C01}, {0x5C02, 0x5C02}, {0x5C03, 0x5C03}, {0x5C04, 0x5C04}, {0x5C05, 0x5C05}, {0x5C06, 0x5C06}, + {0x5C07, 0x5C07}, {0x5C08, 0x5C08}, {0x5C09, 0x5C09}, {0x5C0A, 0x5C0A}, {0x5C0B, 0x5C0B}, {0x5C0C, 0x5C0C}, {0x5C0D, 0x5C0D}, + {0x5C0E, 0x5C0E}, {0x5C0F, 0x5C0F}, {0x5C10, 0x5C10}, {0x5C11, 0x5C11}, {0x5C12, 0x5C12}, {0x5C13, 0x5C13}, {0x5C14, 0x5C14}, + {0x5C15, 0x5C15}, {0x5C16, 0x5C16}, {0x5C17, 0x5C17}, {0x5C18, 0x5C18}, {0x5C19, 0x5C19}, {0x5C1A, 0x5C1A}, {0x5C1B, 0x5C1B}, + {0x5C1C, 0x5C1C}, {0x5C1D, 0x5C1D}, {0x5C1E, 0x5C1E}, {0x5C1F, 0x5C1F}, {0x5C20, 0x5C20}, {0x5C21, 0x5C21}, {0x5C22, 0x5C22}, + {0x5C23, 0x5C23}, {0x5C24, 0x5C24}, {0x5C25, 0x5C25}, {0x5C26, 0x5C26}, {0x5C27, 0x5C27}, {0x5C28, 0x5C28}, {0x5C29, 0x5C29}, + {0x5C2A, 0x5C2A}, {0x5C2B, 0x5C2B}, {0x5C2C, 0x5C2C}, {0x5C2D, 0x5C2D}, {0x5C2E, 0x5C2E}, {0x5C2F, 0x5C2F}, {0x5C30, 0x5C30}, + {0x5C31, 0x5C31}, {0x5C32, 0x5C32}, {0x5C33, 0x5C33}, {0x5C34, 0x5C34}, {0x5C35, 0x5C35}, {0x5C36, 0x5C36}, {0x5C37, 0x5C37}, + {0x5C38, 0x5C38}, {0x5C39, 0x5C39}, {0x5C3A, 0x5C3A}, {0x5C3B, 0x5C3B}, {0x5C3C, 0x5C3C}, {0x5C3D, 0x5C3D}, {0x5C3E, 0x5C3E}, + {0x5C3F, 0x5C3F}, {0x5C40, 0x5C40}, {0x5C41, 0x5C41}, {0x5C42, 0x5C42}, {0x5C43, 0x5C43}, {0x5C44, 0x5C44}, {0x5C45, 0x5C45}, + {0x5C46, 0x5C46}, {0x5C47, 0x5C47}, {0x5C48, 0x5C48}, {0x5C49, 0x5C49}, {0x5C4A, 0x5C4A}, {0x5C4B, 0x5C4B}, {0x5C4C, 0x5C4C}, + {0x5C4D, 0x5C4D}, {0x5C4E, 0x5C4E}, {0x5C4F, 0x5C4F}, {0x5C50, 0x5C50}, {0x5C51, 0x5C51}, {0x5C52, 0x5C52}, {0x5C53, 0x5C53}, + {0x5C54, 0x5C54}, {0x5C55, 0x5C55}, {0x5C56, 0x5C56}, {0x5C57, 0x5C57}, {0x5C58, 0x5C58}, {0x5C59, 0x5C59}, {0x5C5A, 0x5C5A}, + {0x5C5B, 0x5C5B}, {0x5C5C, 0x5C5C}, {0x5C5D, 0x5C5D}, {0x5C5E, 0x5C5E}, {0x5C5F, 0x5C5F}, {0x5C60, 0x5C60}, {0x5C61, 0x5C61}, + {0x5C62, 0x5C62}, {0x5C63, 0x5C63}, {0x5C64, 0x5C64}, {0x5C65, 0x5C65}, {0x5C66, 0x5C66}, {0x5C67, 0x5C67}, {0x5C68, 0x5C68}, + {0x5C69, 0x5C69}, {0x5C6A, 0x5C6A}, {0x5C6B, 0x5C6B}, {0x5C6C, 0x5C6C}, {0x5C6D, 0x5C6D}, {0x5C6E, 0x5C6E}, {0x5C6F, 0x5C6F}, + {0x5C70, 0x5C70}, {0x5C71, 0x5C71}, {0x5C72, 0x5C72}, {0x5C73, 0x5C73}, {0x5C74, 0x5C74}, {0x5C75, 0x5C75}, {0x5C76, 0x5C76}, + {0x5C77, 0x5C77}, {0x5C78, 0x5C78}, {0x5C79, 0x5C79}, {0x5C7A, 0x5C7A}, {0x5C7B, 0x5C7B}, {0x5C7C, 0x5C7C}, {0x5C7D, 0x5C7D}, + {0x5C7E, 0x5C7E}, {0x5C7F, 0x5C7F}, {0x5C80, 0x5C80}, {0x5C81, 0x5C81}, {0x5C82, 0x5C82}, {0x5C83, 0x5C83}, {0x5C84, 0x5C84}, + {0x5C85, 0x5C85}, {0x5C86, 0x5C86}, {0x5C87, 0x5C87}, {0x5C88, 0x5C88}, {0x5C89, 0x5C89}, {0x5C8A, 0x5C8A}, {0x5C8B, 0x5C8B}, + {0x5C8C, 0x5C8C}, {0x5C8D, 0x5C8D}, {0x5C8E, 0x5C8E}, {0x5C8F, 0x5C8F}, {0x5C90, 0x5C90}, {0x5C91, 0x5C91}, {0x5C92, 0x5C92}, + {0x5C93, 0x5C93}, {0x5C94, 0x5C94}, {0x5C95, 0x5C95}, {0x5C96, 0x5C96}, {0x5C97, 0x5C97}, {0x5C98, 0x5C98}, {0x5C99, 0x5C99}, + {0x5C9A, 0x5C9A}, {0x5C9B, 0x5C9B}, {0x5C9C, 0x5C9C}, {0x5C9D, 0x5C9D}, {0x5C9E, 0x5C9E}, {0x5C9F, 0x5C9F}, {0x5CA0, 0x5CA0}, + {0x5CA1, 0x5CA1}, {0x5CA2, 0x5CA2}, {0x5CA3, 0x5CA3}, {0x5CA4, 0x5CA4}, {0x5CA5, 0x5CA5}, {0x5CA6, 0x5CA6}, {0x5CA7, 0x5CA7}, + {0x5CA8, 0x5CA8}, {0x5CA9, 0x5CA9}, {0x5CAA, 0x5CAA}, {0x5CAB, 0x5CAB}, {0x5CAC, 0x5CAC}, {0x5CAD, 0x5CAD}, {0x5CAE, 0x5CAE}, + {0x5CAF, 0x5CAF}, {0x5CB0, 0x5CB0}, {0x5CB1, 0x5CB1}, {0x5CB2, 0x5CB2}, {0x5CB3, 0x5CB3}, {0x5CB4, 0x5CB4}, {0x5CB5, 0x5CB5}, + {0x5CB6, 0x5CB6}, {0x5CB7, 0x5CB7}, {0x5CB8, 0x5CB8}, {0x5CB9, 0x5CB9}, {0x5CBA, 0x5CBA}, {0x5CBB, 0x5CBB}, {0x5CBC, 0x5CBC}, + {0x5CBD, 0x5CBD}, {0x5CBE, 0x5CBE}, {0x5CBF, 0x5CBF}, {0x5CC0, 0x5CC0}, {0x5CC1, 0x5CC1}, {0x5CC2, 0x5CC2}, {0x5CC3, 0x5CC3}, + {0x5CC4, 0x5CC4}, {0x5CC5, 0x5CC5}, {0x5CC6, 0x5CC6}, {0x5CC7, 0x5CC7}, {0x5CC8, 0x5CC8}, {0x5CC9, 0x5CC9}, {0x5CCA, 0x5CCA}, + {0x5CCB, 0x5CCB}, {0x5CCC, 0x5CCC}, {0x5CCD, 0x5CCD}, {0x5CCE, 0x5CCE}, {0x5CCF, 0x5CCF}, {0x5CD0, 0x5CD0}, {0x5CD1, 0x5CD1}, + {0x5CD2, 0x5CD2}, {0x5CD3, 0x5CD3}, {0x5CD4, 0x5CD4}, {0x5CD5, 0x5CD5}, {0x5CD6, 0x5CD6}, {0x5CD7, 0x5CD7}, {0x5CD8, 0x5CD8}, + {0x5CD9, 0x5CD9}, {0x5CDA, 0x5CDA}, {0x5CDB, 0x5CDB}, {0x5CDC, 0x5CDC}, {0x5CDD, 0x5CDD}, {0x5CDE, 0x5CDE}, {0x5CDF, 0x5CDF}, + {0x5CE0, 0x5CE0}, {0x5CE1, 0x5CE1}, {0x5CE2, 0x5CE2}, {0x5CE3, 0x5CE3}, {0x5CE4, 0x5CE4}, {0x5CE5, 0x5CE5}, {0x5CE6, 0x5CE6}, + {0x5CE7, 0x5CE7}, {0x5CE8, 0x5CE8}, {0x5CE9, 0x5CE9}, {0x5CEA, 0x5CEA}, {0x5CEB, 0x5CEB}, {0x5CEC, 0x5CEC}, {0x5CED, 0x5CED}, + {0x5CEE, 0x5CEE}, {0x5CEF, 0x5CEF}, {0x5CF0, 0x5CF0}, {0x5CF1, 0x5CF1}, {0x5CF2, 0x5CF2}, {0x5CF3, 0x5CF3}, {0x5CF4, 0x5CF4}, + {0x5CF5, 0x5CF5}, {0x5CF6, 0x5CF6}, {0x5CF7, 0x5CF7}, {0x5CF8, 0x5CF8}, {0x5CF9, 0x5CF9}, {0x5CFA, 0x5CFA}, {0x5CFB, 0x5CFB}, + {0x5CFC, 0x5CFC}, {0x5CFD, 0x5CFD}, {0x5CFE, 0x5CFE}, {0x5CFF, 0x5CFF}, {0x5D00, 0x5D00}, {0x5D01, 0x5D01}, {0x5D02, 0x5D02}, + {0x5D03, 0x5D03}, {0x5D04, 0x5D04}, {0x5D05, 0x5D05}, {0x5D06, 0x5D06}, {0x5D07, 0x5D07}, {0x5D08, 0x5D08}, {0x5D09, 0x5D09}, + {0x5D0A, 0x5D0A}, {0x5D0B, 0x5D0B}, {0x5D0C, 0x5D0C}, {0x5D0D, 0x5D0D}, {0x5D0E, 0x5D0E}, {0x5D0F, 0x5D0F}, {0x5D10, 0x5D10}, + {0x5D11, 0x5D11}, {0x5D12, 0x5D12}, {0x5D13, 0x5D13}, {0x5D14, 0x5D14}, {0x5D15, 0x5D15}, {0x5D16, 0x5D16}, {0x5D17, 0x5D17}, + {0x5D18, 0x5D18}, {0x5D19, 0x5D19}, {0x5D1A, 0x5D1A}, {0x5D1B, 0x5D1B}, {0x5D1C, 0x5D1C}, {0x5D1D, 0x5D1D}, {0x5D1E, 0x5D1E}, + {0x5D1F, 0x5D1F}, {0x5D20, 0x5D20}, {0x5D21, 0x5D21}, {0x5D22, 0x5D22}, {0x5D23, 0x5D23}, {0x5D24, 0x5D24}, {0x5D25, 0x5D25}, + {0x5D26, 0x5D26}, {0x5D27, 0x5D27}, {0x5D28, 0x5D28}, {0x5D29, 0x5D29}, {0x5D2A, 0x5D2A}, {0x5D2B, 0x5D2B}, {0x5D2C, 0x5D2C}, + {0x5D2D, 0x5D2D}, {0x5D2E, 0x5D2E}, {0x5D2F, 0x5D2F}, {0x5D30, 0x5D30}, {0x5D31, 0x5D31}, {0x5D32, 0x5D32}, {0x5D33, 0x5D33}, + {0x5D34, 0x5D34}, {0x5D35, 0x5D35}, {0x5D36, 0x5D36}, {0x5D37, 0x5D37}, {0x5D38, 0x5D38}, {0x5D39, 0x5D39}, {0x5D3A, 0x5D3A}, + {0x5D3B, 0x5D3B}, {0x5D3C, 0x5D3C}, {0x5D3D, 0x5D3D}, {0x5D3E, 0x5D3E}, {0x5D3F, 0x5D3F}, {0x5D40, 0x5D40}, {0x5D41, 0x5D41}, + {0x5D42, 0x5D42}, {0x5D43, 0x5D43}, {0x5D44, 0x5D44}, {0x5D45, 0x5D45}, {0x5D46, 0x5D46}, {0x5D47, 0x5D47}, {0x5D48, 0x5D48}, + {0x5D49, 0x5D49}, {0x5D4A, 0x5D4A}, {0x5D4B, 0x5D4B}, {0x5D4C, 0x5D4C}, {0x5D4D, 0x5D4D}, {0x5D4E, 0x5D4E}, {0x5D4F, 0x5D4F}, + {0x5D50, 0x5D50}, {0x5D51, 0x5D51}, {0x5D52, 0x5D52}, {0x5D53, 0x5D53}, {0x5D54, 0x5D54}, {0x5D55, 0x5D55}, {0x5D56, 0x5D56}, + {0x5D57, 0x5D57}, {0x5D58, 0x5D58}, {0x5D59, 0x5D59}, {0x5D5A, 0x5D5A}, {0x5D5B, 0x5D5B}, {0x5D5C, 0x5D5C}, {0x5D5D, 0x5D5D}, + {0x5D5E, 0x5D5E}, {0x5D5F, 0x5D5F}, {0x5D60, 0x5D60}, {0x5D61, 0x5D61}, {0x5D62, 0x5D62}, {0x5D63, 0x5D63}, {0x5D64, 0x5D64}, + {0x5D65, 0x5D65}, {0x5D66, 0x5D66}, {0x5D67, 0x5D67}, {0x5D68, 0x5D68}, {0x5D69, 0x5D69}, {0x5D6A, 0x5D6A}, {0x5D6B, 0x5D6B}, + {0x5D6C, 0x5D6C}, {0x5D6D, 0x5D6D}, {0x5D6E, 0x5D6E}, {0x5D6F, 0x5D6F}, {0x5D70, 0x5D70}, {0x5D71, 0x5D71}, {0x5D72, 0x5D72}, + {0x5D73, 0x5D73}, {0x5D74, 0x5D74}, {0x5D75, 0x5D75}, {0x5D76, 0x5D76}, {0x5D77, 0x5D77}, {0x5D78, 0x5D78}, {0x5D79, 0x5D79}, + {0x5D7A, 0x5D7A}, {0x5D7B, 0x5D7B}, {0x5D7C, 0x5D7C}, {0x5D7D, 0x5D7D}, {0x5D7E, 0x5D7E}, {0x5D7F, 0x5D7F}, {0x5D80, 0x5D80}, + {0x5D81, 0x5D81}, {0x5D82, 0x5D82}, {0x5D83, 0x5D83}, {0x5D84, 0x5D84}, {0x5D85, 0x5D85}, {0x5D86, 0x5D86}, {0x5D87, 0x5D87}, + {0x5D88, 0x5D88}, {0x5D89, 0x5D89}, {0x5D8A, 0x5D8A}, {0x5D8B, 0x5D8B}, {0x5D8C, 0x5D8C}, {0x5D8D, 0x5D8D}, {0x5D8E, 0x5D8E}, + {0x5D8F, 0x5D8F}, {0x5D90, 0x5D90}, {0x5D91, 0x5D91}, {0x5D92, 0x5D92}, {0x5D93, 0x5D93}, {0x5D94, 0x5D94}, {0x5D95, 0x5D95}, + {0x5D96, 0x5D96}, {0x5D97, 0x5D97}, {0x5D98, 0x5D98}, {0x5D99, 0x5D99}, {0x5D9A, 0x5D9A}, {0x5D9B, 0x5D9B}, {0x5D9C, 0x5D9C}, + {0x5D9D, 0x5D9D}, {0x5D9E, 0x5D9E}, {0x5D9F, 0x5D9F}, {0x5DA0, 0x5DA0}, {0x5DA1, 0x5DA1}, {0x5DA2, 0x5DA2}, {0x5DA3, 0x5DA3}, + {0x5DA4, 0x5DA4}, {0x5DA5, 0x5DA5}, {0x5DA6, 0x5DA6}, {0x5DA7, 0x5DA7}, {0x5DA8, 0x5DA8}, {0x5DA9, 0x5DA9}, {0x5DAA, 0x5DAA}, + {0x5DAB, 0x5DAB}, {0x5DAC, 0x5DAC}, {0x5DAD, 0x5DAD}, {0x5DAE, 0x5DAE}, {0x5DAF, 0x5DAF}, {0x5DB0, 0x5DB0}, {0x5DB1, 0x5DB1}, + {0x5DB2, 0x5DB2}, {0x5DB3, 0x5DB3}, {0x5DB4, 0x5DB4}, {0x5DB5, 0x5DB5}, {0x5DB6, 0x5DB6}, {0x5DB7, 0x5DB7}, {0x5DB8, 0x5DB8}, + {0x5DB9, 0x5DB9}, {0x5DBA, 0x5DBA}, {0x5DBB, 0x5DBB}, {0x5DBC, 0x5DBC}, {0x5DBD, 0x5DBD}, {0x5DBE, 0x5DBE}, {0x5DBF, 0x5DBF}, + {0x5DC0, 0x5DC0}, {0x5DC1, 0x5DC1}, {0x5DC2, 0x5DC2}, {0x5DC3, 0x5DC3}, {0x5DC4, 0x5DC4}, {0x5DC5, 0x5DC5}, {0x5DC6, 0x5DC6}, + {0x5DC7, 0x5DC7}, {0x5DC8, 0x5DC8}, {0x5DC9, 0x5DC9}, {0x5DCA, 0x5DCA}, {0x5DCB, 0x5DCB}, {0x5DCC, 0x5DCC}, {0x5DCD, 0x5DCD}, + {0x5DCE, 0x5DCE}, {0x5DCF, 0x5DCF}, {0x5DD0, 0x5DD0}, {0x5DD1, 0x5DD1}, {0x5DD2, 0x5DD2}, {0x5DD3, 0x5DD3}, {0x5DD4, 0x5DD4}, + {0x5DD5, 0x5DD5}, {0x5DD6, 0x5DD6}, {0x5DD7, 0x5DD7}, {0x5DD8, 0x5DD8}, {0x5DD9, 0x5DD9}, {0x5DDA, 0x5DDA}, {0x5DDB, 0x5DDB}, + {0x5DDC, 0x5DDC}, {0x5DDD, 0x5DDD}, {0x5DDE, 0x5DDE}, {0x5DDF, 0x5DDF}, {0x5DE0, 0x5DE0}, {0x5DE1, 0x5DE1}, {0x5DE2, 0x5DE2}, + {0x5DE3, 0x5DE3}, {0x5DE4, 0x5DE4}, {0x5DE5, 0x5DE5}, {0x5DE6, 0x5DE6}, {0x5DE7, 0x5DE7}, {0x5DE8, 0x5DE8}, {0x5DE9, 0x5DE9}, + {0x5DEA, 0x5DEA}, {0x5DEB, 0x5DEB}, {0x5DEC, 0x5DEC}, {0x5DED, 0x5DED}, {0x5DEE, 0x5DEE}, {0x5DEF, 0x5DEF}, {0x5DF0, 0x5DF0}, + {0x5DF1, 0x5DF1}, {0x5DF2, 0x5DF2}, {0x5DF3, 0x5DF3}, {0x5DF4, 0x5DF4}, {0x5DF5, 0x5DF5}, {0x5DF6, 0x5DF6}, {0x5DF7, 0x5DF7}, + {0x5DF8, 0x5DF8}, {0x5DF9, 0x5DF9}, {0x5DFA, 0x5DFA}, {0x5DFB, 0x5DFB}, {0x5DFC, 0x5DFC}, {0x5DFD, 0x5DFD}, {0x5DFE, 0x5DFE}, + {0x5DFF, 0x5DFF}, {0x5E00, 0x5E00}, {0x5E01, 0x5E01}, {0x5E02, 0x5E02}, {0x5E03, 0x5E03}, {0x5E04, 0x5E04}, {0x5E05, 0x5E05}, + {0x5E06, 0x5E06}, {0x5E07, 0x5E07}, {0x5E08, 0x5E08}, {0x5E09, 0x5E09}, {0x5E0A, 0x5E0A}, {0x5E0B, 0x5E0B}, {0x5E0C, 0x5E0C}, + {0x5E0D, 0x5E0D}, {0x5E0E, 0x5E0E}, {0x5E0F, 0x5E0F}, {0x5E10, 0x5E10}, {0x5E11, 0x5E11}, {0x5E12, 0x5E12}, {0x5E13, 0x5E13}, + {0x5E14, 0x5E14}, {0x5E15, 0x5E15}, {0x5E16, 0x5E16}, {0x5E17, 0x5E17}, {0x5E18, 0x5E18}, {0x5E19, 0x5E19}, {0x5E1A, 0x5E1A}, + {0x5E1B, 0x5E1B}, {0x5E1C, 0x5E1C}, {0x5E1D, 0x5E1D}, {0x5E1E, 0x5E1E}, {0x5E1F, 0x5E1F}, {0x5E20, 0x5E20}, {0x5E21, 0x5E21}, + {0x5E22, 0x5E22}, {0x5E23, 0x5E23}, {0x5E24, 0x5E24}, {0x5E25, 0x5E25}, {0x5E26, 0x5E26}, {0x5E27, 0x5E27}, {0x5E28, 0x5E28}, + {0x5E29, 0x5E29}, {0x5E2A, 0x5E2A}, {0x5E2B, 0x5E2B}, {0x5E2C, 0x5E2C}, {0x5E2D, 0x5E2D}, {0x5E2E, 0x5E2E}, {0x5E2F, 0x5E2F}, + {0x5E30, 0x5E30}, {0x5E31, 0x5E31}, {0x5E32, 0x5E32}, {0x5E33, 0x5E33}, {0x5E34, 0x5E34}, {0x5E35, 0x5E35}, {0x5E36, 0x5E36}, + {0x5E37, 0x5E37}, {0x5E38, 0x5E38}, {0x5E39, 0x5E39}, {0x5E3A, 0x5E3A}, {0x5E3B, 0x5E3B}, {0x5E3C, 0x5E3C}, {0x5E3D, 0x5E3D}, + {0x5E3E, 0x5E3E}, {0x5E3F, 0x5E3F}, {0x5E40, 0x5E40}, {0x5E41, 0x5E41}, {0x5E42, 0x5E42}, {0x5E43, 0x5E43}, {0x5E44, 0x5E44}, + {0x5E45, 0x5E45}, {0x5E46, 0x5E46}, {0x5E47, 0x5E47}, {0x5E48, 0x5E48}, {0x5E49, 0x5E49}, {0x5E4A, 0x5E4A}, {0x5E4B, 0x5E4B}, + {0x5E4C, 0x5E4C}, {0x5E4D, 0x5E4D}, {0x5E4E, 0x5E4E}, {0x5E4F, 0x5E4F}, {0x5E50, 0x5E50}, {0x5E51, 0x5E51}, {0x5E52, 0x5E52}, + {0x5E53, 0x5E53}, {0x5E54, 0x5E54}, {0x5E55, 0x5E55}, {0x5E56, 0x5E56}, {0x5E57, 0x5E57}, {0x5E58, 0x5E58}, {0x5E59, 0x5E59}, + {0x5E5A, 0x5E5A}, {0x5E5B, 0x5E5B}, {0x5E5C, 0x5E5C}, {0x5E5D, 0x5E5D}, {0x5E5E, 0x5E5E}, {0x5E5F, 0x5E5F}, {0x5E60, 0x5E60}, + {0x5E61, 0x5E61}, {0x5E62, 0x5E62}, {0x5E63, 0x5E63}, {0x5E64, 0x5E64}, {0x5E65, 0x5E65}, {0x5E66, 0x5E66}, {0x5E67, 0x5E67}, + {0x5E68, 0x5E68}, {0x5E69, 0x5E69}, {0x5E6A, 0x5E6A}, {0x5E6B, 0x5E6B}, {0x5E6C, 0x5E6C}, {0x5E6D, 0x5E6D}, {0x5E6E, 0x5E6E}, + {0x5E6F, 0x5E6F}, {0x5E70, 0x5E70}, {0x5E71, 0x5E71}, {0x5E72, 0x5E72}, {0x5E73, 0x5E73}, {0x5E74, 0x5E74}, {0x5E75, 0x5E75}, + {0x5E76, 0x5E76}, {0x5E77, 0x5E77}, {0x5E78, 0x5E78}, {0x5E79, 0x5E79}, {0x5E7A, 0x5E7A}, {0x5E7B, 0x5E7B}, {0x5E7C, 0x5E7C}, + {0x5E7D, 0x5E7D}, {0x5E7E, 0x5E7E}, {0x5E7F, 0x5E7F}, {0x5E80, 0x5E80}, {0x5E81, 0x5E81}, {0x5E82, 0x5E82}, {0x5E83, 0x5E83}, + {0x5E84, 0x5E84}, {0x5E85, 0x5E85}, {0x5E86, 0x5E86}, {0x5E87, 0x5E87}, {0x5E88, 0x5E88}, {0x5E89, 0x5E89}, {0x5E8A, 0x5E8A}, + {0x5E8B, 0x5E8B}, {0x5E8C, 0x5E8C}, {0x5E8D, 0x5E8D}, {0x5E8E, 0x5E8E}, {0x5E8F, 0x5E8F}, {0x5E90, 0x5E90}, {0x5E91, 0x5E91}, + {0x5E92, 0x5E92}, {0x5E93, 0x5E93}, {0x5E94, 0x5E94}, {0x5E95, 0x5E95}, {0x5E96, 0x5E96}, {0x5E97, 0x5E97}, {0x5E98, 0x5E98}, + {0x5E99, 0x5E99}, {0x5E9A, 0x5E9A}, {0x5E9B, 0x5E9B}, {0x5E9C, 0x5E9C}, {0x5E9D, 0x5E9D}, {0x5E9E, 0x5E9E}, {0x5E9F, 0x5E9F}, + {0x5EA0, 0x5EA0}, {0x5EA1, 0x5EA1}, {0x5EA2, 0x5EA2}, {0x5EA3, 0x5EA3}, {0x5EA4, 0x5EA4}, {0x5EA5, 0x5EA5}, {0x5EA6, 0x5EA6}, + {0x5EA7, 0x5EA7}, {0x5EA8, 0x5EA8}, {0x5EA9, 0x5EA9}, {0x5EAA, 0x5EAA}, {0x5EAB, 0x5EAB}, {0x5EAC, 0x5EAC}, {0x5EAD, 0x5EAD}, + {0x5EAE, 0x5EAE}, {0x5EAF, 0x5EAF}, {0x5EB0, 0x5EB0}, {0x5EB1, 0x5EB1}, {0x5EB2, 0x5EB2}, {0x5EB3, 0x5EB3}, {0x5EB4, 0x5EB4}, + {0x5EB5, 0x5EB5}, {0x5EB6, 0x5EB6}, {0x5EB7, 0x5EB7}, {0x5EB8, 0x5EB8}, {0x5EB9, 0x5EB9}, {0x5EBA, 0x5EBA}, {0x5EBB, 0x5EBB}, + {0x5EBC, 0x5EBC}, {0x5EBD, 0x5EBD}, {0x5EBE, 0x5EBE}, {0x5EBF, 0x5EBF}, {0x5EC0, 0x5EC0}, {0x5EC1, 0x5EC1}, {0x5EC2, 0x5EC2}, + {0x5EC3, 0x5EC3}, {0x5EC4, 0x5EC4}, {0x5EC5, 0x5EC5}, {0x5EC6, 0x5EC6}, {0x5EC7, 0x5EC7}, {0x5EC8, 0x5EC8}, {0x5EC9, 0x5EC9}, + {0x5ECA, 0x5ECA}, {0x5ECB, 0x5ECB}, {0x5ECC, 0x5ECC}, {0x5ECD, 0x5ECD}, {0x5ECE, 0x5ECE}, {0x5ECF, 0x5ECF}, {0x5ED0, 0x5ED0}, + {0x5ED1, 0x5ED1}, {0x5ED2, 0x5ED2}, {0x5ED3, 0x5ED3}, {0x5ED4, 0x5ED4}, {0x5ED5, 0x5ED5}, {0x5ED6, 0x5ED6}, {0x5ED7, 0x5ED7}, + {0x5ED8, 0x5ED8}, {0x5ED9, 0x5ED9}, {0x5EDA, 0x5EDA}, {0x5EDB, 0x5EDB}, {0x5EDC, 0x5EDC}, {0x5EDD, 0x5EDD}, {0x5EDE, 0x5EDE}, + {0x5EDF, 0x5EDF}, {0x5EE0, 0x5EE0}, {0x5EE1, 0x5EE1}, {0x5EE2, 0x5EE2}, {0x5EE3, 0x5EE3}, {0x5EE4, 0x5EE4}, {0x5EE5, 0x5EE5}, + {0x5EE6, 0x5EE6}, {0x5EE7, 0x5EE7}, {0x5EE8, 0x5EE8}, {0x5EE9, 0x5EE9}, {0x5EEA, 0x5EEA}, {0x5EEB, 0x5EEB}, {0x5EEC, 0x5EEC}, + {0x5EED, 0x5EED}, {0x5EEE, 0x5EEE}, {0x5EEF, 0x5EEF}, {0x5EF0, 0x5EF0}, {0x5EF1, 0x5EF1}, {0x5EF2, 0x5EF2}, {0x5EF3, 0x5EF3}, + {0x5EF4, 0x5EF4}, {0x5EF5, 0x5EF5}, {0x5EF6, 0x5EF6}, {0x5EF7, 0x5EF7}, {0x5EF8, 0x5EF8}, {0x5EF9, 0x5EF9}, {0x5EFA, 0x5EFA}, + {0x5EFB, 0x5EFB}, {0x5EFC, 0x5EFC}, {0x5EFD, 0x5EFD}, {0x5EFE, 0x5EFE}, {0x5EFF, 0x5EFF}, {0x5F00, 0x5F00}, {0x5F01, 0x5F01}, + {0x5F02, 0x5F02}, {0x5F03, 0x5F03}, {0x5F04, 0x5F04}, {0x5F05, 0x5F05}, {0x5F06, 0x5F06}, {0x5F07, 0x5F07}, {0x5F08, 0x5F08}, + {0x5F09, 0x5F09}, {0x5F0A, 0x5F0A}, {0x5F0B, 0x5F0B}, {0x5F0C, 0x5F0C}, {0x5F0D, 0x5F0D}, {0x5F0E, 0x5F0E}, {0x5F0F, 0x5F0F}, + {0x5F10, 0x5F10}, {0x5F11, 0x5F11}, {0x5F12, 0x5F12}, {0x5F13, 0x5F13}, {0x5F14, 0x5F14}, {0x5F15, 0x5F15}, {0x5F16, 0x5F16}, + {0x5F17, 0x5F17}, {0x5F18, 0x5F18}, {0x5F19, 0x5F19}, {0x5F1A, 0x5F1A}, {0x5F1B, 0x5F1B}, {0x5F1C, 0x5F1C}, {0x5F1D, 0x5F1D}, + {0x5F1E, 0x5F1E}, {0x5F1F, 0x5F1F}, {0x5F20, 0x5F20}, {0x5F21, 0x5F21}, {0x5F22, 0x5F22}, {0x5F23, 0x5F23}, {0x5F24, 0x5F24}, + {0x5F25, 0x5F25}, {0x5F26, 0x5F26}, {0x5F27, 0x5F27}, {0x5F28, 0x5F28}, {0x5F29, 0x5F29}, {0x5F2A, 0x5F2A}, {0x5F2B, 0x5F2B}, + {0x5F2C, 0x5F2C}, {0x5F2D, 0x5F2D}, {0x5F2E, 0x5F2E}, {0x5F2F, 0x5F2F}, {0x5F30, 0x5F30}, {0x5F31, 0x5F31}, {0x5F32, 0x5F32}, + {0x5F33, 0x5F33}, {0x5F34, 0x5F34}, {0x5F35, 0x5F35}, {0x5F36, 0x5F36}, {0x5F37, 0x5F37}, {0x5F38, 0x5F38}, {0x5F39, 0x5F39}, + {0x5F3A, 0x5F3A}, {0x5F3B, 0x5F3B}, {0x5F3C, 0x5F3C}, {0x5F3D, 0x5F3D}, {0x5F3E, 0x5F3E}, {0x5F3F, 0x5F3F}, {0x5F40, 0x5F40}, + {0x5F41, 0x5F41}, {0x5F42, 0x5F42}, {0x5F43, 0x5F43}, {0x5F44, 0x5F44}, {0x5F45, 0x5F45}, {0x5F46, 0x5F46}, {0x5F47, 0x5F47}, + {0x5F48, 0x5F48}, {0x5F49, 0x5F49}, {0x5F4A, 0x5F4A}, {0x5F4B, 0x5F4B}, {0x5F4C, 0x5F4C}, {0x5F4D, 0x5F4D}, {0x5F4E, 0x5F4E}, + {0x5F4F, 0x5F4F}, {0x5F50, 0x5F50}, {0x5F51, 0x5F51}, {0x5F52, 0x5F52}, {0x5F53, 0x5F53}, {0x5F54, 0x5F54}, {0x5F55, 0x5F55}, + {0x5F56, 0x5F56}, {0x5F57, 0x5F57}, {0x5F58, 0x5F58}, {0x5F59, 0x5F59}, {0x5F5A, 0x5F5A}, {0x5F5B, 0x5F5B}, {0x5F5C, 0x5F5C}, + {0x5F5D, 0x5F5D}, {0x5F5E, 0x5F5E}, {0x5F5F, 0x5F5F}, {0x5F60, 0x5F60}, {0x5F61, 0x5F61}, {0x5F62, 0x5F62}, {0x5F63, 0x5F63}, + {0x5F64, 0x5F64}, {0x5F65, 0x5F65}, {0x5F66, 0x5F66}, {0x5F67, 0x5F67}, {0x5F68, 0x5F68}, {0x5F69, 0x5F69}, {0x5F6A, 0x5F6A}, + {0x5F6B, 0x5F6B}, {0x5F6C, 0x5F6C}, {0x5F6D, 0x5F6D}, {0x5F6E, 0x5F6E}, {0x5F6F, 0x5F6F}, {0x5F70, 0x5F70}, {0x5F71, 0x5F71}, + {0x5F72, 0x5F72}, {0x5F73, 0x5F73}, {0x5F74, 0x5F74}, {0x5F75, 0x5F75}, {0x5F76, 0x5F76}, {0x5F77, 0x5F77}, {0x5F78, 0x5F78}, + {0x5F79, 0x5F79}, {0x5F7A, 0x5F7A}, {0x5F7B, 0x5F7B}, {0x5F7C, 0x5F7C}, {0x5F7D, 0x5F7D}, {0x5F7E, 0x5F7E}, {0x5F7F, 0x5F7F}, + {0x5F80, 0x5F80}, {0x5F81, 0x5F81}, {0x5F82, 0x5F82}, {0x5F83, 0x5F83}, {0x5F84, 0x5F84}, {0x5F85, 0x5F85}, {0x5F86, 0x5F86}, + {0x5F87, 0x5F87}, {0x5F88, 0x5F88}, {0x5F89, 0x5F89}, {0x5F8A, 0x5F8A}, {0x5F8B, 0x5F8B}, {0x5F8C, 0x5F8C}, {0x5F8D, 0x5F8D}, + {0x5F8E, 0x5F8E}, {0x5F8F, 0x5F8F}, {0x5F90, 0x5F90}, {0x5F91, 0x5F91}, {0x5F92, 0x5F92}, {0x5F93, 0x5F93}, {0x5F94, 0x5F94}, + {0x5F95, 0x5F95}, {0x5F96, 0x5F96}, {0x5F97, 0x5F97}, {0x5F98, 0x5F98}, {0x5F99, 0x5F99}, {0x5F9A, 0x5F9A}, {0x5F9B, 0x5F9B}, + {0x5F9C, 0x5F9C}, {0x5F9D, 0x5F9D}, {0x5F9E, 0x5F9E}, {0x5F9F, 0x5F9F}, {0x5FA0, 0x5FA0}, {0x5FA1, 0x5FA1}, {0x5FA2, 0x5FA2}, + {0x5FA3, 0x5FA3}, {0x5FA4, 0x5FA4}, {0x5FA5, 0x5FA5}, {0x5FA6, 0x5FA6}, {0x5FA7, 0x5FA7}, {0x5FA8, 0x5FA8}, {0x5FA9, 0x5FA9}, + {0x5FAA, 0x5FAA}, {0x5FAB, 0x5FAB}, {0x5FAC, 0x5FAC}, {0x5FAD, 0x5FAD}, {0x5FAE, 0x5FAE}, {0x5FAF, 0x5FAF}, {0x5FB0, 0x5FB0}, + {0x5FB1, 0x5FB1}, {0x5FB2, 0x5FB2}, {0x5FB3, 0x5FB3}, {0x5FB4, 0x5FB4}, {0x5FB5, 0x5FB5}, {0x5FB6, 0x5FB6}, {0x5FB7, 0x5FB7}, + {0x5FB8, 0x5FB8}, {0x5FB9, 0x5FB9}, {0x5FBA, 0x5FBA}, {0x5FBB, 0x5FBB}, {0x5FBC, 0x5FBC}, {0x5FBD, 0x5FBD}, {0x5FBE, 0x5FBE}, + {0x5FBF, 0x5FBF}, {0x5FC0, 0x5FC0}, {0x5FC1, 0x5FC1}, {0x5FC2, 0x5FC2}, {0x5FC3, 0x5FC3}, {0x5FC4, 0x5FC4}, {0x5FC5, 0x5FC5}, + {0x5FC6, 0x5FC6}, {0x5FC7, 0x5FC7}, {0x5FC8, 0x5FC8}, {0x5FC9, 0x5FC9}, {0x5FCA, 0x5FCA}, {0x5FCB, 0x5FCB}, {0x5FCC, 0x5FCC}, + {0x5FCD, 0x5FCD}, {0x5FCE, 0x5FCE}, {0x5FCF, 0x5FCF}, {0x5FD0, 0x5FD0}, {0x5FD1, 0x5FD1}, {0x5FD2, 0x5FD2}, {0x5FD3, 0x5FD3}, + {0x5FD4, 0x5FD4}, {0x5FD5, 0x5FD5}, {0x5FD6, 0x5FD6}, {0x5FD7, 0x5FD7}, {0x5FD8, 0x5FD8}, {0x5FD9, 0x5FD9}, {0x5FDA, 0x5FDA}, + {0x5FDB, 0x5FDB}, {0x5FDC, 0x5FDC}, {0x5FDD, 0x5FDD}, {0x5FDE, 0x5FDE}, {0x5FDF, 0x5FDF}, {0x5FE0, 0x5FE0}, {0x5FE1, 0x5FE1}, + {0x5FE2, 0x5FE2}, {0x5FE3, 0x5FE3}, {0x5FE4, 0x5FE4}, {0x5FE5, 0x5FE5}, {0x5FE6, 0x5FE6}, {0x5FE7, 0x5FE7}, {0x5FE8, 0x5FE8}, + {0x5FE9, 0x5FE9}, {0x5FEA, 0x5FEA}, {0x5FEB, 0x5FEB}, {0x5FEC, 0x5FEC}, {0x5FED, 0x5FED}, {0x5FEE, 0x5FEE}, {0x5FEF, 0x5FEF}, + {0x5FF0, 0x5FF0}, {0x5FF1, 0x5FF1}, {0x5FF2, 0x5FF2}, {0x5FF3, 0x5FF3}, {0x5FF4, 0x5FF4}, {0x5FF5, 0x5FF5}, {0x5FF6, 0x5FF6}, + {0x5FF7, 0x5FF7}, {0x5FF8, 0x5FF8}, {0x5FF9, 0x5FF9}, {0x5FFA, 0x5FFA}, {0x5FFB, 0x5FFB}, {0x5FFC, 0x5FFC}, {0x5FFD, 0x5FFD}, + {0x5FFE, 0x5FFE}, {0x5FFF, 0x5FFF}, {0x6000, 0x6000}, {0x6001, 0x6001}, {0x6002, 0x6002}, {0x6003, 0x6003}, {0x6004, 0x6004}, + {0x6005, 0x6005}, {0x6006, 0x6006}, {0x6007, 0x6007}, {0x6008, 0x6008}, {0x6009, 0x6009}, {0x600A, 0x600A}, {0x600B, 0x600B}, + {0x600C, 0x600C}, {0x600D, 0x600D}, {0x600E, 0x600E}, {0x600F, 0x600F}, {0x6010, 0x6010}, {0x6011, 0x6011}, {0x6012, 0x6012}, + {0x6013, 0x6013}, {0x6014, 0x6014}, {0x6015, 0x6015}, {0x6016, 0x6016}, {0x6017, 0x6017}, {0x6018, 0x6018}, {0x6019, 0x6019}, + {0x601A, 0x601A}, {0x601B, 0x601B}, {0x601C, 0x601C}, {0x601D, 0x601D}, {0x601E, 0x601E}, {0x601F, 0x601F}, {0x6020, 0x6020}, + {0x6021, 0x6021}, {0x6022, 0x6022}, {0x6023, 0x6023}, {0x6024, 0x6024}, {0x6025, 0x6025}, {0x6026, 0x6026}, {0x6027, 0x6027}, + {0x6028, 0x6028}, {0x6029, 0x6029}, {0x602A, 0x602A}, {0x602B, 0x602B}, {0x602C, 0x602C}, {0x602D, 0x602D}, {0x602E, 0x602E}, + {0x602F, 0x602F}, {0x6030, 0x6030}, {0x6031, 0x6031}, {0x6032, 0x6032}, {0x6033, 0x6033}, {0x6034, 0x6034}, {0x6035, 0x6035}, + {0x6036, 0x6036}, {0x6037, 0x6037}, {0x6038, 0x6038}, {0x6039, 0x6039}, {0x603A, 0x603A}, {0x603B, 0x603B}, {0x603C, 0x603C}, + {0x603D, 0x603D}, {0x603E, 0x603E}, {0x603F, 0x603F}, {0x6040, 0x6040}, {0x6041, 0x6041}, {0x6042, 0x6042}, {0x6043, 0x6043}, + {0x6044, 0x6044}, {0x6045, 0x6045}, {0x6046, 0x6046}, {0x6047, 0x6047}, {0x6048, 0x6048}, {0x6049, 0x6049}, {0x604A, 0x604A}, + {0x604B, 0x604B}, {0x604C, 0x604C}, {0x604D, 0x604D}, {0x604E, 0x604E}, {0x604F, 0x604F}, {0x6050, 0x6050}, {0x6051, 0x6051}, + {0x6052, 0x6052}, {0x6053, 0x6053}, {0x6054, 0x6054}, {0x6055, 0x6055}, {0x6056, 0x6056}, {0x6057, 0x6057}, {0x6058, 0x6058}, + {0x6059, 0x6059}, {0x605A, 0x605A}, {0x605B, 0x605B}, {0x605C, 0x605C}, {0x605D, 0x605D}, {0x605E, 0x605E}, {0x605F, 0x605F}, + {0x6060, 0x6060}, {0x6061, 0x6061}, {0x6062, 0x6062}, {0x6063, 0x6063}, {0x6064, 0x6064}, {0x6065, 0x6065}, {0x6066, 0x6066}, + {0x6067, 0x6067}, {0x6068, 0x6068}, {0x6069, 0x6069}, {0x606A, 0x606A}, {0x606B, 0x606B}, {0x606C, 0x606C}, {0x606D, 0x606D}, + {0x606E, 0x606E}, {0x606F, 0x606F}, {0x6070, 0x6070}, {0x6071, 0x6071}, {0x6072, 0x6072}, {0x6073, 0x6073}, {0x6074, 0x6074}, + {0x6075, 0x6075}, {0x6076, 0x6076}, {0x6077, 0x6077}, {0x6078, 0x6078}, {0x6079, 0x6079}, {0x607A, 0x607A}, {0x607B, 0x607B}, + {0x607C, 0x607C}, {0x607D, 0x607D}, {0x607E, 0x607E}, {0x607F, 0x607F}, {0x6080, 0x6080}, {0x6081, 0x6081}, {0x6082, 0x6082}, + {0x6083, 0x6083}, {0x6084, 0x6084}, {0x6085, 0x6085}, {0x6086, 0x6086}, {0x6087, 0x6087}, {0x6088, 0x6088}, {0x6089, 0x6089}, + {0x608A, 0x608A}, {0x608B, 0x608B}, {0x608C, 0x608C}, {0x608D, 0x608D}, {0x608E, 0x608E}, {0x608F, 0x608F}, {0x6090, 0x6090}, + {0x6091, 0x6091}, {0x6092, 0x6092}, {0x6093, 0x6093}, {0x6094, 0x6094}, {0x6095, 0x6095}, {0x6096, 0x6096}, {0x6097, 0x6097}, + {0x6098, 0x6098}, {0x6099, 0x6099}, {0x609A, 0x609A}, {0x609B, 0x609B}, {0x609C, 0x609C}, {0x609D, 0x609D}, {0x609E, 0x609E}, + {0x609F, 0x609F}, {0x60A0, 0x60A0}, {0x60A1, 0x60A1}, {0x60A2, 0x60A2}, {0x60A3, 0x60A3}, {0x60A4, 0x60A4}, {0x60A5, 0x60A5}, + {0x60A6, 0x60A6}, {0x60A7, 0x60A7}, {0x60A8, 0x60A8}, {0x60A9, 0x60A9}, {0x60AA, 0x60AA}, {0x60AB, 0x60AB}, {0x60AC, 0x60AC}, + {0x60AD, 0x60AD}, {0x60AE, 0x60AE}, {0x60AF, 0x60AF}, {0x60B0, 0x60B0}, {0x60B1, 0x60B1}, {0x60B2, 0x60B2}, {0x60B3, 0x60B3}, + {0x60B4, 0x60B4}, {0x60B5, 0x60B5}, {0x60B6, 0x60B6}, {0x60B7, 0x60B7}, {0x60B8, 0x60B8}, {0x60B9, 0x60B9}, {0x60BA, 0x60BA}, + {0x60BB, 0x60BB}, {0x60BC, 0x60BC}, {0x60BD, 0x60BD}, {0x60BE, 0x60BE}, {0x60BF, 0x60BF}, {0x60C0, 0x60C0}, {0x60C1, 0x60C1}, + {0x60C2, 0x60C2}, {0x60C3, 0x60C3}, {0x60C4, 0x60C4}, {0x60C5, 0x60C5}, {0x60C6, 0x60C6}, {0x60C7, 0x60C7}, {0x60C8, 0x60C8}, + {0x60C9, 0x60C9}, {0x60CA, 0x60CA}, {0x60CB, 0x60CB}, {0x60CC, 0x60CC}, {0x60CD, 0x60CD}, {0x60CE, 0x60CE}, {0x60CF, 0x60CF}, + {0x60D0, 0x60D0}, {0x60D1, 0x60D1}, {0x60D2, 0x60D2}, {0x60D3, 0x60D3}, {0x60D4, 0x60D4}, {0x60D5, 0x60D5}, {0x60D6, 0x60D6}, + {0x60D7, 0x60D7}, {0x60D8, 0x60D8}, {0x60D9, 0x60D9}, {0x60DA, 0x60DA}, {0x60DB, 0x60DB}, {0x60DC, 0x60DC}, {0x60DD, 0x60DD}, + {0x60DE, 0x60DE}, {0x60DF, 0x60DF}, {0x60E0, 0x60E0}, {0x60E1, 0x60E1}, {0x60E2, 0x60E2}, {0x60E3, 0x60E3}, {0x60E4, 0x60E4}, + {0x60E5, 0x60E5}, {0x60E6, 0x60E6}, {0x60E7, 0x60E7}, {0x60E8, 0x60E8}, {0x60E9, 0x60E9}, {0x60EA, 0x60EA}, {0x60EB, 0x60EB}, + {0x60EC, 0x60EC}, {0x60ED, 0x60ED}, {0x60EE, 0x60EE}, {0x60EF, 0x60EF}, {0x60F0, 0x60F0}, {0x60F1, 0x60F1}, {0x60F2, 0x60F2}, + {0x60F3, 0x60F3}, {0x60F4, 0x60F4}, {0x60F5, 0x60F5}, {0x60F6, 0x60F6}, {0x60F7, 0x60F7}, {0x60F8, 0x60F8}, {0x60F9, 0x60F9}, + {0x60FA, 0x60FA}, {0x60FB, 0x60FB}, {0x60FC, 0x60FC}, {0x60FD, 0x60FD}, {0x60FE, 0x60FE}, {0x60FF, 0x60FF}, {0x6100, 0x6100}, + {0x6101, 0x6101}, {0x6102, 0x6102}, {0x6103, 0x6103}, {0x6104, 0x6104}, {0x6105, 0x6105}, {0x6106, 0x6106}, {0x6107, 0x6107}, + {0x6108, 0x6108}, {0x6109, 0x6109}, {0x610A, 0x610A}, {0x610B, 0x610B}, {0x610C, 0x610C}, {0x610D, 0x610D}, {0x610E, 0x610E}, + {0x610F, 0x610F}, {0x6110, 0x6110}, {0x6111, 0x6111}, {0x6112, 0x6112}, {0x6113, 0x6113}, {0x6114, 0x6114}, {0x6115, 0x6115}, + {0x6116, 0x6116}, {0x6117, 0x6117}, {0x6118, 0x6118}, {0x6119, 0x6119}, {0x611A, 0x611A}, {0x611B, 0x611B}, {0x611C, 0x611C}, + {0x611D, 0x611D}, {0x611E, 0x611E}, {0x611F, 0x611F}, {0x6120, 0x6120}, {0x6121, 0x6121}, {0x6122, 0x6122}, {0x6123, 0x6123}, + {0x6124, 0x6124}, {0x6125, 0x6125}, {0x6126, 0x6126}, {0x6127, 0x6127}, {0x6128, 0x6128}, {0x6129, 0x6129}, {0x612A, 0x612A}, + {0x612B, 0x612B}, {0x612C, 0x612C}, {0x612D, 0x612D}, {0x612E, 0x612E}, {0x612F, 0x612F}, {0x6130, 0x6130}, {0x6131, 0x6131}, + {0x6132, 0x6132}, {0x6133, 0x6133}, {0x6134, 0x6134}, {0x6135, 0x6135}, {0x6136, 0x6136}, {0x6137, 0x6137}, {0x6138, 0x6138}, + {0x6139, 0x6139}, {0x613A, 0x613A}, {0x613B, 0x613B}, {0x613C, 0x613C}, {0x613D, 0x613D}, {0x613E, 0x613E}, {0x613F, 0x613F}, + {0x6140, 0x6140}, {0x6141, 0x6141}, {0x6142, 0x6142}, {0x6143, 0x6143}, {0x6144, 0x6144}, {0x6145, 0x6145}, {0x6146, 0x6146}, + {0x6147, 0x6147}, {0x6148, 0x6148}, {0x6149, 0x6149}, {0x614A, 0x614A}, {0x614B, 0x614B}, {0x614C, 0x614C}, {0x614D, 0x614D}, + {0x614E, 0x614E}, {0x614F, 0x614F}, {0x6150, 0x6150}, {0x6151, 0x6151}, {0x6152, 0x6152}, {0x6153, 0x6153}, {0x6154, 0x6154}, + {0x6155, 0x6155}, {0x6156, 0x6156}, {0x6157, 0x6157}, {0x6158, 0x6158}, {0x6159, 0x6159}, {0x615A, 0x615A}, {0x615B, 0x615B}, + {0x615C, 0x615C}, {0x615D, 0x615D}, {0x615E, 0x615E}, {0x615F, 0x615F}, {0x6160, 0x6160}, {0x6161, 0x6161}, {0x6162, 0x6162}, + {0x6163, 0x6163}, {0x6164, 0x6164}, {0x6165, 0x6165}, {0x6166, 0x6166}, {0x6167, 0x6167}, {0x6168, 0x6168}, {0x6169, 0x6169}, + {0x616A, 0x616A}, {0x616B, 0x616B}, {0x616C, 0x616C}, {0x616D, 0x616D}, {0x616E, 0x616E}, {0x616F, 0x616F}, {0x6170, 0x6170}, + {0x6171, 0x6171}, {0x6172, 0x6172}, {0x6173, 0x6173}, {0x6174, 0x6174}, {0x6175, 0x6175}, {0x6176, 0x6176}, {0x6177, 0x6177}, + {0x6178, 0x6178}, {0x6179, 0x6179}, {0x617A, 0x617A}, {0x617B, 0x617B}, {0x617C, 0x617C}, {0x617D, 0x617D}, {0x617E, 0x617E}, + {0x617F, 0x617F}, {0x6180, 0x6180}, {0x6181, 0x6181}, {0x6182, 0x6182}, {0x6183, 0x6183}, {0x6184, 0x6184}, {0x6185, 0x6185}, + {0x6186, 0x6186}, {0x6187, 0x6187}, {0x6188, 0x6188}, {0x6189, 0x6189}, {0x618A, 0x618A}, {0x618B, 0x618B}, {0x618C, 0x618C}, + {0x618D, 0x618D}, {0x618E, 0x618E}, {0x618F, 0x618F}, {0x6190, 0x6190}, {0x6191, 0x6191}, {0x6192, 0x6192}, {0x6193, 0x6193}, + {0x6194, 0x6194}, {0x6195, 0x6195}, {0x6196, 0x6196}, {0x6197, 0x6197}, {0x6198, 0x6198}, {0x6199, 0x6199}, {0x619A, 0x619A}, + {0x619B, 0x619B}, {0x619C, 0x619C}, {0x619D, 0x619D}, {0x619E, 0x619E}, {0x619F, 0x619F}, {0x61A0, 0x61A0}, {0x61A1, 0x61A1}, + {0x61A2, 0x61A2}, {0x61A3, 0x61A3}, {0x61A4, 0x61A4}, {0x61A5, 0x61A5}, {0x61A6, 0x61A6}, {0x61A7, 0x61A7}, {0x61A8, 0x61A8}, + {0x61A9, 0x61A9}, {0x61AA, 0x61AA}, {0x61AB, 0x61AB}, {0x61AC, 0x61AC}, {0x61AD, 0x61AD}, {0x61AE, 0x61AE}, {0x61AF, 0x61AF}, + {0x61B0, 0x61B0}, {0x61B1, 0x61B1}, {0x61B2, 0x61B2}, {0x61B3, 0x61B3}, {0x61B4, 0x61B4}, {0x61B5, 0x61B5}, {0x61B6, 0x61B6}, + {0x61B7, 0x61B7}, {0x61B8, 0x61B8}, {0x61B9, 0x61B9}, {0x61BA, 0x61BA}, {0x61BB, 0x61BB}, {0x61BC, 0x61BC}, {0x61BD, 0x61BD}, + {0x61BE, 0x61BE}, {0x61BF, 0x61BF}, {0x61C0, 0x61C0}, {0x61C1, 0x61C1}, {0x61C2, 0x61C2}, {0x61C3, 0x61C3}, {0x61C4, 0x61C4}, + {0x61C5, 0x61C5}, {0x61C6, 0x61C6}, {0x61C7, 0x61C7}, {0x61C8, 0x61C8}, {0x61C9, 0x61C9}, {0x61CA, 0x61CA}, {0x61CB, 0x61CB}, + {0x61CC, 0x61CC}, {0x61CD, 0x61CD}, {0x61CE, 0x61CE}, {0x61CF, 0x61CF}, {0x61D0, 0x61D0}, {0x61D1, 0x61D1}, {0x61D2, 0x61D2}, + {0x61D3, 0x61D3}, {0x61D4, 0x61D4}, {0x61D5, 0x61D5}, {0x61D6, 0x61D6}, {0x61D7, 0x61D7}, {0x61D8, 0x61D8}, {0x61D9, 0x61D9}, + {0x61DA, 0x61DA}, {0x61DB, 0x61DB}, {0x61DC, 0x61DC}, {0x61DD, 0x61DD}, {0x61DE, 0x61DE}, {0x61DF, 0x61DF}, {0x61E0, 0x61E0}, + {0x61E1, 0x61E1}, {0x61E2, 0x61E2}, {0x61E3, 0x61E3}, {0x61E4, 0x61E4}, {0x61E5, 0x61E5}, {0x61E6, 0x61E6}, {0x61E7, 0x61E7}, + {0x61E8, 0x61E8}, {0x61E9, 0x61E9}, {0x61EA, 0x61EA}, {0x61EB, 0x61EB}, {0x61EC, 0x61EC}, {0x61ED, 0x61ED}, {0x61EE, 0x61EE}, + {0x61EF, 0x61EF}, {0x61F0, 0x61F0}, {0x61F1, 0x61F1}, {0x61F2, 0x61F2}, {0x61F3, 0x61F3}, {0x61F4, 0x61F4}, {0x61F5, 0x61F5}, + {0x61F6, 0x61F6}, {0x61F7, 0x61F7}, {0x61F8, 0x61F8}, {0x61F9, 0x61F9}, {0x61FA, 0x61FA}, {0x61FB, 0x61FB}, {0x61FC, 0x61FC}, + {0x61FD, 0x61FD}, {0x61FE, 0x61FE}, {0x61FF, 0x61FF}, {0x6200, 0x6200}, {0x6201, 0x6201}, {0x6202, 0x6202}, {0x6203, 0x6203}, + {0x6204, 0x6204}, {0x6205, 0x6205}, {0x6206, 0x6206}, {0x6207, 0x6207}, {0x6208, 0x6208}, {0x6209, 0x6209}, {0x620A, 0x620A}, + {0x620B, 0x620B}, {0x620C, 0x620C}, {0x620D, 0x620D}, {0x620E, 0x620E}, {0x620F, 0x620F}, {0x6210, 0x6210}, {0x6211, 0x6211}, + {0x6212, 0x6212}, {0x6213, 0x6213}, {0x6214, 0x6214}, {0x6215, 0x6215}, {0x6216, 0x6216}, {0x6217, 0x6217}, {0x6218, 0x6218}, + {0x6219, 0x6219}, {0x621A, 0x621A}, {0x621B, 0x621B}, {0x621C, 0x621C}, {0x621D, 0x621D}, {0x621E, 0x621E}, {0x621F, 0x621F}, + {0x6220, 0x6220}, {0x6221, 0x6221}, {0x6222, 0x6222}, {0x6223, 0x6223}, {0x6224, 0x6224}, {0x6225, 0x6225}, {0x6226, 0x6226}, + {0x6227, 0x6227}, {0x6228, 0x6228}, {0x6229, 0x6229}, {0x622A, 0x622A}, {0x622B, 0x622B}, {0x622C, 0x622C}, {0x622D, 0x622D}, + {0x622E, 0x622E}, {0x622F, 0x622F}, {0x6230, 0x6230}, {0x6231, 0x6231}, {0x6232, 0x6232}, {0x6233, 0x6233}, {0x6234, 0x6234}, + {0x6235, 0x6235}, {0x6236, 0x6236}, {0x6237, 0x6237}, {0x6238, 0x6238}, {0x6239, 0x6239}, {0x623A, 0x623A}, {0x623B, 0x623B}, + {0x623C, 0x623C}, {0x623D, 0x623D}, {0x623E, 0x623E}, {0x623F, 0x623F}, {0x6240, 0x6240}, {0x6241, 0x6241}, {0x6242, 0x6242}, + {0x6243, 0x6243}, {0x6244, 0x6244}, {0x6245, 0x6245}, {0x6246, 0x6246}, {0x6247, 0x6247}, {0x6248, 0x6248}, {0x6249, 0x6249}, + {0x624A, 0x624A}, {0x624B, 0x624B}, {0x624C, 0x624C}, {0x624D, 0x624D}, {0x624E, 0x624E}, {0x624F, 0x624F}, {0x6250, 0x6250}, + {0x6251, 0x6251}, {0x6252, 0x6252}, {0x6253, 0x6253}, {0x6254, 0x6254}, {0x6255, 0x6255}, {0x6256, 0x6256}, {0x6257, 0x6257}, + {0x6258, 0x6258}, {0x6259, 0x6259}, {0x625A, 0x625A}, {0x625B, 0x625B}, {0x625C, 0x625C}, {0x625D, 0x625D}, {0x625E, 0x625E}, + {0x625F, 0x625F}, {0x6260, 0x6260}, {0x6261, 0x6261}, {0x6262, 0x6262}, {0x6263, 0x6263}, {0x6264, 0x6264}, {0x6265, 0x6265}, + {0x6266, 0x6266}, {0x6267, 0x6267}, {0x6268, 0x6268}, {0x6269, 0x6269}, {0x626A, 0x626A}, {0x626B, 0x626B}, {0x626C, 0x626C}, + {0x626D, 0x626D}, {0x626E, 0x626E}, {0x626F, 0x626F}, {0x6270, 0x6270}, {0x6271, 0x6271}, {0x6272, 0x6272}, {0x6273, 0x6273}, + {0x6274, 0x6274}, {0x6275, 0x6275}, {0x6276, 0x6276}, {0x6277, 0x6277}, {0x6278, 0x6278}, {0x6279, 0x6279}, {0x627A, 0x627A}, + {0x627B, 0x627B}, {0x627C, 0x627C}, {0x627D, 0x627D}, {0x627E, 0x627E}, {0x627F, 0x627F}, {0x6280, 0x6280}, {0x6281, 0x6281}, + {0x6282, 0x6282}, {0x6283, 0x6283}, {0x6284, 0x6284}, {0x6285, 0x6285}, {0x6286, 0x6286}, {0x6287, 0x6287}, {0x6288, 0x6288}, + {0x6289, 0x6289}, {0x628A, 0x628A}, {0x628B, 0x628B}, {0x628C, 0x628C}, {0x628D, 0x628D}, {0x628E, 0x628E}, {0x628F, 0x628F}, + {0x6290, 0x6290}, {0x6291, 0x6291}, {0x6292, 0x6292}, {0x6293, 0x6293}, {0x6294, 0x6294}, {0x6295, 0x6295}, {0x6296, 0x6296}, + {0x6297, 0x6297}, {0x6298, 0x6298}, {0x6299, 0x6299}, {0x629A, 0x629A}, {0x629B, 0x629B}, {0x629C, 0x629C}, {0x629D, 0x629D}, + {0x629E, 0x629E}, {0x629F, 0x629F}, {0x62A0, 0x62A0}, {0x62A1, 0x62A1}, {0x62A2, 0x62A2}, {0x62A3, 0x62A3}, {0x62A4, 0x62A4}, + {0x62A5, 0x62A5}, {0x62A6, 0x62A6}, {0x62A7, 0x62A7}, {0x62A8, 0x62A8}, {0x62A9, 0x62A9}, {0x62AA, 0x62AA}, {0x62AB, 0x62AB}, + {0x62AC, 0x62AC}, {0x62AD, 0x62AD}, {0x62AE, 0x62AE}, {0x62AF, 0x62AF}, {0x62B0, 0x62B0}, {0x62B1, 0x62B1}, {0x62B2, 0x62B2}, + {0x62B3, 0x62B3}, {0x62B4, 0x62B4}, {0x62B5, 0x62B5}, {0x62B6, 0x62B6}, {0x62B7, 0x62B7}, {0x62B8, 0x62B8}, {0x62B9, 0x62B9}, + {0x62BA, 0x62BA}, {0x62BB, 0x62BB}, {0x62BC, 0x62BC}, {0x62BD, 0x62BD}, {0x62BE, 0x62BE}, {0x62BF, 0x62BF}, {0x62C0, 0x62C0}, + {0x62C1, 0x62C1}, {0x62C2, 0x62C2}, {0x62C3, 0x62C3}, {0x62C4, 0x62C4}, {0x62C5, 0x62C5}, {0x62C6, 0x62C6}, {0x62C7, 0x62C7}, + {0x62C8, 0x62C8}, {0x62C9, 0x62C9}, {0x62CA, 0x62CA}, {0x62CB, 0x62CB}, {0x62CC, 0x62CC}, {0x62CD, 0x62CD}, {0x62CE, 0x62CE}, + {0x62CF, 0x62CF}, {0x62D0, 0x62D0}, {0x62D1, 0x62D1}, {0x62D2, 0x62D2}, {0x62D3, 0x62D3}, {0x62D4, 0x62D4}, {0x62D5, 0x62D5}, + {0x62D6, 0x62D6}, {0x62D7, 0x62D7}, {0x62D8, 0x62D8}, {0x62D9, 0x62D9}, {0x62DA, 0x62DA}, {0x62DB, 0x62DB}, {0x62DC, 0x62DC}, + {0x62DD, 0x62DD}, {0x62DE, 0x62DE}, {0x62DF, 0x62DF}, {0x62E0, 0x62E0}, {0x62E1, 0x62E1}, {0x62E2, 0x62E2}, {0x62E3, 0x62E3}, + {0x62E4, 0x62E4}, {0x62E5, 0x62E5}, {0x62E6, 0x62E6}, {0x62E7, 0x62E7}, {0x62E8, 0x62E8}, {0x62E9, 0x62E9}, {0x62EA, 0x62EA}, + {0x62EB, 0x62EB}, {0x62EC, 0x62EC}, {0x62ED, 0x62ED}, {0x62EE, 0x62EE}, {0x62EF, 0x62EF}, {0x62F0, 0x62F0}, {0x62F1, 0x62F1}, + {0x62F2, 0x62F2}, {0x62F3, 0x62F3}, {0x62F4, 0x62F4}, {0x62F5, 0x62F5}, {0x62F6, 0x62F6}, {0x62F7, 0x62F7}, {0x62F8, 0x62F8}, + {0x62F9, 0x62F9}, {0x62FA, 0x62FA}, {0x62FB, 0x62FB}, {0x62FC, 0x62FC}, {0x62FD, 0x62FD}, {0x62FE, 0x62FE}, {0x62FF, 0x62FF}, + {0x6300, 0x6300}, {0x6301, 0x6301}, {0x6302, 0x6302}, {0x6303, 0x6303}, {0x6304, 0x6304}, {0x6305, 0x6305}, {0x6306, 0x6306}, + {0x6307, 0x6307}, {0x6308, 0x6308}, {0x6309, 0x6309}, {0x630A, 0x630A}, {0x630B, 0x630B}, {0x630C, 0x630C}, {0x630D, 0x630D}, + {0x630E, 0x630E}, {0x630F, 0x630F}, {0x6310, 0x6310}, {0x6311, 0x6311}, {0x6312, 0x6312}, {0x6313, 0x6313}, {0x6314, 0x6314}, + {0x6315, 0x6315}, {0x6316, 0x6316}, {0x6317, 0x6317}, {0x6318, 0x6318}, {0x6319, 0x6319}, {0x631A, 0x631A}, {0x631B, 0x631B}, + {0x631C, 0x631C}, {0x631D, 0x631D}, {0x631E, 0x631E}, {0x631F, 0x631F}, {0x6320, 0x6320}, {0x6321, 0x6321}, {0x6322, 0x6322}, + {0x6323, 0x6323}, {0x6324, 0x6324}, {0x6325, 0x6325}, {0x6326, 0x6326}, {0x6327, 0x6327}, {0x6328, 0x6328}, {0x6329, 0x6329}, + {0x632A, 0x632A}, {0x632B, 0x632B}, {0x632C, 0x632C}, {0x632D, 0x632D}, {0x632E, 0x632E}, {0x632F, 0x632F}, {0x6330, 0x6330}, + {0x6331, 0x6331}, {0x6332, 0x6332}, {0x6333, 0x6333}, {0x6334, 0x6334}, {0x6335, 0x6335}, {0x6336, 0x6336}, {0x6337, 0x6337}, + {0x6338, 0x6338}, {0x6339, 0x6339}, {0x633A, 0x633A}, {0x633B, 0x633B}, {0x633C, 0x633C}, {0x633D, 0x633D}, {0x633E, 0x633E}, + {0x633F, 0x633F}, {0x6340, 0x6340}, {0x6341, 0x6341}, {0x6342, 0x6342}, {0x6343, 0x6343}, {0x6344, 0x6344}, {0x6345, 0x6345}, + {0x6346, 0x6346}, {0x6347, 0x6347}, {0x6348, 0x6348}, {0x6349, 0x6349}, {0x634A, 0x634A}, {0x634B, 0x634B}, {0x634C, 0x634C}, + {0x634D, 0x634D}, {0x634E, 0x634E}, {0x634F, 0x634F}, {0x6350, 0x6350}, {0x6351, 0x6351}, {0x6352, 0x6352}, {0x6353, 0x6353}, + {0x6354, 0x6354}, {0x6355, 0x6355}, {0x6356, 0x6356}, {0x6357, 0x6357}, {0x6358, 0x6358}, {0x6359, 0x6359}, {0x635A, 0x635A}, + {0x635B, 0x635B}, {0x635C, 0x635C}, {0x635D, 0x635D}, {0x635E, 0x635E}, {0x635F, 0x635F}, {0x6360, 0x6360}, {0x6361, 0x6361}, + {0x6362, 0x6362}, {0x6363, 0x6363}, {0x6364, 0x6364}, {0x6365, 0x6365}, {0x6366, 0x6366}, {0x6367, 0x6367}, {0x6368, 0x6368}, + {0x6369, 0x6369}, {0x636A, 0x636A}, {0x636B, 0x636B}, {0x636C, 0x636C}, {0x636D, 0x636D}, {0x636E, 0x636E}, {0x636F, 0x636F}, + {0x6370, 0x6370}, {0x6371, 0x6371}, {0x6372, 0x6372}, {0x6373, 0x6373}, {0x6374, 0x6374}, {0x6375, 0x6375}, {0x6376, 0x6376}, + {0x6377, 0x6377}, {0x6378, 0x6378}, {0x6379, 0x6379}, {0x637A, 0x637A}, {0x637B, 0x637B}, {0x637C, 0x637C}, {0x637D, 0x637D}, + {0x637E, 0x637E}, {0x637F, 0x637F}, {0x6380, 0x6380}, {0x6381, 0x6381}, {0x6382, 0x6382}, {0x6383, 0x6383}, {0x6384, 0x6384}, + {0x6385, 0x6385}, {0x6386, 0x6386}, {0x6387, 0x6387}, {0x6388, 0x6388}, {0x6389, 0x6389}, {0x638A, 0x638A}, {0x638B, 0x638B}, + {0x638C, 0x638C}, {0x638D, 0x638D}, {0x638E, 0x638E}, {0x638F, 0x638F}, {0x6390, 0x6390}, {0x6391, 0x6391}, {0x6392, 0x6392}, + {0x6393, 0x6393}, {0x6394, 0x6394}, {0x6395, 0x6395}, {0x6396, 0x6396}, {0x6397, 0x6397}, {0x6398, 0x6398}, {0x6399, 0x6399}, + {0x639A, 0x639A}, {0x639B, 0x639B}, {0x639C, 0x639C}, {0x639D, 0x639D}, {0x639E, 0x639E}, {0x639F, 0x639F}, {0x63A0, 0x63A0}, + {0x63A1, 0x63A1}, {0x63A2, 0x63A2}, {0x63A3, 0x63A3}, {0x63A4, 0x63A4}, {0x63A5, 0x63A5}, {0x63A6, 0x63A6}, {0x63A7, 0x63A7}, + {0x63A8, 0x63A8}, {0x63A9, 0x63A9}, {0x63AA, 0x63AA}, {0x63AB, 0x63AB}, {0x63AC, 0x63AC}, {0x63AD, 0x63AD}, {0x63AE, 0x63AE}, + {0x63AF, 0x63AF}, {0x63B0, 0x63B0}, {0x63B1, 0x63B1}, {0x63B2, 0x63B2}, {0x63B3, 0x63B3}, {0x63B4, 0x63B4}, {0x63B5, 0x63B5}, + {0x63B6, 0x63B6}, {0x63B7, 0x63B7}, {0x63B8, 0x63B8}, {0x63B9, 0x63B9}, {0x63BA, 0x63BA}, {0x63BB, 0x63BB}, {0x63BC, 0x63BC}, + {0x63BD, 0x63BD}, {0x63BE, 0x63BE}, {0x63BF, 0x63BF}, {0x63C0, 0x63C0}, {0x63C1, 0x63C1}, {0x63C2, 0x63C2}, {0x63C3, 0x63C3}, + {0x63C4, 0x63C4}, {0x63C5, 0x63C5}, {0x63C6, 0x63C6}, {0x63C7, 0x63C7}, {0x63C8, 0x63C8}, {0x63C9, 0x63C9}, {0x63CA, 0x63CA}, + {0x63CB, 0x63CB}, {0x63CC, 0x63CC}, {0x63CD, 0x63CD}, {0x63CE, 0x63CE}, {0x63CF, 0x63CF}, {0x63D0, 0x63D0}, {0x63D1, 0x63D1}, + {0x63D2, 0x63D2}, {0x63D3, 0x63D3}, {0x63D4, 0x63D4}, {0x63D5, 0x63D5}, {0x63D6, 0x63D6}, {0x63D7, 0x63D7}, {0x63D8, 0x63D8}, + {0x63D9, 0x63D9}, {0x63DA, 0x63DA}, {0x63DB, 0x63DB}, {0x63DC, 0x63DC}, {0x63DD, 0x63DD}, {0x63DE, 0x63DE}, {0x63DF, 0x63DF}, + {0x63E0, 0x63E0}, {0x63E1, 0x63E1}, {0x63E2, 0x63E2}, {0x63E3, 0x63E3}, {0x63E4, 0x63E4}, {0x63E5, 0x63E5}, {0x63E6, 0x63E6}, + {0x63E7, 0x63E7}, {0x63E8, 0x63E8}, {0x63E9, 0x63E9}, {0x63EA, 0x63EA}, {0x63EB, 0x63EB}, {0x63EC, 0x63EC}, {0x63ED, 0x63ED}, + {0x63EE, 0x63EE}, {0x63EF, 0x63EF}, {0x63F0, 0x63F0}, {0x63F1, 0x63F1}, {0x63F2, 0x63F2}, {0x63F3, 0x63F3}, {0x63F4, 0x63F4}, + {0x63F5, 0x63F5}, {0x63F6, 0x63F6}, {0x63F7, 0x63F7}, {0x63F8, 0x63F8}, {0x63F9, 0x63F9}, {0x63FA, 0x63FA}, {0x63FB, 0x63FB}, + {0x63FC, 0x63FC}, {0x63FD, 0x63FD}, {0x63FE, 0x63FE}, {0x63FF, 0x63FF}, {0x6400, 0x6400}, {0x6401, 0x6401}, {0x6402, 0x6402}, + {0x6403, 0x6403}, {0x6404, 0x6404}, {0x6405, 0x6405}, {0x6406, 0x6406}, {0x6407, 0x6407}, {0x6408, 0x6408}, {0x6409, 0x6409}, + {0x640A, 0x640A}, {0x640B, 0x640B}, {0x640C, 0x640C}, {0x640D, 0x640D}, {0x640E, 0x640E}, {0x640F, 0x640F}, {0x6410, 0x6410}, + {0x6411, 0x6411}, {0x6412, 0x6412}, {0x6413, 0x6413}, {0x6414, 0x6414}, {0x6415, 0x6415}, {0x6416, 0x6416}, {0x6417, 0x6417}, + {0x6418, 0x6418}, {0x6419, 0x6419}, {0x641A, 0x641A}, {0x641B, 0x641B}, {0x641C, 0x641C}, {0x641D, 0x641D}, {0x641E, 0x641E}, + {0x641F, 0x641F}, {0x6420, 0x6420}, {0x6421, 0x6421}, {0x6422, 0x6422}, {0x6423, 0x6423}, {0x6424, 0x6424}, {0x6425, 0x6425}, + {0x6426, 0x6426}, {0x6427, 0x6427}, {0x6428, 0x6428}, {0x6429, 0x6429}, {0x642A, 0x642A}, {0x642B, 0x642B}, {0x642C, 0x642C}, + {0x642D, 0x642D}, {0x642E, 0x642E}, {0x642F, 0x642F}, {0x6430, 0x6430}, {0x6431, 0x6431}, {0x6432, 0x6432}, {0x6433, 0x6433}, + {0x6434, 0x6434}, {0x6435, 0x6435}, {0x6436, 0x6436}, {0x6437, 0x6437}, {0x6438, 0x6438}, {0x6439, 0x6439}, {0x643A, 0x643A}, + {0x643B, 0x643B}, {0x643C, 0x643C}, {0x643D, 0x643D}, {0x643E, 0x643E}, {0x643F, 0x643F}, {0x6440, 0x6440}, {0x6441, 0x6441}, + {0x6442, 0x6442}, {0x6443, 0x6443}, {0x6444, 0x6444}, {0x6445, 0x6445}, {0x6446, 0x6446}, {0x6447, 0x6447}, {0x6448, 0x6448}, + {0x6449, 0x6449}, {0x644A, 0x644A}, {0x644B, 0x644B}, {0x644C, 0x644C}, {0x644D, 0x644D}, {0x644E, 0x644E}, {0x644F, 0x644F}, + {0x6450, 0x6450}, {0x6451, 0x6451}, {0x6452, 0x6452}, {0x6453, 0x6453}, {0x6454, 0x6454}, {0x6455, 0x6455}, {0x6456, 0x6456}, + {0x6457, 0x6457}, {0x6458, 0x6458}, {0x6459, 0x6459}, {0x645A, 0x645A}, {0x645B, 0x645B}, {0x645C, 0x645C}, {0x645D, 0x645D}, + {0x645E, 0x645E}, {0x645F, 0x645F}, {0x6460, 0x6460}, {0x6461, 0x6461}, {0x6462, 0x6462}, {0x6463, 0x6463}, {0x6464, 0x6464}, + {0x6465, 0x6465}, {0x6466, 0x6466}, {0x6467, 0x6467}, {0x6468, 0x6468}, {0x6469, 0x6469}, {0x646A, 0x646A}, {0x646B, 0x646B}, + {0x646C, 0x646C}, {0x646D, 0x646D}, {0x646E, 0x646E}, {0x646F, 0x646F}, {0x6470, 0x6470}, {0x6471, 0x6471}, {0x6472, 0x6472}, + {0x6473, 0x6473}, {0x6474, 0x6474}, {0x6475, 0x6475}, {0x6476, 0x6476}, {0x6477, 0x6477}, {0x6478, 0x6478}, {0x6479, 0x6479}, + {0x647A, 0x647A}, {0x647B, 0x647B}, {0x647C, 0x647C}, {0x647D, 0x647D}, {0x647E, 0x647E}, {0x647F, 0x647F}, {0x6480, 0x6480}, + {0x6481, 0x6481}, {0x6482, 0x6482}, {0x6483, 0x6483}, {0x6484, 0x6484}, {0x6485, 0x6485}, {0x6486, 0x6486}, {0x6487, 0x6487}, + {0x6488, 0x6488}, {0x6489, 0x6489}, {0x648A, 0x648A}, {0x648B, 0x648B}, {0x648C, 0x648C}, {0x648D, 0x648D}, {0x648E, 0x648E}, + {0x648F, 0x648F}, {0x6490, 0x6490}, {0x6491, 0x6491}, {0x6492, 0x6492}, {0x6493, 0x6493}, {0x6494, 0x6494}, {0x6495, 0x6495}, + {0x6496, 0x6496}, {0x6497, 0x6497}, {0x6498, 0x6498}, {0x6499, 0x6499}, {0x649A, 0x649A}, {0x649B, 0x649B}, {0x649C, 0x649C}, + {0x649D, 0x649D}, {0x649E, 0x649E}, {0x649F, 0x649F}, {0x64A0, 0x64A0}, {0x64A1, 0x64A1}, {0x64A2, 0x64A2}, {0x64A3, 0x64A3}, + {0x64A4, 0x64A4}, {0x64A5, 0x64A5}, {0x64A6, 0x64A6}, {0x64A7, 0x64A7}, {0x64A8, 0x64A8}, {0x64A9, 0x64A9}, {0x64AA, 0x64AA}, + {0x64AB, 0x64AB}, {0x64AC, 0x64AC}, {0x64AD, 0x64AD}, {0x64AE, 0x64AE}, {0x64AF, 0x64AF}, {0x64B0, 0x64B0}, {0x64B1, 0x64B1}, + {0x64B2, 0x64B2}, {0x64B3, 0x64B3}, {0x64B4, 0x64B4}, {0x64B5, 0x64B5}, {0x64B6, 0x64B6}, {0x64B7, 0x64B7}, {0x64B8, 0x64B8}, + {0x64B9, 0x64B9}, {0x64BA, 0x64BA}, {0x64BB, 0x64BB}, {0x64BC, 0x64BC}, {0x64BD, 0x64BD}, {0x64BE, 0x64BE}, {0x64BF, 0x64BF}, + {0x64C0, 0x64C0}, {0x64C1, 0x64C1}, {0x64C2, 0x64C2}, {0x64C3, 0x64C3}, {0x64C4, 0x64C4}, {0x64C5, 0x64C5}, {0x64C6, 0x64C6}, + {0x64C7, 0x64C7}, {0x64C8, 0x64C8}, {0x64C9, 0x64C9}, {0x64CA, 0x64CA}, {0x64CB, 0x64CB}, {0x64CC, 0x64CC}, {0x64CD, 0x64CD}, + {0x64CE, 0x64CE}, {0x64CF, 0x64CF}, {0x64D0, 0x64D0}, {0x64D1, 0x64D1}, {0x64D2, 0x64D2}, {0x64D3, 0x64D3}, {0x64D4, 0x64D4}, + {0x64D5, 0x64D5}, {0x64D6, 0x64D6}, {0x64D7, 0x64D7}, {0x64D8, 0x64D8}, {0x64D9, 0x64D9}, {0x64DA, 0x64DA}, {0x64DB, 0x64DB}, + {0x64DC, 0x64DC}, {0x64DD, 0x64DD}, {0x64DE, 0x64DE}, {0x64DF, 0x64DF}, {0x64E0, 0x64E0}, {0x64E1, 0x64E1}, {0x64E2, 0x64E2}, + {0x64E3, 0x64E3}, {0x64E4, 0x64E4}, {0x64E5, 0x64E5}, {0x64E6, 0x64E6}, {0x64E7, 0x64E7}, {0x64E8, 0x64E8}, {0x64E9, 0x64E9}, + {0x64EA, 0x64EA}, {0x64EB, 0x64EB}, {0x64EC, 0x64EC}, {0x64ED, 0x64ED}, {0x64EE, 0x64EE}, {0x64EF, 0x64EF}, {0x64F0, 0x64F0}, + {0x64F1, 0x64F1}, {0x64F2, 0x64F2}, {0x64F3, 0x64F3}, {0x64F4, 0x64F4}, {0x64F5, 0x64F5}, {0x64F6, 0x64F6}, {0x64F7, 0x64F7}, + {0x64F8, 0x64F8}, {0x64F9, 0x64F9}, {0x64FA, 0x64FA}, {0x64FB, 0x64FB}, {0x64FC, 0x64FC}, {0x64FD, 0x64FD}, {0x64FE, 0x64FE}, + {0x64FF, 0x64FF}, {0x6500, 0x6500}, {0x6501, 0x6501}, {0x6502, 0x6502}, {0x6503, 0x6503}, {0x6504, 0x6504}, {0x6505, 0x6505}, + {0x6506, 0x6506}, {0x6507, 0x6507}, {0x6508, 0x6508}, {0x6509, 0x6509}, {0x650A, 0x650A}, {0x650B, 0x650B}, {0x650C, 0x650C}, + {0x650D, 0x650D}, {0x650E, 0x650E}, {0x650F, 0x650F}, {0x6510, 0x6510}, {0x6511, 0x6511}, {0x6512, 0x6512}, {0x6513, 0x6513}, + {0x6514, 0x6514}, {0x6515, 0x6515}, {0x6516, 0x6516}, {0x6517, 0x6517}, {0x6518, 0x6518}, {0x6519, 0x6519}, {0x651A, 0x651A}, + {0x651B, 0x651B}, {0x651C, 0x651C}, {0x651D, 0x651D}, {0x651E, 0x651E}, {0x651F, 0x651F}, {0x6520, 0x6520}, {0x6521, 0x6521}, + {0x6522, 0x6522}, {0x6523, 0x6523}, {0x6524, 0x6524}, {0x6525, 0x6525}, {0x6526, 0x6526}, {0x6527, 0x6527}, {0x6528, 0x6528}, + {0x6529, 0x6529}, {0x652A, 0x652A}, {0x652B, 0x652B}, {0x652C, 0x652C}, {0x652D, 0x652D}, {0x652E, 0x652E}, {0x652F, 0x652F}, + {0x6530, 0x6530}, {0x6531, 0x6531}, {0x6532, 0x6532}, {0x6533, 0x6533}, {0x6534, 0x6534}, {0x6535, 0x6535}, {0x6536, 0x6536}, + {0x6537, 0x6537}, {0x6538, 0x6538}, {0x6539, 0x6539}, {0x653A, 0x653A}, {0x653B, 0x653B}, {0x653C, 0x653C}, {0x653D, 0x653D}, + {0x653E, 0x653E}, {0x653F, 0x653F}, {0x6540, 0x6540}, {0x6541, 0x6541}, {0x6542, 0x6542}, {0x6543, 0x6543}, {0x6544, 0x6544}, + {0x6545, 0x6545}, {0x6546, 0x6546}, {0x6547, 0x6547}, {0x6548, 0x6548}, {0x6549, 0x6549}, {0x654A, 0x654A}, {0x654B, 0x654B}, + {0x654C, 0x654C}, {0x654D, 0x654D}, {0x654E, 0x654E}, {0x654F, 0x654F}, {0x6550, 0x6550}, {0x6551, 0x6551}, {0x6552, 0x6552}, + {0x6553, 0x6553}, {0x6554, 0x6554}, {0x6555, 0x6555}, {0x6556, 0x6556}, {0x6557, 0x6557}, {0x6558, 0x6558}, {0x6559, 0x6559}, + {0x655A, 0x655A}, {0x655B, 0x655B}, {0x655C, 0x655C}, {0x655D, 0x655D}, {0x655E, 0x655E}, {0x655F, 0x655F}, {0x6560, 0x6560}, + {0x6561, 0x6561}, {0x6562, 0x6562}, {0x6563, 0x6563}, {0x6564, 0x6564}, {0x6565, 0x6565}, {0x6566, 0x6566}, {0x6567, 0x6567}, + {0x6568, 0x6568}, {0x6569, 0x6569}, {0x656A, 0x656A}, {0x656B, 0x656B}, {0x656C, 0x656C}, {0x656D, 0x656D}, {0x656E, 0x656E}, + {0x656F, 0x656F}, {0x6570, 0x6570}, {0x6571, 0x6571}, {0x6572, 0x6572}, {0x6573, 0x6573}, {0x6574, 0x6574}, {0x6575, 0x6575}, + {0x6576, 0x6576}, {0x6577, 0x6577}, {0x6578, 0x6578}, {0x6579, 0x6579}, {0x657A, 0x657A}, {0x657B, 0x657B}, {0x657C, 0x657C}, + {0x657D, 0x657D}, {0x657E, 0x657E}, {0x657F, 0x657F}, {0x6580, 0x6580}, {0x6581, 0x6581}, {0x6582, 0x6582}, {0x6583, 0x6583}, + {0x6584, 0x6584}, {0x6585, 0x6585}, {0x6586, 0x6586}, {0x6587, 0x6587}, {0x6588, 0x6588}, {0x6589, 0x6589}, {0x658A, 0x658A}, + {0x658B, 0x658B}, {0x658C, 0x658C}, {0x658D, 0x658D}, {0x658E, 0x658E}, {0x658F, 0x658F}, {0x6590, 0x6590}, {0x6591, 0x6591}, + {0x6592, 0x6592}, {0x6593, 0x6593}, {0x6594, 0x6594}, {0x6595, 0x6595}, {0x6596, 0x6596}, {0x6597, 0x6597}, {0x6598, 0x6598}, + {0x6599, 0x6599}, {0x659A, 0x659A}, {0x659B, 0x659B}, {0x659C, 0x659C}, {0x659D, 0x659D}, {0x659E, 0x659E}, {0x659F, 0x659F}, + {0x65A0, 0x65A0}, {0x65A1, 0x65A1}, {0x65A2, 0x65A2}, {0x65A3, 0x65A3}, {0x65A4, 0x65A4}, {0x65A5, 0x65A5}, {0x65A6, 0x65A6}, + {0x65A7, 0x65A7}, {0x65A8, 0x65A8}, {0x65A9, 0x65A9}, {0x65AA, 0x65AA}, {0x65AB, 0x65AB}, {0x65AC, 0x65AC}, {0x65AD, 0x65AD}, + {0x65AE, 0x65AE}, {0x65AF, 0x65AF}, {0x65B0, 0x65B0}, {0x65B1, 0x65B1}, {0x65B2, 0x65B2}, {0x65B3, 0x65B3}, {0x65B4, 0x65B4}, + {0x65B5, 0x65B5}, {0x65B6, 0x65B6}, {0x65B7, 0x65B7}, {0x65B8, 0x65B8}, {0x65B9, 0x65B9}, {0x65BA, 0x65BA}, {0x65BB, 0x65BB}, + {0x65BC, 0x65BC}, {0x65BD, 0x65BD}, {0x65BE, 0x65BE}, {0x65BF, 0x65BF}, {0x65C0, 0x65C0}, {0x65C1, 0x65C1}, {0x65C2, 0x65C2}, + {0x65C3, 0x65C3}, {0x65C4, 0x65C4}, {0x65C5, 0x65C5}, {0x65C6, 0x65C6}, {0x65C7, 0x65C7}, {0x65C8, 0x65C8}, {0x65C9, 0x65C9}, + {0x65CA, 0x65CA}, {0x65CB, 0x65CB}, {0x65CC, 0x65CC}, {0x65CD, 0x65CD}, {0x65CE, 0x65CE}, {0x65CF, 0x65CF}, {0x65D0, 0x65D0}, + {0x65D1, 0x65D1}, {0x65D2, 0x65D2}, {0x65D3, 0x65D3}, {0x65D4, 0x65D4}, {0x65D5, 0x65D5}, {0x65D6, 0x65D6}, {0x65D7, 0x65D7}, + {0x65D8, 0x65D8}, {0x65D9, 0x65D9}, {0x65DA, 0x65DA}, {0x65DB, 0x65DB}, {0x65DC, 0x65DC}, {0x65DD, 0x65DD}, {0x65DE, 0x65DE}, + {0x65DF, 0x65DF}, {0x65E0, 0x65E0}, {0x65E1, 0x65E1}, {0x65E2, 0x65E2}, {0x65E3, 0x65E3}, {0x65E4, 0x65E4}, {0x65E5, 0x65E5}, + {0x65E6, 0x65E6}, {0x65E7, 0x65E7}, {0x65E8, 0x65E8}, {0x65E9, 0x65E9}, {0x65EA, 0x65EA}, {0x65EB, 0x65EB}, {0x65EC, 0x65EC}, + {0x65ED, 0x65ED}, {0x65EE, 0x65EE}, {0x65EF, 0x65EF}, {0x65F0, 0x65F0}, {0x65F1, 0x65F1}, {0x65F2, 0x65F2}, {0x65F3, 0x65F3}, + {0x65F4, 0x65F4}, {0x65F5, 0x65F5}, {0x65F6, 0x65F6}, {0x65F7, 0x65F7}, {0x65F8, 0x65F8}, {0x65F9, 0x65F9}, {0x65FA, 0x65FA}, + {0x65FB, 0x65FB}, {0x65FC, 0x65FC}, {0x65FD, 0x65FD}, {0x65FE, 0x65FE}, {0x65FF, 0x65FF}, {0x6600, 0x6600}, {0x6601, 0x6601}, + {0x6602, 0x6602}, {0x6603, 0x6603}, {0x6604, 0x6604}, {0x6605, 0x6605}, {0x6606, 0x6606}, {0x6607, 0x6607}, {0x6608, 0x6608}, + {0x6609, 0x6609}, {0x660A, 0x660A}, {0x660B, 0x660B}, {0x660C, 0x660C}, {0x660D, 0x660D}, {0x660E, 0x660E}, {0x660F, 0x660F}, + {0x6610, 0x6610}, {0x6611, 0x6611}, {0x6612, 0x6612}, {0x6613, 0x6613}, {0x6614, 0x6614}, {0x6615, 0x6615}, {0x6616, 0x6616}, + {0x6617, 0x6617}, {0x6618, 0x6618}, {0x6619, 0x6619}, {0x661A, 0x661A}, {0x661B, 0x661B}, {0x661C, 0x661C}, {0x661D, 0x661D}, + {0x661E, 0x661E}, {0x661F, 0x661F}, {0x6620, 0x6620}, {0x6621, 0x6621}, {0x6622, 0x6622}, {0x6623, 0x6623}, {0x6624, 0x6624}, + {0x6625, 0x6625}, {0x6626, 0x6626}, {0x6627, 0x6627}, {0x6628, 0x6628}, {0x6629, 0x6629}, {0x662A, 0x662A}, {0x662B, 0x662B}, + {0x662C, 0x662C}, {0x662D, 0x662D}, {0x662E, 0x662E}, {0x662F, 0x662F}, {0x6630, 0x6630}, {0x6631, 0x6631}, {0x6632, 0x6632}, + {0x6633, 0x6633}, {0x6634, 0x6634}, {0x6635, 0x6635}, {0x6636, 0x6636}, {0x6637, 0x6637}, {0x6638, 0x6638}, {0x6639, 0x6639}, + {0x663A, 0x663A}, {0x663B, 0x663B}, {0x663C, 0x663C}, {0x663D, 0x663D}, {0x663E, 0x663E}, {0x663F, 0x663F}, {0x6640, 0x6640}, + {0x6641, 0x6641}, {0x6642, 0x6642}, {0x6643, 0x6643}, {0x6644, 0x6644}, {0x6645, 0x6645}, {0x6646, 0x6646}, {0x6647, 0x6647}, + {0x6648, 0x6648}, {0x6649, 0x6649}, {0x664A, 0x664A}, {0x664B, 0x664B}, {0x664C, 0x664C}, {0x664D, 0x664D}, {0x664E, 0x664E}, + {0x664F, 0x664F}, {0x6650, 0x6650}, {0x6651, 0x6651}, {0x6652, 0x6652}, {0x6653, 0x6653}, {0x6654, 0x6654}, {0x6655, 0x6655}, + {0x6656, 0x6656}, {0x6657, 0x6657}, {0x6658, 0x6658}, {0x6659, 0x6659}, {0x665A, 0x665A}, {0x665B, 0x665B}, {0x665C, 0x665C}, + {0x665D, 0x665D}, {0x665E, 0x665E}, {0x665F, 0x665F}, {0x6660, 0x6660}, {0x6661, 0x6661}, {0x6662, 0x6662}, {0x6663, 0x6663}, + {0x6664, 0x6664}, {0x6665, 0x6665}, {0x6666, 0x6666}, {0x6667, 0x6667}, {0x6668, 0x6668}, {0x6669, 0x6669}, {0x666A, 0x666A}, + {0x666B, 0x666B}, {0x666C, 0x666C}, {0x666D, 0x666D}, {0x666E, 0x666E}, {0x666F, 0x666F}, {0x6670, 0x6670}, {0x6671, 0x6671}, + {0x6672, 0x6672}, {0x6673, 0x6673}, {0x6674, 0x6674}, {0x6675, 0x6675}, {0x6676, 0x6676}, {0x6677, 0x6677}, {0x6678, 0x6678}, + {0x6679, 0x6679}, {0x667A, 0x667A}, {0x667B, 0x667B}, {0x667C, 0x667C}, {0x667D, 0x667D}, {0x667E, 0x667E}, {0x667F, 0x667F}, + {0x6680, 0x6680}, {0x6681, 0x6681}, {0x6682, 0x6682}, {0x6683, 0x6683}, {0x6684, 0x6684}, {0x6685, 0x6685}, {0x6686, 0x6686}, + {0x6687, 0x6687}, {0x6688, 0x6688}, {0x6689, 0x6689}, {0x668A, 0x668A}, {0x668B, 0x668B}, {0x668C, 0x668C}, {0x668D, 0x668D}, + {0x668E, 0x668E}, {0x668F, 0x668F}, {0x6690, 0x6690}, {0x6691, 0x6691}, {0x6692, 0x6692}, {0x6693, 0x6693}, {0x6694, 0x6694}, + {0x6695, 0x6695}, {0x6696, 0x6696}, {0x6697, 0x6697}, {0x6698, 0x6698}, {0x6699, 0x6699}, {0x669A, 0x669A}, {0x669B, 0x669B}, + {0x669C, 0x669C}, {0x669D, 0x669D}, {0x669E, 0x669E}, {0x669F, 0x669F}, {0x66A0, 0x66A0}, {0x66A1, 0x66A1}, {0x66A2, 0x66A2}, + {0x66A3, 0x66A3}, {0x66A4, 0x66A4}, {0x66A5, 0x66A5}, {0x66A6, 0x66A6}, {0x66A7, 0x66A7}, {0x66A8, 0x66A8}, {0x66A9, 0x66A9}, + {0x66AA, 0x66AA}, {0x66AB, 0x66AB}, {0x66AC, 0x66AC}, {0x66AD, 0x66AD}, {0x66AE, 0x66AE}, {0x66AF, 0x66AF}, {0x66B0, 0x66B0}, + {0x66B1, 0x66B1}, {0x66B2, 0x66B2}, {0x66B3, 0x66B3}, {0x66B4, 0x66B4}, {0x66B5, 0x66B5}, {0x66B6, 0x66B6}, {0x66B7, 0x66B7}, + {0x66B8, 0x66B8}, {0x66B9, 0x66B9}, {0x66BA, 0x66BA}, {0x66BB, 0x66BB}, {0x66BC, 0x66BC}, {0x66BD, 0x66BD}, {0x66BE, 0x66BE}, + {0x66BF, 0x66BF}, {0x66C0, 0x66C0}, {0x66C1, 0x66C1}, {0x66C2, 0x66C2}, {0x66C3, 0x66C3}, {0x66C4, 0x66C4}, {0x66C5, 0x66C5}, + {0x66C6, 0x66C6}, {0x66C7, 0x66C7}, {0x66C8, 0x66C8}, {0x66C9, 0x66C9}, {0x66CA, 0x66CA}, {0x66CB, 0x66CB}, {0x66CC, 0x66CC}, + {0x66CD, 0x66CD}, {0x66CE, 0x66CE}, {0x66CF, 0x66CF}, {0x66D0, 0x66D0}, {0x66D1, 0x66D1}, {0x66D2, 0x66D2}, {0x66D3, 0x66D3}, + {0x66D4, 0x66D4}, {0x66D5, 0x66D5}, {0x66D6, 0x66D6}, {0x66D7, 0x66D7}, {0x66D8, 0x66D8}, {0x66D9, 0x66D9}, {0x66DA, 0x66DA}, + {0x66DB, 0x66DB}, {0x66DC, 0x66DC}, {0x66DD, 0x66DD}, {0x66DE, 0x66DE}, {0x66DF, 0x66DF}, {0x66E0, 0x66E0}, {0x66E1, 0x66E1}, + {0x66E2, 0x66E2}, {0x66E3, 0x66E3}, {0x66E4, 0x66E4}, {0x66E5, 0x66E5}, {0x66E6, 0x66E6}, {0x66E7, 0x66E7}, {0x66E8, 0x66E8}, + {0x66E9, 0x66E9}, {0x66EA, 0x66EA}, {0x66EB, 0x66EB}, {0x66EC, 0x66EC}, {0x66ED, 0x66ED}, {0x66EE, 0x66EE}, {0x66EF, 0x66EF}, + {0x66F0, 0x66F0}, {0x66F1, 0x66F1}, {0x66F2, 0x66F2}, {0x66F3, 0x66F3}, {0x66F4, 0x66F4}, {0x66F5, 0x66F5}, {0x66F6, 0x66F6}, + {0x66F7, 0x66F7}, {0x66F8, 0x66F8}, {0x66F9, 0x66F9}, {0x66FA, 0x66FA}, {0x66FB, 0x66FB}, {0x66FC, 0x66FC}, {0x66FD, 0x66FD}, + {0x66FE, 0x66FE}, {0x66FF, 0x66FF}, {0x6700, 0x6700}, {0x6701, 0x6701}, {0x6702, 0x6702}, {0x6703, 0x6703}, {0x6704, 0x6704}, + {0x6705, 0x6705}, {0x6706, 0x6706}, {0x6707, 0x6707}, {0x6708, 0x6708}, {0x6709, 0x6709}, {0x670A, 0x670A}, {0x670B, 0x670B}, + {0x670C, 0x670C}, {0x670D, 0x670D}, {0x670E, 0x670E}, {0x670F, 0x670F}, {0x6710, 0x6710}, {0x6711, 0x6711}, {0x6712, 0x6712}, + {0x6713, 0x6713}, {0x6714, 0x6714}, {0x6715, 0x6715}, {0x6716, 0x6716}, {0x6717, 0x6717}, {0x6718, 0x6718}, {0x6719, 0x6719}, + {0x671A, 0x671A}, {0x671B, 0x671B}, {0x671C, 0x671C}, {0x671D, 0x671D}, {0x671E, 0x671E}, {0x671F, 0x671F}, {0x6720, 0x6720}, + {0x6721, 0x6721}, {0x6722, 0x6722}, {0x6723, 0x6723}, {0x6724, 0x6724}, {0x6725, 0x6725}, {0x6726, 0x6726}, {0x6727, 0x6727}, + {0x6728, 0x6728}, {0x6729, 0x6729}, {0x672A, 0x672A}, {0x672B, 0x672B}, {0x672C, 0x672C}, {0x672D, 0x672D}, {0x672E, 0x672E}, + {0x672F, 0x672F}, {0x6730, 0x6730}, {0x6731, 0x6731}, {0x6732, 0x6732}, {0x6733, 0x6733}, {0x6734, 0x6734}, {0x6735, 0x6735}, + {0x6736, 0x6736}, {0x6737, 0x6737}, {0x6738, 0x6738}, {0x6739, 0x6739}, {0x673A, 0x673A}, {0x673B, 0x673B}, {0x673C, 0x673C}, + {0x673D, 0x673D}, {0x673E, 0x673E}, {0x673F, 0x673F}, {0x6740, 0x6740}, {0x6741, 0x6741}, {0x6742, 0x6742}, {0x6743, 0x6743}, + {0x6744, 0x6744}, {0x6745, 0x6745}, {0x6746, 0x6746}, {0x6747, 0x6747}, {0x6748, 0x6748}, {0x6749, 0x6749}, {0x674A, 0x674A}, + {0x674B, 0x674B}, {0x674C, 0x674C}, {0x674D, 0x674D}, {0x674E, 0x674E}, {0x674F, 0x674F}, {0x6750, 0x6750}, {0x6751, 0x6751}, + {0x6752, 0x6752}, {0x6753, 0x6753}, {0x6754, 0x6754}, {0x6755, 0x6755}, {0x6756, 0x6756}, {0x6757, 0x6757}, {0x6758, 0x6758}, + {0x6759, 0x6759}, {0x675A, 0x675A}, {0x675B, 0x675B}, {0x675C, 0x675C}, {0x675D, 0x675D}, {0x675E, 0x675E}, {0x675F, 0x675F}, + {0x6760, 0x6760}, {0x6761, 0x6761}, {0x6762, 0x6762}, {0x6763, 0x6763}, {0x6764, 0x6764}, {0x6765, 0x6765}, {0x6766, 0x6766}, + {0x6767, 0x6767}, {0x6768, 0x6768}, {0x6769, 0x6769}, {0x676A, 0x676A}, {0x676B, 0x676B}, {0x676C, 0x676C}, {0x676D, 0x676D}, + {0x676E, 0x676E}, {0x676F, 0x676F}, {0x6770, 0x6770}, {0x6771, 0x6771}, {0x6772, 0x6772}, {0x6773, 0x6773}, {0x6774, 0x6774}, + {0x6775, 0x6775}, {0x6776, 0x6776}, {0x6777, 0x6777}, {0x6778, 0x6778}, {0x6779, 0x6779}, {0x677A, 0x677A}, {0x677B, 0x677B}, + {0x677C, 0x677C}, {0x677D, 0x677D}, {0x677E, 0x677E}, {0x677F, 0x677F}, {0x6780, 0x6780}, {0x6781, 0x6781}, {0x6782, 0x6782}, + {0x6783, 0x6783}, {0x6784, 0x6784}, {0x6785, 0x6785}, {0x6786, 0x6786}, {0x6787, 0x6787}, {0x6788, 0x6788}, {0x6789, 0x6789}, + {0x678A, 0x678A}, {0x678B, 0x678B}, {0x678C, 0x678C}, {0x678D, 0x678D}, {0x678E, 0x678E}, {0x678F, 0x678F}, {0x6790, 0x6790}, + {0x6791, 0x6791}, {0x6792, 0x6792}, {0x6793, 0x6793}, {0x6794, 0x6794}, {0x6795, 0x6795}, {0x6796, 0x6796}, {0x6797, 0x6797}, + {0x6798, 0x6798}, {0x6799, 0x6799}, {0x679A, 0x679A}, {0x679B, 0x679B}, {0x679C, 0x679C}, {0x679D, 0x679D}, {0x679E, 0x679E}, + {0x679F, 0x679F}, {0x67A0, 0x67A0}, {0x67A1, 0x67A1}, {0x67A2, 0x67A2}, {0x67A3, 0x67A3}, {0x67A4, 0x67A4}, {0x67A5, 0x67A5}, + {0x67A6, 0x67A6}, {0x67A7, 0x67A7}, {0x67A8, 0x67A8}, {0x67A9, 0x67A9}, {0x67AA, 0x67AA}, {0x67AB, 0x67AB}, {0x67AC, 0x67AC}, + {0x67AD, 0x67AD}, {0x67AE, 0x67AE}, {0x67AF, 0x67AF}, {0x67B0, 0x67B0}, {0x67B1, 0x67B1}, {0x67B2, 0x67B2}, {0x67B3, 0x67B3}, + {0x67B4, 0x67B4}, {0x67B5, 0x67B5}, {0x67B6, 0x67B6}, {0x67B7, 0x67B7}, {0x67B8, 0x67B8}, {0x67B9, 0x67B9}, {0x67BA, 0x67BA}, + {0x67BB, 0x67BB}, {0x67BC, 0x67BC}, {0x67BD, 0x67BD}, {0x67BE, 0x67BE}, {0x67BF, 0x67BF}, {0x67C0, 0x67C0}, {0x67C1, 0x67C1}, + {0x67C2, 0x67C2}, {0x67C3, 0x67C3}, {0x67C4, 0x67C4}, {0x67C5, 0x67C5}, {0x67C6, 0x67C6}, {0x67C7, 0x67C7}, {0x67C8, 0x67C8}, + {0x67C9, 0x67C9}, {0x67CA, 0x67CA}, {0x67CB, 0x67CB}, {0x67CC, 0x67CC}, {0x67CD, 0x67CD}, {0x67CE, 0x67CE}, {0x67CF, 0x67CF}, + {0x67D0, 0x67D0}, {0x67D1, 0x67D1}, {0x67D2, 0x67D2}, {0x67D3, 0x67D3}, {0x67D4, 0x67D4}, {0x67D5, 0x67D5}, {0x67D6, 0x67D6}, + {0x67D7, 0x67D7}, {0x67D8, 0x67D8}, {0x67D9, 0x67D9}, {0x67DA, 0x67DA}, {0x67DB, 0x67DB}, {0x67DC, 0x67DC}, {0x67DD, 0x67DD}, + {0x67DE, 0x67DE}, {0x67DF, 0x67DF}, {0x67E0, 0x67E0}, {0x67E1, 0x67E1}, {0x67E2, 0x67E2}, {0x67E3, 0x67E3}, {0x67E4, 0x67E4}, + {0x67E5, 0x67E5}, {0x67E6, 0x67E6}, {0x67E7, 0x67E7}, {0x67E8, 0x67E8}, {0x67E9, 0x67E9}, {0x67EA, 0x67EA}, {0x67EB, 0x67EB}, + {0x67EC, 0x67EC}, {0x67ED, 0x67ED}, {0x67EE, 0x67EE}, {0x67EF, 0x67EF}, {0x67F0, 0x67F0}, {0x67F1, 0x67F1}, {0x67F2, 0x67F2}, + {0x67F3, 0x67F3}, {0x67F4, 0x67F4}, {0x67F5, 0x67F5}, {0x67F6, 0x67F6}, {0x67F7, 0x67F7}, {0x67F8, 0x67F8}, {0x67F9, 0x67F9}, + {0x67FA, 0x67FA}, {0x67FB, 0x67FB}, {0x67FC, 0x67FC}, {0x67FD, 0x67FD}, {0x67FE, 0x67FE}, {0x67FF, 0x67FF}, {0x6800, 0x6800}, + {0x6801, 0x6801}, {0x6802, 0x6802}, {0x6803, 0x6803}, {0x6804, 0x6804}, {0x6805, 0x6805}, {0x6806, 0x6806}, {0x6807, 0x6807}, + {0x6808, 0x6808}, {0x6809, 0x6809}, {0x680A, 0x680A}, {0x680B, 0x680B}, {0x680C, 0x680C}, {0x680D, 0x680D}, {0x680E, 0x680E}, + {0x680F, 0x680F}, {0x6810, 0x6810}, {0x6811, 0x6811}, {0x6812, 0x6812}, {0x6813, 0x6813}, {0x6814, 0x6814}, {0x6815, 0x6815}, + {0x6816, 0x6816}, {0x6817, 0x6817}, {0x6818, 0x6818}, {0x6819, 0x6819}, {0x681A, 0x681A}, {0x681B, 0x681B}, {0x681C, 0x681C}, + {0x681D, 0x681D}, {0x681E, 0x681E}, {0x681F, 0x681F}, {0x6820, 0x6820}, {0x6821, 0x6821}, {0x6822, 0x6822}, {0x6823, 0x6823}, + {0x6824, 0x6824}, {0x6825, 0x6825}, {0x6826, 0x6826}, {0x6827, 0x6827}, {0x6828, 0x6828}, {0x6829, 0x6829}, {0x682A, 0x682A}, + {0x682B, 0x682B}, {0x682C, 0x682C}, {0x682D, 0x682D}, {0x682E, 0x682E}, {0x682F, 0x682F}, {0x6830, 0x6830}, {0x6831, 0x6831}, + {0x6832, 0x6832}, {0x6833, 0x6833}, {0x6834, 0x6834}, {0x6835, 0x6835}, {0x6836, 0x6836}, {0x6837, 0x6837}, {0x6838, 0x6838}, + {0x6839, 0x6839}, {0x683A, 0x683A}, {0x683B, 0x683B}, {0x683C, 0x683C}, {0x683D, 0x683D}, {0x683E, 0x683E}, {0x683F, 0x683F}, + {0x6840, 0x6840}, {0x6841, 0x6841}, {0x6842, 0x6842}, {0x6843, 0x6843}, {0x6844, 0x6844}, {0x6845, 0x6845}, {0x6846, 0x6846}, + {0x6847, 0x6847}, {0x6848, 0x6848}, {0x6849, 0x6849}, {0x684A, 0x684A}, {0x684B, 0x684B}, {0x684C, 0x684C}, {0x684D, 0x684D}, + {0x684E, 0x684E}, {0x684F, 0x684F}, {0x6850, 0x6850}, {0x6851, 0x6851}, {0x6852, 0x6852}, {0x6853, 0x6853}, {0x6854, 0x6854}, + {0x6855, 0x6855}, {0x6856, 0x6856}, {0x6857, 0x6857}, {0x6858, 0x6858}, {0x6859, 0x6859}, {0x685A, 0x685A}, {0x685B, 0x685B}, + {0x685C, 0x685C}, {0x685D, 0x685D}, {0x685E, 0x685E}, {0x685F, 0x685F}, {0x6860, 0x6860}, {0x6861, 0x6861}, {0x6862, 0x6862}, + {0x6863, 0x6863}, {0x6864, 0x6864}, {0x6865, 0x6865}, {0x6866, 0x6866}, {0x6867, 0x6867}, {0x6868, 0x6868}, {0x6869, 0x6869}, + {0x686A, 0x686A}, {0x686B, 0x686B}, {0x686C, 0x686C}, {0x686D, 0x686D}, {0x686E, 0x686E}, {0x686F, 0x686F}, {0x6870, 0x6870}, + {0x6871, 0x6871}, {0x6872, 0x6872}, {0x6873, 0x6873}, {0x6874, 0x6874}, {0x6875, 0x6875}, {0x6876, 0x6876}, {0x6877, 0x6877}, + {0x6878, 0x6878}, {0x6879, 0x6879}, {0x687A, 0x687A}, {0x687B, 0x687B}, {0x687C, 0x687C}, {0x687D, 0x687D}, {0x687E, 0x687E}, + {0x687F, 0x687F}, {0x6880, 0x6880}, {0x6881, 0x6881}, {0x6882, 0x6882}, {0x6883, 0x6883}, {0x6884, 0x6884}, {0x6885, 0x6885}, + {0x6886, 0x6886}, {0x6887, 0x6887}, {0x6888, 0x6888}, {0x6889, 0x6889}, {0x688A, 0x688A}, {0x688B, 0x688B}, {0x688C, 0x688C}, + {0x688D, 0x688D}, {0x688E, 0x688E}, {0x688F, 0x688F}, {0x6890, 0x6890}, {0x6891, 0x6891}, {0x6892, 0x6892}, {0x6893, 0x6893}, + {0x6894, 0x6894}, {0x6895, 0x6895}, {0x6896, 0x6896}, {0x6897, 0x6897}, {0x6898, 0x6898}, {0x6899, 0x6899}, {0x689A, 0x689A}, + {0x689B, 0x689B}, {0x689C, 0x689C}, {0x689D, 0x689D}, {0x689E, 0x689E}, {0x689F, 0x689F}, {0x68A0, 0x68A0}, {0x68A1, 0x68A1}, + {0x68A2, 0x68A2}, {0x68A3, 0x68A3}, {0x68A4, 0x68A4}, {0x68A5, 0x68A5}, {0x68A6, 0x68A6}, {0x68A7, 0x68A7}, {0x68A8, 0x68A8}, + {0x68A9, 0x68A9}, {0x68AA, 0x68AA}, {0x68AB, 0x68AB}, {0x68AC, 0x68AC}, {0x68AD, 0x68AD}, {0x68AE, 0x68AE}, {0x68AF, 0x68AF}, + {0x68B0, 0x68B0}, {0x68B1, 0x68B1}, {0x68B2, 0x68B2}, {0x68B3, 0x68B3}, {0x68B4, 0x68B4}, {0x68B5, 0x68B5}, {0x68B6, 0x68B6}, + {0x68B7, 0x68B7}, {0x68B8, 0x68B8}, {0x68B9, 0x68B9}, {0x68BA, 0x68BA}, {0x68BB, 0x68BB}, {0x68BC, 0x68BC}, {0x68BD, 0x68BD}, + {0x68BE, 0x68BE}, {0x68BF, 0x68BF}, {0x68C0, 0x68C0}, {0x68C1, 0x68C1}, {0x68C2, 0x68C2}, {0x68C3, 0x68C3}, {0x68C4, 0x68C4}, + {0x68C5, 0x68C5}, {0x68C6, 0x68C6}, {0x68C7, 0x68C7}, {0x68C8, 0x68C8}, {0x68C9, 0x68C9}, {0x68CA, 0x68CA}, {0x68CB, 0x68CB}, + {0x68CC, 0x68CC}, {0x68CD, 0x68CD}, {0x68CE, 0x68CE}, {0x68CF, 0x68CF}, {0x68D0, 0x68D0}, {0x68D1, 0x68D1}, {0x68D2, 0x68D2}, + {0x68D3, 0x68D3}, {0x68D4, 0x68D4}, {0x68D5, 0x68D5}, {0x68D6, 0x68D6}, {0x68D7, 0x68D7}, {0x68D8, 0x68D8}, {0x68D9, 0x68D9}, + {0x68DA, 0x68DA}, {0x68DB, 0x68DB}, {0x68DC, 0x68DC}, {0x68DD, 0x68DD}, {0x68DE, 0x68DE}, {0x68DF, 0x68DF}, {0x68E0, 0x68E0}, + {0x68E1, 0x68E1}, {0x68E2, 0x68E2}, {0x68E3, 0x68E3}, {0x68E4, 0x68E4}, {0x68E5, 0x68E5}, {0x68E6, 0x68E6}, {0x68E7, 0x68E7}, + {0x68E8, 0x68E8}, {0x68E9, 0x68E9}, {0x68EA, 0x68EA}, {0x68EB, 0x68EB}, {0x68EC, 0x68EC}, {0x68ED, 0x68ED}, {0x68EE, 0x68EE}, + {0x68EF, 0x68EF}, {0x68F0, 0x68F0}, {0x68F1, 0x68F1}, {0x68F2, 0x68F2}, {0x68F3, 0x68F3}, {0x68F4, 0x68F4}, {0x68F5, 0x68F5}, + {0x68F6, 0x68F6}, {0x68F7, 0x68F7}, {0x68F8, 0x68F8}, {0x68F9, 0x68F9}, {0x68FA, 0x68FA}, {0x68FB, 0x68FB}, {0x68FC, 0x68FC}, + {0x68FD, 0x68FD}, {0x68FE, 0x68FE}, {0x68FF, 0x68FF}, {0x6900, 0x6900}, {0x6901, 0x6901}, {0x6902, 0x6902}, {0x6903, 0x6903}, + {0x6904, 0x6904}, {0x6905, 0x6905}, {0x6906, 0x6906}, {0x6907, 0x6907}, {0x6908, 0x6908}, {0x6909, 0x6909}, {0x690A, 0x690A}, + {0x690B, 0x690B}, {0x690C, 0x690C}, {0x690D, 0x690D}, {0x690E, 0x690E}, {0x690F, 0x690F}, {0x6910, 0x6910}, {0x6911, 0x6911}, + {0x6912, 0x6912}, {0x6913, 0x6913}, {0x6914, 0x6914}, {0x6915, 0x6915}, {0x6916, 0x6916}, {0x6917, 0x6917}, {0x6918, 0x6918}, + {0x6919, 0x6919}, {0x691A, 0x691A}, {0x691B, 0x691B}, {0x691C, 0x691C}, {0x691D, 0x691D}, {0x691E, 0x691E}, {0x691F, 0x691F}, + {0x6920, 0x6920}, {0x6921, 0x6921}, {0x6922, 0x6922}, {0x6923, 0x6923}, {0x6924, 0x6924}, {0x6925, 0x6925}, {0x6926, 0x6926}, + {0x6927, 0x6927}, {0x6928, 0x6928}, {0x6929, 0x6929}, {0x692A, 0x692A}, {0x692B, 0x692B}, {0x692C, 0x692C}, {0x692D, 0x692D}, + {0x692E, 0x692E}, {0x692F, 0x692F}, {0x6930, 0x6930}, {0x6931, 0x6931}, {0x6932, 0x6932}, {0x6933, 0x6933}, {0x6934, 0x6934}, + {0x6935, 0x6935}, {0x6936, 0x6936}, {0x6937, 0x6937}, {0x6938, 0x6938}, {0x6939, 0x6939}, {0x693A, 0x693A}, {0x693B, 0x693B}, + {0x693C, 0x693C}, {0x693D, 0x693D}, {0x693E, 0x693E}, {0x693F, 0x693F}, {0x6940, 0x6940}, {0x6941, 0x6941}, {0x6942, 0x6942}, + {0x6943, 0x6943}, {0x6944, 0x6944}, {0x6945, 0x6945}, {0x6946, 0x6946}, {0x6947, 0x6947}, {0x6948, 0x6948}, {0x6949, 0x6949}, + {0x694A, 0x694A}, {0x694B, 0x694B}, {0x694C, 0x694C}, {0x694D, 0x694D}, {0x694E, 0x694E}, {0x694F, 0x694F}, {0x6950, 0x6950}, + {0x6951, 0x6951}, {0x6952, 0x6952}, {0x6953, 0x6953}, {0x6954, 0x6954}, {0x6955, 0x6955}, {0x6956, 0x6956}, {0x6957, 0x6957}, + {0x6958, 0x6958}, {0x6959, 0x6959}, {0x695A, 0x695A}, {0x695B, 0x695B}, {0x695C, 0x695C}, {0x695D, 0x695D}, {0x695E, 0x695E}, + {0x695F, 0x695F}, {0x6960, 0x6960}, {0x6961, 0x6961}, {0x6962, 0x6962}, {0x6963, 0x6963}, {0x6964, 0x6964}, {0x6965, 0x6965}, + {0x6966, 0x6966}, {0x6967, 0x6967}, {0x6968, 0x6968}, {0x6969, 0x6969}, {0x696A, 0x696A}, {0x696B, 0x696B}, {0x696C, 0x696C}, + {0x696D, 0x696D}, {0x696E, 0x696E}, {0x696F, 0x696F}, {0x6970, 0x6970}, {0x6971, 0x6971}, {0x6972, 0x6972}, {0x6973, 0x6973}, + {0x6974, 0x6974}, {0x6975, 0x6975}, {0x6976, 0x6976}, {0x6977, 0x6977}, {0x6978, 0x6978}, {0x6979, 0x6979}, {0x697A, 0x697A}, + {0x697B, 0x697B}, {0x697C, 0x697C}, {0x697D, 0x697D}, {0x697E, 0x697E}, {0x697F, 0x697F}, {0x6980, 0x6980}, {0x6981, 0x6981}, + {0x6982, 0x6982}, {0x6983, 0x6983}, {0x6984, 0x6984}, {0x6985, 0x6985}, {0x6986, 0x6986}, {0x6987, 0x6987}, {0x6988, 0x6988}, + {0x6989, 0x6989}, {0x698A, 0x698A}, {0x698B, 0x698B}, {0x698C, 0x698C}, {0x698D, 0x698D}, {0x698E, 0x698E}, {0x698F, 0x698F}, + {0x6990, 0x6990}, {0x6991, 0x6991}, {0x6992, 0x6992}, {0x6993, 0x6993}, {0x6994, 0x6994}, {0x6995, 0x6995}, {0x6996, 0x6996}, + {0x6997, 0x6997}, {0x6998, 0x6998}, {0x6999, 0x6999}, {0x699A, 0x699A}, {0x699B, 0x699B}, {0x699C, 0x699C}, {0x699D, 0x699D}, + {0x699E, 0x699E}, {0x699F, 0x699F}, {0x69A0, 0x69A0}, {0x69A1, 0x69A1}, {0x69A2, 0x69A2}, {0x69A3, 0x69A3}, {0x69A4, 0x69A4}, + {0x69A5, 0x69A5}, {0x69A6, 0x69A6}, {0x69A7, 0x69A7}, {0x69A8, 0x69A8}, {0x69A9, 0x69A9}, {0x69AA, 0x69AA}, {0x69AB, 0x69AB}, + {0x69AC, 0x69AC}, {0x69AD, 0x69AD}, {0x69AE, 0x69AE}, {0x69AF, 0x69AF}, {0x69B0, 0x69B0}, {0x69B1, 0x69B1}, {0x69B2, 0x69B2}, + {0x69B3, 0x69B3}, {0x69B4, 0x69B4}, {0x69B5, 0x69B5}, {0x69B6, 0x69B6}, {0x69B7, 0x69B7}, {0x69B8, 0x69B8}, {0x69B9, 0x69B9}, + {0x69BA, 0x69BA}, {0x69BB, 0x69BB}, {0x69BC, 0x69BC}, {0x69BD, 0x69BD}, {0x69BE, 0x69BE}, {0x69BF, 0x69BF}, {0x69C0, 0x69C0}, + {0x69C1, 0x69C1}, {0x69C2, 0x69C2}, {0x69C3, 0x69C3}, {0x69C4, 0x69C4}, {0x69C5, 0x69C5}, {0x69C6, 0x69C6}, {0x69C7, 0x69C7}, + {0x69C8, 0x69C8}, {0x69C9, 0x69C9}, {0x69CA, 0x69CA}, {0x69CB, 0x69CB}, {0x69CC, 0x69CC}, {0x69CD, 0x69CD}, {0x69CE, 0x69CE}, + {0x69CF, 0x69CF}, {0x69D0, 0x69D0}, {0x69D1, 0x69D1}, {0x69D2, 0x69D2}, {0x69D3, 0x69D3}, {0x69D4, 0x69D4}, {0x69D5, 0x69D5}, + {0x69D6, 0x69D6}, {0x69D7, 0x69D7}, {0x69D8, 0x69D8}, {0x69D9, 0x69D9}, {0x69DA, 0x69DA}, {0x69DB, 0x69DB}, {0x69DC, 0x69DC}, + {0x69DD, 0x69DD}, {0x69DE, 0x69DE}, {0x69DF, 0x69DF}, {0x69E0, 0x69E0}, {0x69E1, 0x69E1}, {0x69E2, 0x69E2}, {0x69E3, 0x69E3}, + {0x69E4, 0x69E4}, {0x69E5, 0x69E5}, {0x69E6, 0x69E6}, {0x69E7, 0x69E7}, {0x69E8, 0x69E8}, {0x69E9, 0x69E9}, {0x69EA, 0x69EA}, + {0x69EB, 0x69EB}, {0x69EC, 0x69EC}, {0x69ED, 0x69ED}, {0x69EE, 0x69EE}, {0x69EF, 0x69EF}, {0x69F0, 0x69F0}, {0x69F1, 0x69F1}, + {0x69F2, 0x69F2}, {0x69F3, 0x69F3}, {0x69F4, 0x69F4}, {0x69F5, 0x69F5}, {0x69F6, 0x69F6}, {0x69F7, 0x69F7}, {0x69F8, 0x69F8}, + {0x69F9, 0x69F9}, {0x69FA, 0x69FA}, {0x69FB, 0x69FB}, {0x69FC, 0x69FC}, {0x69FD, 0x69FD}, {0x69FE, 0x69FE}, {0x69FF, 0x69FF}, + {0x6A00, 0x6A00}, {0x6A01, 0x6A01}, {0x6A02, 0x6A02}, {0x6A03, 0x6A03}, {0x6A04, 0x6A04}, {0x6A05, 0x6A05}, {0x6A06, 0x6A06}, + {0x6A07, 0x6A07}, {0x6A08, 0x6A08}, {0x6A09, 0x6A09}, {0x6A0A, 0x6A0A}, {0x6A0B, 0x6A0B}, {0x6A0C, 0x6A0C}, {0x6A0D, 0x6A0D}, + {0x6A0E, 0x6A0E}, {0x6A0F, 0x6A0F}, {0x6A10, 0x6A10}, {0x6A11, 0x6A11}, {0x6A12, 0x6A12}, {0x6A13, 0x6A13}, {0x6A14, 0x6A14}, + {0x6A15, 0x6A15}, {0x6A16, 0x6A16}, {0x6A17, 0x6A17}, {0x6A18, 0x6A18}, {0x6A19, 0x6A19}, {0x6A1A, 0x6A1A}, {0x6A1B, 0x6A1B}, + {0x6A1C, 0x6A1C}, {0x6A1D, 0x6A1D}, {0x6A1E, 0x6A1E}, {0x6A1F, 0x6A1F}, {0x6A20, 0x6A20}, {0x6A21, 0x6A21}, {0x6A22, 0x6A22}, + {0x6A23, 0x6A23}, {0x6A24, 0x6A24}, {0x6A25, 0x6A25}, {0x6A26, 0x6A26}, {0x6A27, 0x6A27}, {0x6A28, 0x6A28}, {0x6A29, 0x6A29}, + {0x6A2A, 0x6A2A}, {0x6A2B, 0x6A2B}, {0x6A2C, 0x6A2C}, {0x6A2D, 0x6A2D}, {0x6A2E, 0x6A2E}, {0x6A2F, 0x6A2F}, {0x6A30, 0x6A30}, + {0x6A31, 0x6A31}, {0x6A32, 0x6A32}, {0x6A33, 0x6A33}, {0x6A34, 0x6A34}, {0x6A35, 0x6A35}, {0x6A36, 0x6A36}, {0x6A37, 0x6A37}, + {0x6A38, 0x6A38}, {0x6A39, 0x6A39}, {0x6A3A, 0x6A3A}, {0x6A3B, 0x6A3B}, {0x6A3C, 0x6A3C}, {0x6A3D, 0x6A3D}, {0x6A3E, 0x6A3E}, + {0x6A3F, 0x6A3F}, {0x6A40, 0x6A40}, {0x6A41, 0x6A41}, {0x6A42, 0x6A42}, {0x6A43, 0x6A43}, {0x6A44, 0x6A44}, {0x6A45, 0x6A45}, + {0x6A46, 0x6A46}, {0x6A47, 0x6A47}, {0x6A48, 0x6A48}, {0x6A49, 0x6A49}, {0x6A4A, 0x6A4A}, {0x6A4B, 0x6A4B}, {0x6A4C, 0x6A4C}, + {0x6A4D, 0x6A4D}, {0x6A4E, 0x6A4E}, {0x6A4F, 0x6A4F}, {0x6A50, 0x6A50}, {0x6A51, 0x6A51}, {0x6A52, 0x6A52}, {0x6A53, 0x6A53}, + {0x6A54, 0x6A54}, {0x6A55, 0x6A55}, {0x6A56, 0x6A56}, {0x6A57, 0x6A57}, {0x6A58, 0x6A58}, {0x6A59, 0x6A59}, {0x6A5A, 0x6A5A}, + {0x6A5B, 0x6A5B}, {0x6A5C, 0x6A5C}, {0x6A5D, 0x6A5D}, {0x6A5E, 0x6A5E}, {0x6A5F, 0x6A5F}, {0x6A60, 0x6A60}, {0x6A61, 0x6A61}, + {0x6A62, 0x6A62}, {0x6A63, 0x6A63}, {0x6A64, 0x6A64}, {0x6A65, 0x6A65}, {0x6A66, 0x6A66}, {0x6A67, 0x6A67}, {0x6A68, 0x6A68}, + {0x6A69, 0x6A69}, {0x6A6A, 0x6A6A}, {0x6A6B, 0x6A6B}, {0x6A6C, 0x6A6C}, {0x6A6D, 0x6A6D}, {0x6A6E, 0x6A6E}, {0x6A6F, 0x6A6F}, + {0x6A70, 0x6A70}, {0x6A71, 0x6A71}, {0x6A72, 0x6A72}, {0x6A73, 0x6A73}, {0x6A74, 0x6A74}, {0x6A75, 0x6A75}, {0x6A76, 0x6A76}, + {0x6A77, 0x6A77}, {0x6A78, 0x6A78}, {0x6A79, 0x6A79}, {0x6A7A, 0x6A7A}, {0x6A7B, 0x6A7B}, {0x6A7C, 0x6A7C}, {0x6A7D, 0x6A7D}, + {0x6A7E, 0x6A7E}, {0x6A7F, 0x6A7F}, {0x6A80, 0x6A80}, {0x6A81, 0x6A81}, {0x6A82, 0x6A82}, {0x6A83, 0x6A83}, {0x6A84, 0x6A84}, + {0x6A85, 0x6A85}, {0x6A86, 0x6A86}, {0x6A87, 0x6A87}, {0x6A88, 0x6A88}, {0x6A89, 0x6A89}, {0x6A8A, 0x6A8A}, {0x6A8B, 0x6A8B}, + {0x6A8C, 0x6A8C}, {0x6A8D, 0x6A8D}, {0x6A8E, 0x6A8E}, {0x6A8F, 0x6A8F}, {0x6A90, 0x6A90}, {0x6A91, 0x6A91}, {0x6A92, 0x6A92}, + {0x6A93, 0x6A93}, {0x6A94, 0x6A94}, {0x6A95, 0x6A95}, {0x6A96, 0x6A96}, {0x6A97, 0x6A97}, {0x6A98, 0x6A98}, {0x6A99, 0x6A99}, + {0x6A9A, 0x6A9A}, {0x6A9B, 0x6A9B}, {0x6A9C, 0x6A9C}, {0x6A9D, 0x6A9D}, {0x6A9E, 0x6A9E}, {0x6A9F, 0x6A9F}, {0x6AA0, 0x6AA0}, + {0x6AA1, 0x6AA1}, {0x6AA2, 0x6AA2}, {0x6AA3, 0x6AA3}, {0x6AA4, 0x6AA4}, {0x6AA5, 0x6AA5}, {0x6AA6, 0x6AA6}, {0x6AA7, 0x6AA7}, + {0x6AA8, 0x6AA8}, {0x6AA9, 0x6AA9}, {0x6AAA, 0x6AAA}, {0x6AAB, 0x6AAB}, {0x6AAC, 0x6AAC}, {0x6AAD, 0x6AAD}, {0x6AAE, 0x6AAE}, + {0x6AAF, 0x6AAF}, {0x6AB0, 0x6AB0}, {0x6AB1, 0x6AB1}, {0x6AB2, 0x6AB2}, {0x6AB3, 0x6AB3}, {0x6AB4, 0x6AB4}, {0x6AB5, 0x6AB5}, + {0x6AB6, 0x6AB6}, {0x6AB7, 0x6AB7}, {0x6AB8, 0x6AB8}, {0x6AB9, 0x6AB9}, {0x6ABA, 0x6ABA}, {0x6ABB, 0x6ABB}, {0x6ABC, 0x6ABC}, + {0x6ABD, 0x6ABD}, {0x6ABE, 0x6ABE}, {0x6ABF, 0x6ABF}, {0x6AC0, 0x6AC0}, {0x6AC1, 0x6AC1}, {0x6AC2, 0x6AC2}, {0x6AC3, 0x6AC3}, + {0x6AC4, 0x6AC4}, {0x6AC5, 0x6AC5}, {0x6AC6, 0x6AC6}, {0x6AC7, 0x6AC7}, {0x6AC8, 0x6AC8}, {0x6AC9, 0x6AC9}, {0x6ACA, 0x6ACA}, + {0x6ACB, 0x6ACB}, {0x6ACC, 0x6ACC}, {0x6ACD, 0x6ACD}, {0x6ACE, 0x6ACE}, {0x6ACF, 0x6ACF}, {0x6AD0, 0x6AD0}, {0x6AD1, 0x6AD1}, + {0x6AD2, 0x6AD2}, {0x6AD3, 0x6AD3}, {0x6AD4, 0x6AD4}, {0x6AD5, 0x6AD5}, {0x6AD6, 0x6AD6}, {0x6AD7, 0x6AD7}, {0x6AD8, 0x6AD8}, + {0x6AD9, 0x6AD9}, {0x6ADA, 0x6ADA}, {0x6ADB, 0x6ADB}, {0x6ADC, 0x6ADC}, {0x6ADD, 0x6ADD}, {0x6ADE, 0x6ADE}, {0x6ADF, 0x6ADF}, + {0x6AE0, 0x6AE0}, {0x6AE1, 0x6AE1}, {0x6AE2, 0x6AE2}, {0x6AE3, 0x6AE3}, {0x6AE4, 0x6AE4}, {0x6AE5, 0x6AE5}, {0x6AE6, 0x6AE6}, + {0x6AE7, 0x6AE7}, {0x6AE8, 0x6AE8}, {0x6AE9, 0x6AE9}, {0x6AEA, 0x6AEA}, {0x6AEB, 0x6AEB}, {0x6AEC, 0x6AEC}, {0x6AED, 0x6AED}, + {0x6AEE, 0x6AEE}, {0x6AEF, 0x6AEF}, {0x6AF0, 0x6AF0}, {0x6AF1, 0x6AF1}, {0x6AF2, 0x6AF2}, {0x6AF3, 0x6AF3}, {0x6AF4, 0x6AF4}, + {0x6AF5, 0x6AF5}, {0x6AF6, 0x6AF6}, {0x6AF7, 0x6AF7}, {0x6AF8, 0x6AF8}, {0x6AF9, 0x6AF9}, {0x6AFA, 0x6AFA}, {0x6AFB, 0x6AFB}, + {0x6AFC, 0x6AFC}, {0x6AFD, 0x6AFD}, {0x6AFE, 0x6AFE}, {0x6AFF, 0x6AFF}, {0x6B00, 0x6B00}, {0x6B01, 0x6B01}, {0x6B02, 0x6B02}, + {0x6B03, 0x6B03}, {0x6B04, 0x6B04}, {0x6B05, 0x6B05}, {0x6B06, 0x6B06}, {0x6B07, 0x6B07}, {0x6B08, 0x6B08}, {0x6B09, 0x6B09}, + {0x6B0A, 0x6B0A}, {0x6B0B, 0x6B0B}, {0x6B0C, 0x6B0C}, {0x6B0D, 0x6B0D}, {0x6B0E, 0x6B0E}, {0x6B0F, 0x6B0F}, {0x6B10, 0x6B10}, + {0x6B11, 0x6B11}, {0x6B12, 0x6B12}, {0x6B13, 0x6B13}, {0x6B14, 0x6B14}, {0x6B15, 0x6B15}, {0x6B16, 0x6B16}, {0x6B17, 0x6B17}, + {0x6B18, 0x6B18}, {0x6B19, 0x6B19}, {0x6B1A, 0x6B1A}, {0x6B1B, 0x6B1B}, {0x6B1C, 0x6B1C}, {0x6B1D, 0x6B1D}, {0x6B1E, 0x6B1E}, + {0x6B1F, 0x6B1F}, {0x6B20, 0x6B20}, {0x6B21, 0x6B21}, {0x6B22, 0x6B22}, {0x6B23, 0x6B23}, {0x6B24, 0x6B24}, {0x6B25, 0x6B25}, + {0x6B26, 0x6B26}, {0x6B27, 0x6B27}, {0x6B28, 0x6B28}, {0x6B29, 0x6B29}, {0x6B2A, 0x6B2A}, {0x6B2B, 0x6B2B}, {0x6B2C, 0x6B2C}, + {0x6B2D, 0x6B2D}, {0x6B2E, 0x6B2E}, {0x6B2F, 0x6B2F}, {0x6B30, 0x6B30}, {0x6B31, 0x6B31}, {0x6B32, 0x6B32}, {0x6B33, 0x6B33}, + {0x6B34, 0x6B34}, {0x6B35, 0x6B35}, {0x6B36, 0x6B36}, {0x6B37, 0x6B37}, {0x6B38, 0x6B38}, {0x6B39, 0x6B39}, {0x6B3A, 0x6B3A}, + {0x6B3B, 0x6B3B}, {0x6B3C, 0x6B3C}, {0x6B3D, 0x6B3D}, {0x6B3E, 0x6B3E}, {0x6B3F, 0x6B3F}, {0x6B40, 0x6B40}, {0x6B41, 0x6B41}, + {0x6B42, 0x6B42}, {0x6B43, 0x6B43}, {0x6B44, 0x6B44}, {0x6B45, 0x6B45}, {0x6B46, 0x6B46}, {0x6B47, 0x6B47}, {0x6B48, 0x6B48}, + {0x6B49, 0x6B49}, {0x6B4A, 0x6B4A}, {0x6B4B, 0x6B4B}, {0x6B4C, 0x6B4C}, {0x6B4D, 0x6B4D}, {0x6B4E, 0x6B4E}, {0x6B4F, 0x6B4F}, + {0x6B50, 0x6B50}, {0x6B51, 0x6B51}, {0x6B52, 0x6B52}, {0x6B53, 0x6B53}, {0x6B54, 0x6B54}, {0x6B55, 0x6B55}, {0x6B56, 0x6B56}, + {0x6B57, 0x6B57}, {0x6B58, 0x6B58}, {0x6B59, 0x6B59}, {0x6B5A, 0x6B5A}, {0x6B5B, 0x6B5B}, {0x6B5C, 0x6B5C}, {0x6B5D, 0x6B5D}, + {0x6B5E, 0x6B5E}, {0x6B5F, 0x6B5F}, {0x6B60, 0x6B60}, {0x6B61, 0x6B61}, {0x6B62, 0x6B62}, {0x6B63, 0x6B63}, {0x6B64, 0x6B64}, + {0x6B65, 0x6B65}, {0x6B66, 0x6B66}, {0x6B67, 0x6B67}, {0x6B68, 0x6B68}, {0x6B69, 0x6B69}, {0x6B6A, 0x6B6A}, {0x6B6B, 0x6B6B}, + {0x6B6C, 0x6B6C}, {0x6B6D, 0x6B6D}, {0x6B6E, 0x6B6E}, {0x6B6F, 0x6B6F}, {0x6B70, 0x6B70}, {0x6B71, 0x6B71}, {0x6B72, 0x6B72}, + {0x6B73, 0x6B73}, {0x6B74, 0x6B74}, {0x6B75, 0x6B75}, {0x6B76, 0x6B76}, {0x6B77, 0x6B77}, {0x6B78, 0x6B78}, {0x6B79, 0x6B79}, + {0x6B7A, 0x6B7A}, {0x6B7B, 0x6B7B}, {0x6B7C, 0x6B7C}, {0x6B7D, 0x6B7D}, {0x6B7E, 0x6B7E}, {0x6B7F, 0x6B7F}, {0x6B80, 0x6B80}, + {0x6B81, 0x6B81}, {0x6B82, 0x6B82}, {0x6B83, 0x6B83}, {0x6B84, 0x6B84}, {0x6B85, 0x6B85}, {0x6B86, 0x6B86}, {0x6B87, 0x6B87}, + {0x6B88, 0x6B88}, {0x6B89, 0x6B89}, {0x6B8A, 0x6B8A}, {0x6B8B, 0x6B8B}, {0x6B8C, 0x6B8C}, {0x6B8D, 0x6B8D}, {0x6B8E, 0x6B8E}, + {0x6B8F, 0x6B8F}, {0x6B90, 0x6B90}, {0x6B91, 0x6B91}, {0x6B92, 0x6B92}, {0x6B93, 0x6B93}, {0x6B94, 0x6B94}, {0x6B95, 0x6B95}, + {0x6B96, 0x6B96}, {0x6B97, 0x6B97}, {0x6B98, 0x6B98}, {0x6B99, 0x6B99}, {0x6B9A, 0x6B9A}, {0x6B9B, 0x6B9B}, {0x6B9C, 0x6B9C}, + {0x6B9D, 0x6B9D}, {0x6B9E, 0x6B9E}, {0x6B9F, 0x6B9F}, {0x6BA0, 0x6BA0}, {0x6BA1, 0x6BA1}, {0x6BA2, 0x6BA2}, {0x6BA3, 0x6BA3}, + {0x6BA4, 0x6BA4}, {0x6BA5, 0x6BA5}, {0x6BA6, 0x6BA6}, {0x6BA7, 0x6BA7}, {0x6BA8, 0x6BA8}, {0x6BA9, 0x6BA9}, {0x6BAA, 0x6BAA}, + {0x6BAB, 0x6BAB}, {0x6BAC, 0x6BAC}, {0x6BAD, 0x6BAD}, {0x6BAE, 0x6BAE}, {0x6BAF, 0x6BAF}, {0x6BB0, 0x6BB0}, {0x6BB1, 0x6BB1}, + {0x6BB2, 0x6BB2}, {0x6BB3, 0x6BB3}, {0x6BB4, 0x6BB4}, {0x6BB5, 0x6BB5}, {0x6BB6, 0x6BB6}, {0x6BB7, 0x6BB7}, {0x6BB8, 0x6BB8}, + {0x6BB9, 0x6BB9}, {0x6BBA, 0x6BBA}, {0x6BBB, 0x6BBB}, {0x6BBC, 0x6BBC}, {0x6BBD, 0x6BBD}, {0x6BBE, 0x6BBE}, {0x6BBF, 0x6BBF}, + {0x6BC0, 0x6BC0}, {0x6BC1, 0x6BC1}, {0x6BC2, 0x6BC2}, {0x6BC3, 0x6BC3}, {0x6BC4, 0x6BC4}, {0x6BC5, 0x6BC5}, {0x6BC6, 0x6BC6}, + {0x6BC7, 0x6BC7}, {0x6BC8, 0x6BC8}, {0x6BC9, 0x6BC9}, {0x6BCA, 0x6BCA}, {0x6BCB, 0x6BCB}, {0x6BCC, 0x6BCC}, {0x6BCD, 0x6BCD}, + {0x6BCE, 0x6BCE}, {0x6BCF, 0x6BCF}, {0x6BD0, 0x6BD0}, {0x6BD1, 0x6BD1}, {0x6BD2, 0x6BD2}, {0x6BD3, 0x6BD3}, {0x6BD4, 0x6BD4}, + {0x6BD5, 0x6BD5}, {0x6BD6, 0x6BD6}, {0x6BD7, 0x6BD7}, {0x6BD8, 0x6BD8}, {0x6BD9, 0x6BD9}, {0x6BDA, 0x6BDA}, {0x6BDB, 0x6BDB}, + {0x6BDC, 0x6BDC}, {0x6BDD, 0x6BDD}, {0x6BDE, 0x6BDE}, {0x6BDF, 0x6BDF}, {0x6BE0, 0x6BE0}, {0x6BE1, 0x6BE1}, {0x6BE2, 0x6BE2}, + {0x6BE3, 0x6BE3}, {0x6BE4, 0x6BE4}, {0x6BE5, 0x6BE5}, {0x6BE6, 0x6BE6}, {0x6BE7, 0x6BE7}, {0x6BE8, 0x6BE8}, {0x6BE9, 0x6BE9}, + {0x6BEA, 0x6BEA}, {0x6BEB, 0x6BEB}, {0x6BEC, 0x6BEC}, {0x6BED, 0x6BED}, {0x6BEE, 0x6BEE}, {0x6BEF, 0x6BEF}, {0x6BF0, 0x6BF0}, + {0x6BF1, 0x6BF1}, {0x6BF2, 0x6BF2}, {0x6BF3, 0x6BF3}, {0x6BF4, 0x6BF4}, {0x6BF5, 0x6BF5}, {0x6BF6, 0x6BF6}, {0x6BF7, 0x6BF7}, + {0x6BF8, 0x6BF8}, {0x6BF9, 0x6BF9}, {0x6BFA, 0x6BFA}, {0x6BFB, 0x6BFB}, {0x6BFC, 0x6BFC}, {0x6BFD, 0x6BFD}, {0x6BFE, 0x6BFE}, + {0x6BFF, 0x6BFF}, {0x6C00, 0x6C00}, {0x6C01, 0x6C01}, {0x6C02, 0x6C02}, {0x6C03, 0x6C03}, {0x6C04, 0x6C04}, {0x6C05, 0x6C05}, + {0x6C06, 0x6C06}, {0x6C07, 0x6C07}, {0x6C08, 0x6C08}, {0x6C09, 0x6C09}, {0x6C0A, 0x6C0A}, {0x6C0B, 0x6C0B}, {0x6C0C, 0x6C0C}, + {0x6C0D, 0x6C0D}, {0x6C0E, 0x6C0E}, {0x6C0F, 0x6C0F}, {0x6C10, 0x6C10}, {0x6C11, 0x6C11}, {0x6C12, 0x6C12}, {0x6C13, 0x6C13}, + {0x6C14, 0x6C14}, {0x6C15, 0x6C15}, {0x6C16, 0x6C16}, {0x6C17, 0x6C17}, {0x6C18, 0x6C18}, {0x6C19, 0x6C19}, {0x6C1A, 0x6C1A}, + {0x6C1B, 0x6C1B}, {0x6C1C, 0x6C1C}, {0x6C1D, 0x6C1D}, {0x6C1E, 0x6C1E}, {0x6C1F, 0x6C1F}, {0x6C20, 0x6C20}, {0x6C21, 0x6C21}, + {0x6C22, 0x6C22}, {0x6C23, 0x6C23}, {0x6C24, 0x6C24}, {0x6C25, 0x6C25}, {0x6C26, 0x6C26}, {0x6C27, 0x6C27}, {0x6C28, 0x6C28}, + {0x6C29, 0x6C29}, {0x6C2A, 0x6C2A}, {0x6C2B, 0x6C2B}, {0x6C2C, 0x6C2C}, {0x6C2D, 0x6C2D}, {0x6C2E, 0x6C2E}, {0x6C2F, 0x6C2F}, + {0x6C30, 0x6C30}, {0x6C31, 0x6C31}, {0x6C32, 0x6C32}, {0x6C33, 0x6C33}, {0x6C34, 0x6C34}, {0x6C35, 0x6C35}, {0x6C36, 0x6C36}, + {0x6C37, 0x6C37}, {0x6C38, 0x6C38}, {0x6C39, 0x6C39}, {0x6C3A, 0x6C3A}, {0x6C3B, 0x6C3B}, {0x6C3C, 0x6C3C}, {0x6C3D, 0x6C3D}, + {0x6C3E, 0x6C3E}, {0x6C3F, 0x6C3F}, {0x6C40, 0x6C40}, {0x6C41, 0x6C41}, {0x6C42, 0x6C42}, {0x6C43, 0x6C43}, {0x6C44, 0x6C44}, + {0x6C45, 0x6C45}, {0x6C46, 0x6C46}, {0x6C47, 0x6C47}, {0x6C48, 0x6C48}, {0x6C49, 0x6C49}, {0x6C4A, 0x6C4A}, {0x6C4B, 0x6C4B}, + {0x6C4C, 0x6C4C}, {0x6C4D, 0x6C4D}, {0x6C4E, 0x6C4E}, {0x6C4F, 0x6C4F}, {0x6C50, 0x6C50}, {0x6C51, 0x6C51}, {0x6C52, 0x6C52}, + {0x6C53, 0x6C53}, {0x6C54, 0x6C54}, {0x6C55, 0x6C55}, {0x6C56, 0x6C56}, {0x6C57, 0x6C57}, {0x6C58, 0x6C58}, {0x6C59, 0x6C59}, + {0x6C5A, 0x6C5A}, {0x6C5B, 0x6C5B}, {0x6C5C, 0x6C5C}, {0x6C5D, 0x6C5D}, {0x6C5E, 0x6C5E}, {0x6C5F, 0x6C5F}, {0x6C60, 0x6C60}, + {0x6C61, 0x6C61}, {0x6C62, 0x6C62}, {0x6C63, 0x6C63}, {0x6C64, 0x6C64}, {0x6C65, 0x6C65}, {0x6C66, 0x6C66}, {0x6C67, 0x6C67}, + {0x6C68, 0x6C68}, {0x6C69, 0x6C69}, {0x6C6A, 0x6C6A}, {0x6C6B, 0x6C6B}, {0x6C6C, 0x6C6C}, {0x6C6D, 0x6C6D}, {0x6C6E, 0x6C6E}, + {0x6C6F, 0x6C6F}, {0x6C70, 0x6C70}, {0x6C71, 0x6C71}, {0x6C72, 0x6C72}, {0x6C73, 0x6C73}, {0x6C74, 0x6C74}, {0x6C75, 0x6C75}, + {0x6C76, 0x6C76}, {0x6C77, 0x6C77}, {0x6C78, 0x6C78}, {0x6C79, 0x6C79}, {0x6C7A, 0x6C7A}, {0x6C7B, 0x6C7B}, {0x6C7C, 0x6C7C}, + {0x6C7D, 0x6C7D}, {0x6C7E, 0x6C7E}, {0x6C7F, 0x6C7F}, {0x6C80, 0x6C80}, {0x6C81, 0x6C81}, {0x6C82, 0x6C82}, {0x6C83, 0x6C83}, + {0x6C84, 0x6C84}, {0x6C85, 0x6C85}, {0x6C86, 0x6C86}, {0x6C87, 0x6C87}, {0x6C88, 0x6C88}, {0x6C89, 0x6C89}, {0x6C8A, 0x6C8A}, + {0x6C8B, 0x6C8B}, {0x6C8C, 0x6C8C}, {0x6C8D, 0x6C8D}, {0x6C8E, 0x6C8E}, {0x6C8F, 0x6C8F}, {0x6C90, 0x6C90}, {0x6C91, 0x6C91}, + {0x6C92, 0x6C92}, {0x6C93, 0x6C93}, {0x6C94, 0x6C94}, {0x6C95, 0x6C95}, {0x6C96, 0x6C96}, {0x6C97, 0x6C97}, {0x6C98, 0x6C98}, + {0x6C99, 0x6C99}, {0x6C9A, 0x6C9A}, {0x6C9B, 0x6C9B}, {0x6C9C, 0x6C9C}, {0x6C9D, 0x6C9D}, {0x6C9E, 0x6C9E}, {0x6C9F, 0x6C9F}, + {0x6CA0, 0x6CA0}, {0x6CA1, 0x6CA1}, {0x6CA2, 0x6CA2}, {0x6CA3, 0x6CA3}, {0x6CA4, 0x6CA4}, {0x6CA5, 0x6CA5}, {0x6CA6, 0x6CA6}, + {0x6CA7, 0x6CA7}, {0x6CA8, 0x6CA8}, {0x6CA9, 0x6CA9}, {0x6CAA, 0x6CAA}, {0x6CAB, 0x6CAB}, {0x6CAC, 0x6CAC}, {0x6CAD, 0x6CAD}, + {0x6CAE, 0x6CAE}, {0x6CAF, 0x6CAF}, {0x6CB0, 0x6CB0}, {0x6CB1, 0x6CB1}, {0x6CB2, 0x6CB2}, {0x6CB3, 0x6CB3}, {0x6CB4, 0x6CB4}, + {0x6CB5, 0x6CB5}, {0x6CB6, 0x6CB6}, {0x6CB7, 0x6CB7}, {0x6CB8, 0x6CB8}, {0x6CB9, 0x6CB9}, {0x6CBA, 0x6CBA}, {0x6CBB, 0x6CBB}, + {0x6CBC, 0x6CBC}, {0x6CBD, 0x6CBD}, {0x6CBE, 0x6CBE}, {0x6CBF, 0x6CBF}, {0x6CC0, 0x6CC0}, {0x6CC1, 0x6CC1}, {0x6CC2, 0x6CC2}, + {0x6CC3, 0x6CC3}, {0x6CC4, 0x6CC4}, {0x6CC5, 0x6CC5}, {0x6CC6, 0x6CC6}, {0x6CC7, 0x6CC7}, {0x6CC8, 0x6CC8}, {0x6CC9, 0x6CC9}, + {0x6CCA, 0x6CCA}, {0x6CCB, 0x6CCB}, {0x6CCC, 0x6CCC}, {0x6CCD, 0x6CCD}, {0x6CCE, 0x6CCE}, {0x6CCF, 0x6CCF}, {0x6CD0, 0x6CD0}, + {0x6CD1, 0x6CD1}, {0x6CD2, 0x6CD2}, {0x6CD3, 0x6CD3}, {0x6CD4, 0x6CD4}, {0x6CD5, 0x6CD5}, {0x6CD6, 0x6CD6}, {0x6CD7, 0x6CD7}, + {0x6CD8, 0x6CD8}, {0x6CD9, 0x6CD9}, {0x6CDA, 0x6CDA}, {0x6CDB, 0x6CDB}, {0x6CDC, 0x6CDC}, {0x6CDD, 0x6CDD}, {0x6CDE, 0x6CDE}, + {0x6CDF, 0x6CDF}, {0x6CE0, 0x6CE0}, {0x6CE1, 0x6CE1}, {0x6CE2, 0x6CE2}, {0x6CE3, 0x6CE3}, {0x6CE4, 0x6CE4}, {0x6CE5, 0x6CE5}, + {0x6CE6, 0x6CE6}, {0x6CE7, 0x6CE7}, {0x6CE8, 0x6CE8}, {0x6CE9, 0x6CE9}, {0x6CEA, 0x6CEA}, {0x6CEB, 0x6CEB}, {0x6CEC, 0x6CEC}, + {0x6CED, 0x6CED}, {0x6CEE, 0x6CEE}, {0x6CEF, 0x6CEF}, {0x6CF0, 0x6CF0}, {0x6CF1, 0x6CF1}, {0x6CF2, 0x6CF2}, {0x6CF3, 0x6CF3}, + {0x6CF4, 0x6CF4}, {0x6CF5, 0x6CF5}, {0x6CF6, 0x6CF6}, {0x6CF7, 0x6CF7}, {0x6CF8, 0x6CF8}, {0x6CF9, 0x6CF9}, {0x6CFA, 0x6CFA}, + {0x6CFB, 0x6CFB}, {0x6CFC, 0x6CFC}, {0x6CFD, 0x6CFD}, {0x6CFE, 0x6CFE}, {0x6CFF, 0x6CFF}, {0x6D00, 0x6D00}, {0x6D01, 0x6D01}, + {0x6D02, 0x6D02}, {0x6D03, 0x6D03}, {0x6D04, 0x6D04}, {0x6D05, 0x6D05}, {0x6D06, 0x6D06}, {0x6D07, 0x6D07}, {0x6D08, 0x6D08}, + {0x6D09, 0x6D09}, {0x6D0A, 0x6D0A}, {0x6D0B, 0x6D0B}, {0x6D0C, 0x6D0C}, {0x6D0D, 0x6D0D}, {0x6D0E, 0x6D0E}, {0x6D0F, 0x6D0F}, + {0x6D10, 0x6D10}, {0x6D11, 0x6D11}, {0x6D12, 0x6D12}, {0x6D13, 0x6D13}, {0x6D14, 0x6D14}, {0x6D15, 0x6D15}, {0x6D16, 0x6D16}, + {0x6D17, 0x6D17}, {0x6D18, 0x6D18}, {0x6D19, 0x6D19}, {0x6D1A, 0x6D1A}, {0x6D1B, 0x6D1B}, {0x6D1C, 0x6D1C}, {0x6D1D, 0x6D1D}, + {0x6D1E, 0x6D1E}, {0x6D1F, 0x6D1F}, {0x6D20, 0x6D20}, {0x6D21, 0x6D21}, {0x6D22, 0x6D22}, {0x6D23, 0x6D23}, {0x6D24, 0x6D24}, + {0x6D25, 0x6D25}, {0x6D26, 0x6D26}, {0x6D27, 0x6D27}, {0x6D28, 0x6D28}, {0x6D29, 0x6D29}, {0x6D2A, 0x6D2A}, {0x6D2B, 0x6D2B}, + {0x6D2C, 0x6D2C}, {0x6D2D, 0x6D2D}, {0x6D2E, 0x6D2E}, {0x6D2F, 0x6D2F}, {0x6D30, 0x6D30}, {0x6D31, 0x6D31}, {0x6D32, 0x6D32}, + {0x6D33, 0x6D33}, {0x6D34, 0x6D34}, {0x6D35, 0x6D35}, {0x6D36, 0x6D36}, {0x6D37, 0x6D37}, {0x6D38, 0x6D38}, {0x6D39, 0x6D39}, + {0x6D3A, 0x6D3A}, {0x6D3B, 0x6D3B}, {0x6D3C, 0x6D3C}, {0x6D3D, 0x6D3D}, {0x6D3E, 0x6D3E}, {0x6D3F, 0x6D3F}, {0x6D40, 0x6D40}, + {0x6D41, 0x6D41}, {0x6D42, 0x6D42}, {0x6D43, 0x6D43}, {0x6D44, 0x6D44}, {0x6D45, 0x6D45}, {0x6D46, 0x6D46}, {0x6D47, 0x6D47}, + {0x6D48, 0x6D48}, {0x6D49, 0x6D49}, {0x6D4A, 0x6D4A}, {0x6D4B, 0x6D4B}, {0x6D4C, 0x6D4C}, {0x6D4D, 0x6D4D}, {0x6D4E, 0x6D4E}, + {0x6D4F, 0x6D4F}, {0x6D50, 0x6D50}, {0x6D51, 0x6D51}, {0x6D52, 0x6D52}, {0x6D53, 0x6D53}, {0x6D54, 0x6D54}, {0x6D55, 0x6D55}, + {0x6D56, 0x6D56}, {0x6D57, 0x6D57}, {0x6D58, 0x6D58}, {0x6D59, 0x6D59}, {0x6D5A, 0x6D5A}, {0x6D5B, 0x6D5B}, {0x6D5C, 0x6D5C}, + {0x6D5D, 0x6D5D}, {0x6D5E, 0x6D5E}, {0x6D5F, 0x6D5F}, {0x6D60, 0x6D60}, {0x6D61, 0x6D61}, {0x6D62, 0x6D62}, {0x6D63, 0x6D63}, + {0x6D64, 0x6D64}, {0x6D65, 0x6D65}, {0x6D66, 0x6D66}, {0x6D67, 0x6D67}, {0x6D68, 0x6D68}, {0x6D69, 0x6D69}, {0x6D6A, 0x6D6A}, + {0x6D6B, 0x6D6B}, {0x6D6C, 0x6D6C}, {0x6D6D, 0x6D6D}, {0x6D6E, 0x6D6E}, {0x6D6F, 0x6D6F}, {0x6D70, 0x6D70}, {0x6D71, 0x6D71}, + {0x6D72, 0x6D72}, {0x6D73, 0x6D73}, {0x6D74, 0x6D74}, {0x6D75, 0x6D75}, {0x6D76, 0x6D76}, {0x6D77, 0x6D77}, {0x6D78, 0x6D78}, + {0x6D79, 0x6D79}, {0x6D7A, 0x6D7A}, {0x6D7B, 0x6D7B}, {0x6D7C, 0x6D7C}, {0x6D7D, 0x6D7D}, {0x6D7E, 0x6D7E}, {0x6D7F, 0x6D7F}, + {0x6D80, 0x6D80}, {0x6D81, 0x6D81}, {0x6D82, 0x6D82}, {0x6D83, 0x6D83}, {0x6D84, 0x6D84}, {0x6D85, 0x6D85}, {0x6D86, 0x6D86}, + {0x6D87, 0x6D87}, {0x6D88, 0x6D88}, {0x6D89, 0x6D89}, {0x6D8A, 0x6D8A}, {0x6D8B, 0x6D8B}, {0x6D8C, 0x6D8C}, {0x6D8D, 0x6D8D}, + {0x6D8E, 0x6D8E}, {0x6D8F, 0x6D8F}, {0x6D90, 0x6D90}, {0x6D91, 0x6D91}, {0x6D92, 0x6D92}, {0x6D93, 0x6D93}, {0x6D94, 0x6D94}, + {0x6D95, 0x6D95}, {0x6D96, 0x6D96}, {0x6D97, 0x6D97}, {0x6D98, 0x6D98}, {0x6D99, 0x6D99}, {0x6D9A, 0x6D9A}, {0x6D9B, 0x6D9B}, + {0x6D9C, 0x6D9C}, {0x6D9D, 0x6D9D}, {0x6D9E, 0x6D9E}, {0x6D9F, 0x6D9F}, {0x6DA0, 0x6DA0}, {0x6DA1, 0x6DA1}, {0x6DA2, 0x6DA2}, + {0x6DA3, 0x6DA3}, {0x6DA4, 0x6DA4}, {0x6DA5, 0x6DA5}, {0x6DA6, 0x6DA6}, {0x6DA7, 0x6DA7}, {0x6DA8, 0x6DA8}, {0x6DA9, 0x6DA9}, + {0x6DAA, 0x6DAA}, {0x6DAB, 0x6DAB}, {0x6DAC, 0x6DAC}, {0x6DAD, 0x6DAD}, {0x6DAE, 0x6DAE}, {0x6DAF, 0x6DAF}, {0x6DB0, 0x6DB0}, + {0x6DB1, 0x6DB1}, {0x6DB2, 0x6DB2}, {0x6DB3, 0x6DB3}, {0x6DB4, 0x6DB4}, {0x6DB5, 0x6DB5}, {0x6DB6, 0x6DB6}, {0x6DB7, 0x6DB7}, + {0x6DB8, 0x6DB8}, {0x6DB9, 0x6DB9}, {0x6DBA, 0x6DBA}, {0x6DBB, 0x6DBB}, {0x6DBC, 0x6DBC}, {0x6DBD, 0x6DBD}, {0x6DBE, 0x6DBE}, + {0x6DBF, 0x6DBF}, {0x6DC0, 0x6DC0}, {0x6DC1, 0x6DC1}, {0x6DC2, 0x6DC2}, {0x6DC3, 0x6DC3}, {0x6DC4, 0x6DC4}, {0x6DC5, 0x6DC5}, + {0x6DC6, 0x6DC6}, {0x6DC7, 0x6DC7}, {0x6DC8, 0x6DC8}, {0x6DC9, 0x6DC9}, {0x6DCA, 0x6DCA}, {0x6DCB, 0x6DCB}, {0x6DCC, 0x6DCC}, + {0x6DCD, 0x6DCD}, {0x6DCE, 0x6DCE}, {0x6DCF, 0x6DCF}, {0x6DD0, 0x6DD0}, {0x6DD1, 0x6DD1}, {0x6DD2, 0x6DD2}, {0x6DD3, 0x6DD3}, + {0x6DD4, 0x6DD4}, {0x6DD5, 0x6DD5}, {0x6DD6, 0x6DD6}, {0x6DD7, 0x6DD7}, {0x6DD8, 0x6DD8}, {0x6DD9, 0x6DD9}, {0x6DDA, 0x6DDA}, + {0x6DDB, 0x6DDB}, {0x6DDC, 0x6DDC}, {0x6DDD, 0x6DDD}, {0x6DDE, 0x6DDE}, {0x6DDF, 0x6DDF}, {0x6DE0, 0x6DE0}, {0x6DE1, 0x6DE1}, + {0x6DE2, 0x6DE2}, {0x6DE3, 0x6DE3}, {0x6DE4, 0x6DE4}, {0x6DE5, 0x6DE5}, {0x6DE6, 0x6DE6}, {0x6DE7, 0x6DE7}, {0x6DE8, 0x6DE8}, + {0x6DE9, 0x6DE9}, {0x6DEA, 0x6DEA}, {0x6DEB, 0x6DEB}, {0x6DEC, 0x6DEC}, {0x6DED, 0x6DED}, {0x6DEE, 0x6DEE}, {0x6DEF, 0x6DEF}, + {0x6DF0, 0x6DF0}, {0x6DF1, 0x6DF1}, {0x6DF2, 0x6DF2}, {0x6DF3, 0x6DF3}, {0x6DF4, 0x6DF4}, {0x6DF5, 0x6DF5}, {0x6DF6, 0x6DF6}, + {0x6DF7, 0x6DF7}, {0x6DF8, 0x6DF8}, {0x6DF9, 0x6DF9}, {0x6DFA, 0x6DFA}, {0x6DFB, 0x6DFB}, {0x6DFC, 0x6DFC}, {0x6DFD, 0x6DFD}, + {0x6DFE, 0x6DFE}, {0x6DFF, 0x6DFF}, {0x6E00, 0x6E00}, {0x6E01, 0x6E01}, {0x6E02, 0x6E02}, {0x6E03, 0x6E03}, {0x6E04, 0x6E04}, + {0x6E05, 0x6E05}, {0x6E06, 0x6E06}, {0x6E07, 0x6E07}, {0x6E08, 0x6E08}, {0x6E09, 0x6E09}, {0x6E0A, 0x6E0A}, {0x6E0B, 0x6E0B}, + {0x6E0C, 0x6E0C}, {0x6E0D, 0x6E0D}, {0x6E0E, 0x6E0E}, {0x6E0F, 0x6E0F}, {0x6E10, 0x6E10}, {0x6E11, 0x6E11}, {0x6E12, 0x6E12}, + {0x6E13, 0x6E13}, {0x6E14, 0x6E14}, {0x6E15, 0x6E15}, {0x6E16, 0x6E16}, {0x6E17, 0x6E17}, {0x6E18, 0x6E18}, {0x6E19, 0x6E19}, + {0x6E1A, 0x6E1A}, {0x6E1B, 0x6E1B}, {0x6E1C, 0x6E1C}, {0x6E1D, 0x6E1D}, {0x6E1E, 0x6E1E}, {0x6E1F, 0x6E1F}, {0x6E20, 0x6E20}, + {0x6E21, 0x6E21}, {0x6E22, 0x6E22}, {0x6E23, 0x6E23}, {0x6E24, 0x6E24}, {0x6E25, 0x6E25}, {0x6E26, 0x6E26}, {0x6E27, 0x6E27}, + {0x6E28, 0x6E28}, {0x6E29, 0x6E29}, {0x6E2A, 0x6E2A}, {0x6E2B, 0x6E2B}, {0x6E2C, 0x6E2C}, {0x6E2D, 0x6E2D}, {0x6E2E, 0x6E2E}, + {0x6E2F, 0x6E2F}, {0x6E30, 0x6E30}, {0x6E31, 0x6E31}, {0x6E32, 0x6E32}, {0x6E33, 0x6E33}, {0x6E34, 0x6E34}, {0x6E35, 0x6E35}, + {0x6E36, 0x6E36}, {0x6E37, 0x6E37}, {0x6E38, 0x6E38}, {0x6E39, 0x6E39}, {0x6E3A, 0x6E3A}, {0x6E3B, 0x6E3B}, {0x6E3C, 0x6E3C}, + {0x6E3D, 0x6E3D}, {0x6E3E, 0x6E3E}, {0x6E3F, 0x6E3F}, {0x6E40, 0x6E40}, {0x6E41, 0x6E41}, {0x6E42, 0x6E42}, {0x6E43, 0x6E43}, + {0x6E44, 0x6E44}, {0x6E45, 0x6E45}, {0x6E46, 0x6E46}, {0x6E47, 0x6E47}, {0x6E48, 0x6E48}, {0x6E49, 0x6E49}, {0x6E4A, 0x6E4A}, + {0x6E4B, 0x6E4B}, {0x6E4C, 0x6E4C}, {0x6E4D, 0x6E4D}, {0x6E4E, 0x6E4E}, {0x6E4F, 0x6E4F}, {0x6E50, 0x6E50}, {0x6E51, 0x6E51}, + {0x6E52, 0x6E52}, {0x6E53, 0x6E53}, {0x6E54, 0x6E54}, {0x6E55, 0x6E55}, {0x6E56, 0x6E56}, {0x6E57, 0x6E57}, {0x6E58, 0x6E58}, + {0x6E59, 0x6E59}, {0x6E5A, 0x6E5A}, {0x6E5B, 0x6E5B}, {0x6E5C, 0x6E5C}, {0x6E5D, 0x6E5D}, {0x6E5E, 0x6E5E}, {0x6E5F, 0x6E5F}, + {0x6E60, 0x6E60}, {0x6E61, 0x6E61}, {0x6E62, 0x6E62}, {0x6E63, 0x6E63}, {0x6E64, 0x6E64}, {0x6E65, 0x6E65}, {0x6E66, 0x6E66}, + {0x6E67, 0x6E67}, {0x6E68, 0x6E68}, {0x6E69, 0x6E69}, {0x6E6A, 0x6E6A}, {0x6E6B, 0x6E6B}, {0x6E6C, 0x6E6C}, {0x6E6D, 0x6E6D}, + {0x6E6E, 0x6E6E}, {0x6E6F, 0x6E6F}, {0x6E70, 0x6E70}, {0x6E71, 0x6E71}, {0x6E72, 0x6E72}, {0x6E73, 0x6E73}, {0x6E74, 0x6E74}, + {0x6E75, 0x6E75}, {0x6E76, 0x6E76}, {0x6E77, 0x6E77}, {0x6E78, 0x6E78}, {0x6E79, 0x6E79}, {0x6E7A, 0x6E7A}, {0x6E7B, 0x6E7B}, + {0x6E7C, 0x6E7C}, {0x6E7D, 0x6E7D}, {0x6E7E, 0x6E7E}, {0x6E7F, 0x6E7F}, {0x6E80, 0x6E80}, {0x6E81, 0x6E81}, {0x6E82, 0x6E82}, + {0x6E83, 0x6E83}, {0x6E84, 0x6E84}, {0x6E85, 0x6E85}, {0x6E86, 0x6E86}, {0x6E87, 0x6E87}, {0x6E88, 0x6E88}, {0x6E89, 0x6E89}, + {0x6E8A, 0x6E8A}, {0x6E8B, 0x6E8B}, {0x6E8C, 0x6E8C}, {0x6E8D, 0x6E8D}, {0x6E8E, 0x6E8E}, {0x6E8F, 0x6E8F}, {0x6E90, 0x6E90}, + {0x6E91, 0x6E91}, {0x6E92, 0x6E92}, {0x6E93, 0x6E93}, {0x6E94, 0x6E94}, {0x6E95, 0x6E95}, {0x6E96, 0x6E96}, {0x6E97, 0x6E97}, + {0x6E98, 0x6E98}, {0x6E99, 0x6E99}, {0x6E9A, 0x6E9A}, {0x6E9B, 0x6E9B}, {0x6E9C, 0x6E9C}, {0x6E9D, 0x6E9D}, {0x6E9E, 0x6E9E}, + {0x6E9F, 0x6E9F}, {0x6EA0, 0x6EA0}, {0x6EA1, 0x6EA1}, {0x6EA2, 0x6EA2}, {0x6EA3, 0x6EA3}, {0x6EA4, 0x6EA4}, {0x6EA5, 0x6EA5}, + {0x6EA6, 0x6EA6}, {0x6EA7, 0x6EA7}, {0x6EA8, 0x6EA8}, {0x6EA9, 0x6EA9}, {0x6EAA, 0x6EAA}, {0x6EAB, 0x6EAB}, {0x6EAC, 0x6EAC}, + {0x6EAD, 0x6EAD}, {0x6EAE, 0x6EAE}, {0x6EAF, 0x6EAF}, {0x6EB0, 0x6EB0}, {0x6EB1, 0x6EB1}, {0x6EB2, 0x6EB2}, {0x6EB3, 0x6EB3}, + {0x6EB4, 0x6EB4}, {0x6EB5, 0x6EB5}, {0x6EB6, 0x6EB6}, {0x6EB7, 0x6EB7}, {0x6EB8, 0x6EB8}, {0x6EB9, 0x6EB9}, {0x6EBA, 0x6EBA}, + {0x6EBB, 0x6EBB}, {0x6EBC, 0x6EBC}, {0x6EBD, 0x6EBD}, {0x6EBE, 0x6EBE}, {0x6EBF, 0x6EBF}, {0x6EC0, 0x6EC0}, {0x6EC1, 0x6EC1}, + {0x6EC2, 0x6EC2}, {0x6EC3, 0x6EC3}, {0x6EC4, 0x6EC4}, {0x6EC5, 0x6EC5}, {0x6EC6, 0x6EC6}, {0x6EC7, 0x6EC7}, {0x6EC8, 0x6EC8}, + {0x6EC9, 0x6EC9}, {0x6ECA, 0x6ECA}, {0x6ECB, 0x6ECB}, {0x6ECC, 0x6ECC}, {0x6ECD, 0x6ECD}, {0x6ECE, 0x6ECE}, {0x6ECF, 0x6ECF}, + {0x6ED0, 0x6ED0}, {0x6ED1, 0x6ED1}, {0x6ED2, 0x6ED2}, {0x6ED3, 0x6ED3}, {0x6ED4, 0x6ED4}, {0x6ED5, 0x6ED5}, {0x6ED6, 0x6ED6}, + {0x6ED7, 0x6ED7}, {0x6ED8, 0x6ED8}, {0x6ED9, 0x6ED9}, {0x6EDA, 0x6EDA}, {0x6EDB, 0x6EDB}, {0x6EDC, 0x6EDC}, {0x6EDD, 0x6EDD}, + {0x6EDE, 0x6EDE}, {0x6EDF, 0x6EDF}, {0x6EE0, 0x6EE0}, {0x6EE1, 0x6EE1}, {0x6EE2, 0x6EE2}, {0x6EE3, 0x6EE3}, {0x6EE4, 0x6EE4}, + {0x6EE5, 0x6EE5}, {0x6EE6, 0x6EE6}, {0x6EE7, 0x6EE7}, {0x6EE8, 0x6EE8}, {0x6EE9, 0x6EE9}, {0x6EEA, 0x6EEA}, {0x6EEB, 0x6EEB}, + {0x6EEC, 0x6EEC}, {0x6EED, 0x6EED}, {0x6EEE, 0x6EEE}, {0x6EEF, 0x6EEF}, {0x6EF0, 0x6EF0}, {0x6EF1, 0x6EF1}, {0x6EF2, 0x6EF2}, + {0x6EF3, 0x6EF3}, {0x6EF4, 0x6EF4}, {0x6EF5, 0x6EF5}, {0x6EF6, 0x6EF6}, {0x6EF7, 0x6EF7}, {0x6EF8, 0x6EF8}, {0x6EF9, 0x6EF9}, + {0x6EFA, 0x6EFA}, {0x6EFB, 0x6EFB}, {0x6EFC, 0x6EFC}, {0x6EFD, 0x6EFD}, {0x6EFE, 0x6EFE}, {0x6EFF, 0x6EFF}, {0x6F00, 0x6F00}, + {0x6F01, 0x6F01}, {0x6F02, 0x6F02}, {0x6F03, 0x6F03}, {0x6F04, 0x6F04}, {0x6F05, 0x6F05}, {0x6F06, 0x6F06}, {0x6F07, 0x6F07}, + {0x6F08, 0x6F08}, {0x6F09, 0x6F09}, {0x6F0A, 0x6F0A}, {0x6F0B, 0x6F0B}, {0x6F0C, 0x6F0C}, {0x6F0D, 0x6F0D}, {0x6F0E, 0x6F0E}, + {0x6F0F, 0x6F0F}, {0x6F10, 0x6F10}, {0x6F11, 0x6F11}, {0x6F12, 0x6F12}, {0x6F13, 0x6F13}, {0x6F14, 0x6F14}, {0x6F15, 0x6F15}, + {0x6F16, 0x6F16}, {0x6F17, 0x6F17}, {0x6F18, 0x6F18}, {0x6F19, 0x6F19}, {0x6F1A, 0x6F1A}, {0x6F1B, 0x6F1B}, {0x6F1C, 0x6F1C}, + {0x6F1D, 0x6F1D}, {0x6F1E, 0x6F1E}, {0x6F1F, 0x6F1F}, {0x6F20, 0x6F20}, {0x6F21, 0x6F21}, {0x6F22, 0x6F22}, {0x6F23, 0x6F23}, + {0x6F24, 0x6F24}, {0x6F25, 0x6F25}, {0x6F26, 0x6F26}, {0x6F27, 0x6F27}, {0x6F28, 0x6F28}, {0x6F29, 0x6F29}, {0x6F2A, 0x6F2A}, + {0x6F2B, 0x6F2B}, {0x6F2C, 0x6F2C}, {0x6F2D, 0x6F2D}, {0x6F2E, 0x6F2E}, {0x6F2F, 0x6F2F}, {0x6F30, 0x6F30}, {0x6F31, 0x6F31}, + {0x6F32, 0x6F32}, {0x6F33, 0x6F33}, {0x6F34, 0x6F34}, {0x6F35, 0x6F35}, {0x6F36, 0x6F36}, {0x6F37, 0x6F37}, {0x6F38, 0x6F38}, + {0x6F39, 0x6F39}, {0x6F3A, 0x6F3A}, {0x6F3B, 0x6F3B}, {0x6F3C, 0x6F3C}, {0x6F3D, 0x6F3D}, {0x6F3E, 0x6F3E}, {0x6F3F, 0x6F3F}, + {0x6F40, 0x6F40}, {0x6F41, 0x6F41}, {0x6F42, 0x6F42}, {0x6F43, 0x6F43}, {0x6F44, 0x6F44}, {0x6F45, 0x6F45}, {0x6F46, 0x6F46}, + {0x6F47, 0x6F47}, {0x6F48, 0x6F48}, {0x6F49, 0x6F49}, {0x6F4A, 0x6F4A}, {0x6F4B, 0x6F4B}, {0x6F4C, 0x6F4C}, {0x6F4D, 0x6F4D}, + {0x6F4E, 0x6F4E}, {0x6F4F, 0x6F4F}, {0x6F50, 0x6F50}, {0x6F51, 0x6F51}, {0x6F52, 0x6F52}, {0x6F53, 0x6F53}, {0x6F54, 0x6F54}, + {0x6F55, 0x6F55}, {0x6F56, 0x6F56}, {0x6F57, 0x6F57}, {0x6F58, 0x6F58}, {0x6F59, 0x6F59}, {0x6F5A, 0x6F5A}, {0x6F5B, 0x6F5B}, + {0x6F5C, 0x6F5C}, {0x6F5D, 0x6F5D}, {0x6F5E, 0x6F5E}, {0x6F5F, 0x6F5F}, {0x6F60, 0x6F60}, {0x6F61, 0x6F61}, {0x6F62, 0x6F62}, + {0x6F63, 0x6F63}, {0x6F64, 0x6F64}, {0x6F65, 0x6F65}, {0x6F66, 0x6F66}, {0x6F67, 0x6F67}, {0x6F68, 0x6F68}, {0x6F69, 0x6F69}, + {0x6F6A, 0x6F6A}, {0x6F6B, 0x6F6B}, {0x6F6C, 0x6F6C}, {0x6F6D, 0x6F6D}, {0x6F6E, 0x6F6E}, {0x6F6F, 0x6F6F}, {0x6F70, 0x6F70}, + {0x6F71, 0x6F71}, {0x6F72, 0x6F72}, {0x6F73, 0x6F73}, {0x6F74, 0x6F74}, {0x6F75, 0x6F75}, {0x6F76, 0x6F76}, {0x6F77, 0x6F77}, + {0x6F78, 0x6F78}, {0x6F79, 0x6F79}, {0x6F7A, 0x6F7A}, {0x6F7B, 0x6F7B}, {0x6F7C, 0x6F7C}, {0x6F7D, 0x6F7D}, {0x6F7E, 0x6F7E}, + {0x6F7F, 0x6F7F}, {0x6F80, 0x6F80}, {0x6F81, 0x6F81}, {0x6F82, 0x6F82}, {0x6F83, 0x6F83}, {0x6F84, 0x6F84}, {0x6F85, 0x6F85}, + {0x6F86, 0x6F86}, {0x6F87, 0x6F87}, {0x6F88, 0x6F88}, {0x6F89, 0x6F89}, {0x6F8A, 0x6F8A}, {0x6F8B, 0x6F8B}, {0x6F8C, 0x6F8C}, + {0x6F8D, 0x6F8D}, {0x6F8E, 0x6F8E}, {0x6F8F, 0x6F8F}, {0x6F90, 0x6F90}, {0x6F91, 0x6F91}, {0x6F92, 0x6F92}, {0x6F93, 0x6F93}, + {0x6F94, 0x6F94}, {0x6F95, 0x6F95}, {0x6F96, 0x6F96}, {0x6F97, 0x6F97}, {0x6F98, 0x6F98}, {0x6F99, 0x6F99}, {0x6F9A, 0x6F9A}, + {0x6F9B, 0x6F9B}, {0x6F9C, 0x6F9C}, {0x6F9D, 0x6F9D}, {0x6F9E, 0x6F9E}, {0x6F9F, 0x6F9F}, {0x6FA0, 0x6FA0}, {0x6FA1, 0x6FA1}, + {0x6FA2, 0x6FA2}, {0x6FA3, 0x6FA3}, {0x6FA4, 0x6FA4}, {0x6FA5, 0x6FA5}, {0x6FA6, 0x6FA6}, {0x6FA7, 0x6FA7}, {0x6FA8, 0x6FA8}, + {0x6FA9, 0x6FA9}, {0x6FAA, 0x6FAA}, {0x6FAB, 0x6FAB}, {0x6FAC, 0x6FAC}, {0x6FAD, 0x6FAD}, {0x6FAE, 0x6FAE}, {0x6FAF, 0x6FAF}, + {0x6FB0, 0x6FB0}, {0x6FB1, 0x6FB1}, {0x6FB2, 0x6FB2}, {0x6FB3, 0x6FB3}, {0x6FB4, 0x6FB4}, {0x6FB5, 0x6FB5}, {0x6FB6, 0x6FB6}, + {0x6FB7, 0x6FB7}, {0x6FB8, 0x6FB8}, {0x6FB9, 0x6FB9}, {0x6FBA, 0x6FBA}, {0x6FBB, 0x6FBB}, {0x6FBC, 0x6FBC}, {0x6FBD, 0x6FBD}, + {0x6FBE, 0x6FBE}, {0x6FBF, 0x6FBF}, {0x6FC0, 0x6FC0}, {0x6FC1, 0x6FC1}, {0x6FC2, 0x6FC2}, {0x6FC3, 0x6FC3}, {0x6FC4, 0x6FC4}, + {0x6FC5, 0x6FC5}, {0x6FC6, 0x6FC6}, {0x6FC7, 0x6FC7}, {0x6FC8, 0x6FC8}, {0x6FC9, 0x6FC9}, {0x6FCA, 0x6FCA}, {0x6FCB, 0x6FCB}, + {0x6FCC, 0x6FCC}, {0x6FCD, 0x6FCD}, {0x6FCE, 0x6FCE}, {0x6FCF, 0x6FCF}, {0x6FD0, 0x6FD0}, {0x6FD1, 0x6FD1}, {0x6FD2, 0x6FD2}, + {0x6FD3, 0x6FD3}, {0x6FD4, 0x6FD4}, {0x6FD5, 0x6FD5}, {0x6FD6, 0x6FD6}, {0x6FD7, 0x6FD7}, {0x6FD8, 0x6FD8}, {0x6FD9, 0x6FD9}, + {0x6FDA, 0x6FDA}, {0x6FDB, 0x6FDB}, {0x6FDC, 0x6FDC}, {0x6FDD, 0x6FDD}, {0x6FDE, 0x6FDE}, {0x6FDF, 0x6FDF}, {0x6FE0, 0x6FE0}, + {0x6FE1, 0x6FE1}, {0x6FE2, 0x6FE2}, {0x6FE3, 0x6FE3}, {0x6FE4, 0x6FE4}, {0x6FE5, 0x6FE5}, {0x6FE6, 0x6FE6}, {0x6FE7, 0x6FE7}, + {0x6FE8, 0x6FE8}, {0x6FE9, 0x6FE9}, {0x6FEA, 0x6FEA}, {0x6FEB, 0x6FEB}, {0x6FEC, 0x6FEC}, {0x6FED, 0x6FED}, {0x6FEE, 0x6FEE}, + {0x6FEF, 0x6FEF}, {0x6FF0, 0x6FF0}, {0x6FF1, 0x6FF1}, {0x6FF2, 0x6FF2}, {0x6FF3, 0x6FF3}, {0x6FF4, 0x6FF4}, {0x6FF5, 0x6FF5}, + {0x6FF6, 0x6FF6}, {0x6FF7, 0x6FF7}, {0x6FF8, 0x6FF8}, {0x6FF9, 0x6FF9}, {0x6FFA, 0x6FFA}, {0x6FFB, 0x6FFB}, {0x6FFC, 0x6FFC}, + {0x6FFD, 0x6FFD}, {0x6FFE, 0x6FFE}, {0x6FFF, 0x6FFF}, {0x7000, 0x7000}, {0x7001, 0x7001}, {0x7002, 0x7002}, {0x7003, 0x7003}, + {0x7004, 0x7004}, {0x7005, 0x7005}, {0x7006, 0x7006}, {0x7007, 0x7007}, {0x7008, 0x7008}, {0x7009, 0x7009}, {0x700A, 0x700A}, + {0x700B, 0x700B}, {0x700C, 0x700C}, {0x700D, 0x700D}, {0x700E, 0x700E}, {0x700F, 0x700F}, {0x7010, 0x7010}, {0x7011, 0x7011}, + {0x7012, 0x7012}, {0x7013, 0x7013}, {0x7014, 0x7014}, {0x7015, 0x7015}, {0x7016, 0x7016}, {0x7017, 0x7017}, {0x7018, 0x7018}, + {0x7019, 0x7019}, {0x701A, 0x701A}, {0x701B, 0x701B}, {0x701C, 0x701C}, {0x701D, 0x701D}, {0x701E, 0x701E}, {0x701F, 0x701F}, + {0x7020, 0x7020}, {0x7021, 0x7021}, {0x7022, 0x7022}, {0x7023, 0x7023}, {0x7024, 0x7024}, {0x7025, 0x7025}, {0x7026, 0x7026}, + {0x7027, 0x7027}, {0x7028, 0x7028}, {0x7029, 0x7029}, {0x702A, 0x702A}, {0x702B, 0x702B}, {0x702C, 0x702C}, {0x702D, 0x702D}, + {0x702E, 0x702E}, {0x702F, 0x702F}, {0x7030, 0x7030}, {0x7031, 0x7031}, {0x7032, 0x7032}, {0x7033, 0x7033}, {0x7034, 0x7034}, + {0x7035, 0x7035}, {0x7036, 0x7036}, {0x7037, 0x7037}, {0x7038, 0x7038}, {0x7039, 0x7039}, {0x703A, 0x703A}, {0x703B, 0x703B}, + {0x703C, 0x703C}, {0x703D, 0x703D}, {0x703E, 0x703E}, {0x703F, 0x703F}, {0x7040, 0x7040}, {0x7041, 0x7041}, {0x7042, 0x7042}, + {0x7043, 0x7043}, {0x7044, 0x7044}, {0x7045, 0x7045}, {0x7046, 0x7046}, {0x7047, 0x7047}, {0x7048, 0x7048}, {0x7049, 0x7049}, + {0x704A, 0x704A}, {0x704B, 0x704B}, {0x704C, 0x704C}, {0x704D, 0x704D}, {0x704E, 0x704E}, {0x704F, 0x704F}, {0x7050, 0x7050}, + {0x7051, 0x7051}, {0x7052, 0x7052}, {0x7053, 0x7053}, {0x7054, 0x7054}, {0x7055, 0x7055}, {0x7056, 0x7056}, {0x7057, 0x7057}, + {0x7058, 0x7058}, {0x7059, 0x7059}, {0x705A, 0x705A}, {0x705B, 0x705B}, {0x705C, 0x705C}, {0x705D, 0x705D}, {0x705E, 0x705E}, + {0x705F, 0x705F}, {0x7060, 0x7060}, {0x7061, 0x7061}, {0x7062, 0x7062}, {0x7063, 0x7063}, {0x7064, 0x7064}, {0x7065, 0x7065}, + {0x7066, 0x7066}, {0x7067, 0x7067}, {0x7068, 0x7068}, {0x7069, 0x7069}, {0x706A, 0x706A}, {0x706B, 0x706B}, {0x706C, 0x706C}, + {0x706D, 0x706D}, {0x706E, 0x706E}, {0x706F, 0x706F}, {0x7070, 0x7070}, {0x7071, 0x7071}, {0x7072, 0x7072}, {0x7073, 0x7073}, + {0x7074, 0x7074}, {0x7075, 0x7075}, {0x7076, 0x7076}, {0x7077, 0x7077}, {0x7078, 0x7078}, {0x7079, 0x7079}, {0x707A, 0x707A}, + {0x707B, 0x707B}, {0x707C, 0x707C}, {0x707D, 0x707D}, {0x707E, 0x707E}, {0x707F, 0x707F}, {0x7080, 0x7080}, {0x7081, 0x7081}, + {0x7082, 0x7082}, {0x7083, 0x7083}, {0x7084, 0x7084}, {0x7085, 0x7085}, {0x7086, 0x7086}, {0x7087, 0x7087}, {0x7088, 0x7088}, + {0x7089, 0x7089}, {0x708A, 0x708A}, {0x708B, 0x708B}, {0x708C, 0x708C}, {0x708D, 0x708D}, {0x708E, 0x708E}, {0x708F, 0x708F}, + {0x7090, 0x7090}, {0x7091, 0x7091}, {0x7092, 0x7092}, {0x7093, 0x7093}, {0x7094, 0x7094}, {0x7095, 0x7095}, {0x7096, 0x7096}, + {0x7097, 0x7097}, {0x7098, 0x7098}, {0x7099, 0x7099}, {0x709A, 0x709A}, {0x709B, 0x709B}, {0x709C, 0x709C}, {0x709D, 0x709D}, + {0x709E, 0x709E}, {0x709F, 0x709F}, {0x70A0, 0x70A0}, {0x70A1, 0x70A1}, {0x70A2, 0x70A2}, {0x70A3, 0x70A3}, {0x70A4, 0x70A4}, + {0x70A5, 0x70A5}, {0x70A6, 0x70A6}, {0x70A7, 0x70A7}, {0x70A8, 0x70A8}, {0x70A9, 0x70A9}, {0x70AA, 0x70AA}, {0x70AB, 0x70AB}, + {0x70AC, 0x70AC}, {0x70AD, 0x70AD}, {0x70AE, 0x70AE}, {0x70AF, 0x70AF}, {0x70B0, 0x70B0}, {0x70B1, 0x70B1}, {0x70B2, 0x70B2}, + {0x70B3, 0x70B3}, {0x70B4, 0x70B4}, {0x70B5, 0x70B5}, {0x70B6, 0x70B6}, {0x70B7, 0x70B7}, {0x70B8, 0x70B8}, {0x70B9, 0x70B9}, + {0x70BA, 0x70BA}, {0x70BB, 0x70BB}, {0x70BC, 0x70BC}, {0x70BD, 0x70BD}, {0x70BE, 0x70BE}, {0x70BF, 0x70BF}, {0x70C0, 0x70C0}, + {0x70C1, 0x70C1}, {0x70C2, 0x70C2}, {0x70C3, 0x70C3}, {0x70C4, 0x70C4}, {0x70C5, 0x70C5}, {0x70C6, 0x70C6}, {0x70C7, 0x70C7}, + {0x70C8, 0x70C8}, {0x70C9, 0x70C9}, {0x70CA, 0x70CA}, {0x70CB, 0x70CB}, {0x70CC, 0x70CC}, {0x70CD, 0x70CD}, {0x70CE, 0x70CE}, + {0x70CF, 0x70CF}, {0x70D0, 0x70D0}, {0x70D1, 0x70D1}, {0x70D2, 0x70D2}, {0x70D3, 0x70D3}, {0x70D4, 0x70D4}, {0x70D5, 0x70D5}, + {0x70D6, 0x70D6}, {0x70D7, 0x70D7}, {0x70D8, 0x70D8}, {0x70D9, 0x70D9}, {0x70DA, 0x70DA}, {0x70DB, 0x70DB}, {0x70DC, 0x70DC}, + {0x70DD, 0x70DD}, {0x70DE, 0x70DE}, {0x70DF, 0x70DF}, {0x70E0, 0x70E0}, {0x70E1, 0x70E1}, {0x70E2, 0x70E2}, {0x70E3, 0x70E3}, + {0x70E4, 0x70E4}, {0x70E5, 0x70E5}, {0x70E6, 0x70E6}, {0x70E7, 0x70E7}, {0x70E8, 0x70E8}, {0x70E9, 0x70E9}, {0x70EA, 0x70EA}, + {0x70EB, 0x70EB}, {0x70EC, 0x70EC}, {0x70ED, 0x70ED}, {0x70EE, 0x70EE}, {0x70EF, 0x70EF}, {0x70F0, 0x70F0}, {0x70F1, 0x70F1}, + {0x70F2, 0x70F2}, {0x70F3, 0x70F3}, {0x70F4, 0x70F4}, {0x70F5, 0x70F5}, {0x70F6, 0x70F6}, {0x70F7, 0x70F7}, {0x70F8, 0x70F8}, + {0x70F9, 0x70F9}, {0x70FA, 0x70FA}, {0x70FB, 0x70FB}, {0x70FC, 0x70FC}, {0x70FD, 0x70FD}, {0x70FE, 0x70FE}, {0x70FF, 0x70FF}, + {0x7100, 0x7100}, {0x7101, 0x7101}, {0x7102, 0x7102}, {0x7103, 0x7103}, {0x7104, 0x7104}, {0x7105, 0x7105}, {0x7106, 0x7106}, + {0x7107, 0x7107}, {0x7108, 0x7108}, {0x7109, 0x7109}, {0x710A, 0x710A}, {0x710B, 0x710B}, {0x710C, 0x710C}, {0x710D, 0x710D}, + {0x710E, 0x710E}, {0x710F, 0x710F}, {0x7110, 0x7110}, {0x7111, 0x7111}, {0x7112, 0x7112}, {0x7113, 0x7113}, {0x7114, 0x7114}, + {0x7115, 0x7115}, {0x7116, 0x7116}, {0x7117, 0x7117}, {0x7118, 0x7118}, {0x7119, 0x7119}, {0x711A, 0x711A}, {0x711B, 0x711B}, + {0x711C, 0x711C}, {0x711D, 0x711D}, {0x711E, 0x711E}, {0x711F, 0x711F}, {0x7120, 0x7120}, {0x7121, 0x7121}, {0x7122, 0x7122}, + {0x7123, 0x7123}, {0x7124, 0x7124}, {0x7125, 0x7125}, {0x7126, 0x7126}, {0x7127, 0x7127}, {0x7128, 0x7128}, {0x7129, 0x7129}, + {0x712A, 0x712A}, {0x712B, 0x712B}, {0x712C, 0x712C}, {0x712D, 0x712D}, {0x712E, 0x712E}, {0x712F, 0x712F}, {0x7130, 0x7130}, + {0x7131, 0x7131}, {0x7132, 0x7132}, {0x7133, 0x7133}, {0x7134, 0x7134}, {0x7135, 0x7135}, {0x7136, 0x7136}, {0x7137, 0x7137}, + {0x7138, 0x7138}, {0x7139, 0x7139}, {0x713A, 0x713A}, {0x713B, 0x713B}, {0x713C, 0x713C}, {0x713D, 0x713D}, {0x713E, 0x713E}, + {0x713F, 0x713F}, {0x7140, 0x7140}, {0x7141, 0x7141}, {0x7142, 0x7142}, {0x7143, 0x7143}, {0x7144, 0x7144}, {0x7145, 0x7145}, + {0x7146, 0x7146}, {0x7147, 0x7147}, {0x7148, 0x7148}, {0x7149, 0x7149}, {0x714A, 0x714A}, {0x714B, 0x714B}, {0x714C, 0x714C}, + {0x714D, 0x714D}, {0x714E, 0x714E}, {0x714F, 0x714F}, {0x7150, 0x7150}, {0x7151, 0x7151}, {0x7152, 0x7152}, {0x7153, 0x7153}, + {0x7154, 0x7154}, {0x7155, 0x7155}, {0x7156, 0x7156}, {0x7157, 0x7157}, {0x7158, 0x7158}, {0x7159, 0x7159}, {0x715A, 0x715A}, + {0x715B, 0x715B}, {0x715C, 0x715C}, {0x715D, 0x715D}, {0x715E, 0x715E}, {0x715F, 0x715F}, {0x7160, 0x7160}, {0x7161, 0x7161}, + {0x7162, 0x7162}, {0x7163, 0x7163}, {0x7164, 0x7164}, {0x7165, 0x7165}, {0x7166, 0x7166}, {0x7167, 0x7167}, {0x7168, 0x7168}, + {0x7169, 0x7169}, {0x716A, 0x716A}, {0x716B, 0x716B}, {0x716C, 0x716C}, {0x716D, 0x716D}, {0x716E, 0x716E}, {0x716F, 0x716F}, + {0x7170, 0x7170}, {0x7171, 0x7171}, {0x7172, 0x7172}, {0x7173, 0x7173}, {0x7174, 0x7174}, {0x7175, 0x7175}, {0x7176, 0x7176}, + {0x7177, 0x7177}, {0x7178, 0x7178}, {0x7179, 0x7179}, {0x717A, 0x717A}, {0x717B, 0x717B}, {0x717C, 0x717C}, {0x717D, 0x717D}, + {0x717E, 0x717E}, {0x717F, 0x717F}, {0x7180, 0x7180}, {0x7181, 0x7181}, {0x7182, 0x7182}, {0x7183, 0x7183}, {0x7184, 0x7184}, + {0x7185, 0x7185}, {0x7186, 0x7186}, {0x7187, 0x7187}, {0x7188, 0x7188}, {0x7189, 0x7189}, {0x718A, 0x718A}, {0x718B, 0x718B}, + {0x718C, 0x718C}, {0x718D, 0x718D}, {0x718E, 0x718E}, {0x718F, 0x718F}, {0x7190, 0x7190}, {0x7191, 0x7191}, {0x7192, 0x7192}, + {0x7193, 0x7193}, {0x7194, 0x7194}, {0x7195, 0x7195}, {0x7196, 0x7196}, {0x7197, 0x7197}, {0x7198, 0x7198}, {0x7199, 0x7199}, + {0x719A, 0x719A}, {0x719B, 0x719B}, {0x719C, 0x719C}, {0x719D, 0x719D}, {0x719E, 0x719E}, {0x719F, 0x719F}, {0x71A0, 0x71A0}, + {0x71A1, 0x71A1}, {0x71A2, 0x71A2}, {0x71A3, 0x71A3}, {0x71A4, 0x71A4}, {0x71A5, 0x71A5}, {0x71A6, 0x71A6}, {0x71A7, 0x71A7}, + {0x71A8, 0x71A8}, {0x71A9, 0x71A9}, {0x71AA, 0x71AA}, {0x71AB, 0x71AB}, {0x71AC, 0x71AC}, {0x71AD, 0x71AD}, {0x71AE, 0x71AE}, + {0x71AF, 0x71AF}, {0x71B0, 0x71B0}, {0x71B1, 0x71B1}, {0x71B2, 0x71B2}, {0x71B3, 0x71B3}, {0x71B4, 0x71B4}, {0x71B5, 0x71B5}, + {0x71B6, 0x71B6}, {0x71B7, 0x71B7}, {0x71B8, 0x71B8}, {0x71B9, 0x71B9}, {0x71BA, 0x71BA}, {0x71BB, 0x71BB}, {0x71BC, 0x71BC}, + {0x71BD, 0x71BD}, {0x71BE, 0x71BE}, {0x71BF, 0x71BF}, {0x71C0, 0x71C0}, {0x71C1, 0x71C1}, {0x71C2, 0x71C2}, {0x71C3, 0x71C3}, + {0x71C4, 0x71C4}, {0x71C5, 0x71C5}, {0x71C6, 0x71C6}, {0x71C7, 0x71C7}, {0x71C8, 0x71C8}, {0x71C9, 0x71C9}, {0x71CA, 0x71CA}, + {0x71CB, 0x71CB}, {0x71CC, 0x71CC}, {0x71CD, 0x71CD}, {0x71CE, 0x71CE}, {0x71CF, 0x71CF}, {0x71D0, 0x71D0}, {0x71D1, 0x71D1}, + {0x71D2, 0x71D2}, {0x71D3, 0x71D3}, {0x71D4, 0x71D4}, {0x71D5, 0x71D5}, {0x71D6, 0x71D6}, {0x71D7, 0x71D7}, {0x71D8, 0x71D8}, + {0x71D9, 0x71D9}, {0x71DA, 0x71DA}, {0x71DB, 0x71DB}, {0x71DC, 0x71DC}, {0x71DD, 0x71DD}, {0x71DE, 0x71DE}, {0x71DF, 0x71DF}, + {0x71E0, 0x71E0}, {0x71E1, 0x71E1}, {0x71E2, 0x71E2}, {0x71E3, 0x71E3}, {0x71E4, 0x71E4}, {0x71E5, 0x71E5}, {0x71E6, 0x71E6}, + {0x71E7, 0x71E7}, {0x71E8, 0x71E8}, {0x71E9, 0x71E9}, {0x71EA, 0x71EA}, {0x71EB, 0x71EB}, {0x71EC, 0x71EC}, {0x71ED, 0x71ED}, + {0x71EE, 0x71EE}, {0x71EF, 0x71EF}, {0x71F0, 0x71F0}, {0x71F1, 0x71F1}, {0x71F2, 0x71F2}, {0x71F3, 0x71F3}, {0x71F4, 0x71F4}, + {0x71F5, 0x71F5}, {0x71F6, 0x71F6}, {0x71F7, 0x71F7}, {0x71F8, 0x71F8}, {0x71F9, 0x71F9}, {0x71FA, 0x71FA}, {0x71FB, 0x71FB}, + {0x71FC, 0x71FC}, {0x71FD, 0x71FD}, {0x71FE, 0x71FE}, {0x71FF, 0x71FF}, {0x7200, 0x7200}, {0x7201, 0x7201}, {0x7202, 0x7202}, + {0x7203, 0x7203}, {0x7204, 0x7204}, {0x7205, 0x7205}, {0x7206, 0x7206}, {0x7207, 0x7207}, {0x7208, 0x7208}, {0x7209, 0x7209}, + {0x720A, 0x720A}, {0x720B, 0x720B}, {0x720C, 0x720C}, {0x720D, 0x720D}, {0x720E, 0x720E}, {0x720F, 0x720F}, {0x7210, 0x7210}, + {0x7211, 0x7211}, {0x7212, 0x7212}, {0x7213, 0x7213}, {0x7214, 0x7214}, {0x7215, 0x7215}, {0x7216, 0x7216}, {0x7217, 0x7217}, + {0x7218, 0x7218}, {0x7219, 0x7219}, {0x721A, 0x721A}, {0x721B, 0x721B}, {0x721C, 0x721C}, {0x721D, 0x721D}, {0x721E, 0x721E}, + {0x721F, 0x721F}, {0x7220, 0x7220}, {0x7221, 0x7221}, {0x7222, 0x7222}, {0x7223, 0x7223}, {0x7224, 0x7224}, {0x7225, 0x7225}, + {0x7226, 0x7226}, {0x7227, 0x7227}, {0x7228, 0x7228}, {0x7229, 0x7229}, {0x722A, 0x722A}, {0x722B, 0x722B}, {0x722C, 0x722C}, + {0x722D, 0x722D}, {0x722E, 0x722E}, {0x722F, 0x722F}, {0x7230, 0x7230}, {0x7231, 0x7231}, {0x7232, 0x7232}, {0x7233, 0x7233}, + {0x7234, 0x7234}, {0x7235, 0x7235}, {0x7236, 0x7236}, {0x7237, 0x7237}, {0x7238, 0x7238}, {0x7239, 0x7239}, {0x723A, 0x723A}, + {0x723B, 0x723B}, {0x723C, 0x723C}, {0x723D, 0x723D}, {0x723E, 0x723E}, {0x723F, 0x723F}, {0x7240, 0x7240}, {0x7241, 0x7241}, + {0x7242, 0x7242}, {0x7243, 0x7243}, {0x7244, 0x7244}, {0x7245, 0x7245}, {0x7246, 0x7246}, {0x7247, 0x7247}, {0x7248, 0x7248}, + {0x7249, 0x7249}, {0x724A, 0x724A}, {0x724B, 0x724B}, {0x724C, 0x724C}, {0x724D, 0x724D}, {0x724E, 0x724E}, {0x724F, 0x724F}, + {0x7250, 0x7250}, {0x7251, 0x7251}, {0x7252, 0x7252}, {0x7253, 0x7253}, {0x7254, 0x7254}, {0x7255, 0x7255}, {0x7256, 0x7256}, + {0x7257, 0x7257}, {0x7258, 0x7258}, {0x7259, 0x7259}, {0x725A, 0x725A}, {0x725B, 0x725B}, {0x725C, 0x725C}, {0x725D, 0x725D}, + {0x725E, 0x725E}, {0x725F, 0x725F}, {0x7260, 0x7260}, {0x7261, 0x7261}, {0x7262, 0x7262}, {0x7263, 0x7263}, {0x7264, 0x7264}, + {0x7265, 0x7265}, {0x7266, 0x7266}, {0x7267, 0x7267}, {0x7268, 0x7268}, {0x7269, 0x7269}, {0x726A, 0x726A}, {0x726B, 0x726B}, + {0x726C, 0x726C}, {0x726D, 0x726D}, {0x726E, 0x726E}, {0x726F, 0x726F}, {0x7270, 0x7270}, {0x7271, 0x7271}, {0x7272, 0x7272}, + {0x7273, 0x7273}, {0x7274, 0x7274}, {0x7275, 0x7275}, {0x7276, 0x7276}, {0x7277, 0x7277}, {0x7278, 0x7278}, {0x7279, 0x7279}, + {0x727A, 0x727A}, {0x727B, 0x727B}, {0x727C, 0x727C}, {0x727D, 0x727D}, {0x727E, 0x727E}, {0x727F, 0x727F}, {0x7280, 0x7280}, + {0x7281, 0x7281}, {0x7282, 0x7282}, {0x7283, 0x7283}, {0x7284, 0x7284}, {0x7285, 0x7285}, {0x7286, 0x7286}, {0x7287, 0x7287}, + {0x7288, 0x7288}, {0x7289, 0x7289}, {0x728A, 0x728A}, {0x728B, 0x728B}, {0x728C, 0x728C}, {0x728D, 0x728D}, {0x728E, 0x728E}, + {0x728F, 0x728F}, {0x7290, 0x7290}, {0x7291, 0x7291}, {0x7292, 0x7292}, {0x7293, 0x7293}, {0x7294, 0x7294}, {0x7295, 0x7295}, + {0x7296, 0x7296}, {0x7297, 0x7297}, {0x7298, 0x7298}, {0x7299, 0x7299}, {0x729A, 0x729A}, {0x729B, 0x729B}, {0x729C, 0x729C}, + {0x729D, 0x729D}, {0x729E, 0x729E}, {0x729F, 0x729F}, {0x72A0, 0x72A0}, {0x72A1, 0x72A1}, {0x72A2, 0x72A2}, {0x72A3, 0x72A3}, + {0x72A4, 0x72A4}, {0x72A5, 0x72A5}, {0x72A6, 0x72A6}, {0x72A7, 0x72A7}, {0x72A8, 0x72A8}, {0x72A9, 0x72A9}, {0x72AA, 0x72AA}, + {0x72AB, 0x72AB}, {0x72AC, 0x72AC}, {0x72AD, 0x72AD}, {0x72AE, 0x72AE}, {0x72AF, 0x72AF}, {0x72B0, 0x72B0}, {0x72B1, 0x72B1}, + {0x72B2, 0x72B2}, {0x72B3, 0x72B3}, {0x72B4, 0x72B4}, {0x72B5, 0x72B5}, {0x72B6, 0x72B6}, {0x72B7, 0x72B7}, {0x72B8, 0x72B8}, + {0x72B9, 0x72B9}, {0x72BA, 0x72BA}, {0x72BB, 0x72BB}, {0x72BC, 0x72BC}, {0x72BD, 0x72BD}, {0x72BE, 0x72BE}, {0x72BF, 0x72BF}, + {0x72C0, 0x72C0}, {0x72C1, 0x72C1}, {0x72C2, 0x72C2}, {0x72C3, 0x72C3}, {0x72C4, 0x72C4}, {0x72C5, 0x72C5}, {0x72C6, 0x72C6}, + {0x72C7, 0x72C7}, {0x72C8, 0x72C8}, {0x72C9, 0x72C9}, {0x72CA, 0x72CA}, {0x72CB, 0x72CB}, {0x72CC, 0x72CC}, {0x72CD, 0x72CD}, + {0x72CE, 0x72CE}, {0x72CF, 0x72CF}, {0x72D0, 0x72D0}, {0x72D1, 0x72D1}, {0x72D2, 0x72D2}, {0x72D3, 0x72D3}, {0x72D4, 0x72D4}, + {0x72D5, 0x72D5}, {0x72D6, 0x72D6}, {0x72D7, 0x72D7}, {0x72D8, 0x72D8}, {0x72D9, 0x72D9}, {0x72DA, 0x72DA}, {0x72DB, 0x72DB}, + {0x72DC, 0x72DC}, {0x72DD, 0x72DD}, {0x72DE, 0x72DE}, {0x72DF, 0x72DF}, {0x72E0, 0x72E0}, {0x72E1, 0x72E1}, {0x72E2, 0x72E2}, + {0x72E3, 0x72E3}, {0x72E4, 0x72E4}, {0x72E5, 0x72E5}, {0x72E6, 0x72E6}, {0x72E7, 0x72E7}, {0x72E8, 0x72E8}, {0x72E9, 0x72E9}, + {0x72EA, 0x72EA}, {0x72EB, 0x72EB}, {0x72EC, 0x72EC}, {0x72ED, 0x72ED}, {0x72EE, 0x72EE}, {0x72EF, 0x72EF}, {0x72F0, 0x72F0}, + {0x72F1, 0x72F1}, {0x72F2, 0x72F2}, {0x72F3, 0x72F3}, {0x72F4, 0x72F4}, {0x72F5, 0x72F5}, {0x72F6, 0x72F6}, {0x72F7, 0x72F7}, + {0x72F8, 0x72F8}, {0x72F9, 0x72F9}, {0x72FA, 0x72FA}, {0x72FB, 0x72FB}, {0x72FC, 0x72FC}, {0x72FD, 0x72FD}, {0x72FE, 0x72FE}, + {0x72FF, 0x72FF}, {0x7300, 0x7300}, {0x7301, 0x7301}, {0x7302, 0x7302}, {0x7303, 0x7303}, {0x7304, 0x7304}, {0x7305, 0x7305}, + {0x7306, 0x7306}, {0x7307, 0x7307}, {0x7308, 0x7308}, {0x7309, 0x7309}, {0x730A, 0x730A}, {0x730B, 0x730B}, {0x730C, 0x730C}, + {0x730D, 0x730D}, {0x730E, 0x730E}, {0x730F, 0x730F}, {0x7310, 0x7310}, {0x7311, 0x7311}, {0x7312, 0x7312}, {0x7313, 0x7313}, + {0x7314, 0x7314}, {0x7315, 0x7315}, {0x7316, 0x7316}, {0x7317, 0x7317}, {0x7318, 0x7318}, {0x7319, 0x7319}, {0x731A, 0x731A}, + {0x731B, 0x731B}, {0x731C, 0x731C}, {0x731D, 0x731D}, {0x731E, 0x731E}, {0x731F, 0x731F}, {0x7320, 0x7320}, {0x7321, 0x7321}, + {0x7322, 0x7322}, {0x7323, 0x7323}, {0x7324, 0x7324}, {0x7325, 0x7325}, {0x7326, 0x7326}, {0x7327, 0x7327}, {0x7328, 0x7328}, + {0x7329, 0x7329}, {0x732A, 0x732A}, {0x732B, 0x732B}, {0x732C, 0x732C}, {0x732D, 0x732D}, {0x732E, 0x732E}, {0x732F, 0x732F}, + {0x7330, 0x7330}, {0x7331, 0x7331}, {0x7332, 0x7332}, {0x7333, 0x7333}, {0x7334, 0x7334}, {0x7335, 0x7335}, {0x7336, 0x7336}, + {0x7337, 0x7337}, {0x7338, 0x7338}, {0x7339, 0x7339}, {0x733A, 0x733A}, {0x733B, 0x733B}, {0x733C, 0x733C}, {0x733D, 0x733D}, + {0x733E, 0x733E}, {0x733F, 0x733F}, {0x7340, 0x7340}, {0x7341, 0x7341}, {0x7342, 0x7342}, {0x7343, 0x7343}, {0x7344, 0x7344}, + {0x7345, 0x7345}, {0x7346, 0x7346}, {0x7347, 0x7347}, {0x7348, 0x7348}, {0x7349, 0x7349}, {0x734A, 0x734A}, {0x734B, 0x734B}, + {0x734C, 0x734C}, {0x734D, 0x734D}, {0x734E, 0x734E}, {0x734F, 0x734F}, {0x7350, 0x7350}, {0x7351, 0x7351}, {0x7352, 0x7352}, + {0x7353, 0x7353}, {0x7354, 0x7354}, {0x7355, 0x7355}, {0x7356, 0x7356}, {0x7357, 0x7357}, {0x7358, 0x7358}, {0x7359, 0x7359}, + {0x735A, 0x735A}, {0x735B, 0x735B}, {0x735C, 0x735C}, {0x735D, 0x735D}, {0x735E, 0x735E}, {0x735F, 0x735F}, {0x7360, 0x7360}, + {0x7361, 0x7361}, {0x7362, 0x7362}, {0x7363, 0x7363}, {0x7364, 0x7364}, {0x7365, 0x7365}, {0x7366, 0x7366}, {0x7367, 0x7367}, + {0x7368, 0x7368}, {0x7369, 0x7369}, {0x736A, 0x736A}, {0x736B, 0x736B}, {0x736C, 0x736C}, {0x736D, 0x736D}, {0x736E, 0x736E}, + {0x736F, 0x736F}, {0x7370, 0x7370}, {0x7371, 0x7371}, {0x7372, 0x7372}, {0x7373, 0x7373}, {0x7374, 0x7374}, {0x7375, 0x7375}, + {0x7376, 0x7376}, {0x7377, 0x7377}, {0x7378, 0x7378}, {0x7379, 0x7379}, {0x737A, 0x737A}, {0x737B, 0x737B}, {0x737C, 0x737C}, + {0x737D, 0x737D}, {0x737E, 0x737E}, {0x737F, 0x737F}, {0x7380, 0x7380}, {0x7381, 0x7381}, {0x7382, 0x7382}, {0x7383, 0x7383}, + {0x7384, 0x7384}, {0x7385, 0x7385}, {0x7386, 0x7386}, {0x7387, 0x7387}, {0x7388, 0x7388}, {0x7389, 0x7389}, {0x738A, 0x738A}, + {0x738B, 0x738B}, {0x738C, 0x738C}, {0x738D, 0x738D}, {0x738E, 0x738E}, {0x738F, 0x738F}, {0x7390, 0x7390}, {0x7391, 0x7391}, + {0x7392, 0x7392}, {0x7393, 0x7393}, {0x7394, 0x7394}, {0x7395, 0x7395}, {0x7396, 0x7396}, {0x7397, 0x7397}, {0x7398, 0x7398}, + {0x7399, 0x7399}, {0x739A, 0x739A}, {0x739B, 0x739B}, {0x739C, 0x739C}, {0x739D, 0x739D}, {0x739E, 0x739E}, {0x739F, 0x739F}, + {0x73A0, 0x73A0}, {0x73A1, 0x73A1}, {0x73A2, 0x73A2}, {0x73A3, 0x73A3}, {0x73A4, 0x73A4}, {0x73A5, 0x73A5}, {0x73A6, 0x73A6}, + {0x73A7, 0x73A7}, {0x73A8, 0x73A8}, {0x73A9, 0x73A9}, {0x73AA, 0x73AA}, {0x73AB, 0x73AB}, {0x73AC, 0x73AC}, {0x73AD, 0x73AD}, + {0x73AE, 0x73AE}, {0x73AF, 0x73AF}, {0x73B0, 0x73B0}, {0x73B1, 0x73B1}, {0x73B2, 0x73B2}, {0x73B3, 0x73B3}, {0x73B4, 0x73B4}, + {0x73B5, 0x73B5}, {0x73B6, 0x73B6}, {0x73B7, 0x73B7}, {0x73B8, 0x73B8}, {0x73B9, 0x73B9}, {0x73BA, 0x73BA}, {0x73BB, 0x73BB}, + {0x73BC, 0x73BC}, {0x73BD, 0x73BD}, {0x73BE, 0x73BE}, {0x73BF, 0x73BF}, {0x73C0, 0x73C0}, {0x73C1, 0x73C1}, {0x73C2, 0x73C2}, + {0x73C3, 0x73C3}, {0x73C4, 0x73C4}, {0x73C5, 0x73C5}, {0x73C6, 0x73C6}, {0x73C7, 0x73C7}, {0x73C8, 0x73C8}, {0x73C9, 0x73C9}, + {0x73CA, 0x73CA}, {0x73CB, 0x73CB}, {0x73CC, 0x73CC}, {0x73CD, 0x73CD}, {0x73CE, 0x73CE}, {0x73CF, 0x73CF}, {0x73D0, 0x73D0}, + {0x73D1, 0x73D1}, {0x73D2, 0x73D2}, {0x73D3, 0x73D3}, {0x73D4, 0x73D4}, {0x73D5, 0x73D5}, {0x73D6, 0x73D6}, {0x73D7, 0x73D7}, + {0x73D8, 0x73D8}, {0x73D9, 0x73D9}, {0x73DA, 0x73DA}, {0x73DB, 0x73DB}, {0x73DC, 0x73DC}, {0x73DD, 0x73DD}, {0x73DE, 0x73DE}, + {0x73DF, 0x73DF}, {0x73E0, 0x73E0}, {0x73E1, 0x73E1}, {0x73E2, 0x73E2}, {0x73E3, 0x73E3}, {0x73E4, 0x73E4}, {0x73E5, 0x73E5}, + {0x73E6, 0x73E6}, {0x73E7, 0x73E7}, {0x73E8, 0x73E8}, {0x73E9, 0x73E9}, {0x73EA, 0x73EA}, {0x73EB, 0x73EB}, {0x73EC, 0x73EC}, + {0x73ED, 0x73ED}, {0x73EE, 0x73EE}, {0x73EF, 0x73EF}, {0x73F0, 0x73F0}, {0x73F1, 0x73F1}, {0x73F2, 0x73F2}, {0x73F3, 0x73F3}, + {0x73F4, 0x73F4}, {0x73F5, 0x73F5}, {0x73F6, 0x73F6}, {0x73F7, 0x73F7}, {0x73F8, 0x73F8}, {0x73F9, 0x73F9}, {0x73FA, 0x73FA}, + {0x73FB, 0x73FB}, {0x73FC, 0x73FC}, {0x73FD, 0x73FD}, {0x73FE, 0x73FE}, {0x73FF, 0x73FF}, {0x7400, 0x7400}, {0x7401, 0x7401}, + {0x7402, 0x7402}, {0x7403, 0x7403}, {0x7404, 0x7404}, {0x7405, 0x7405}, {0x7406, 0x7406}, {0x7407, 0x7407}, {0x7408, 0x7408}, + {0x7409, 0x7409}, {0x740A, 0x740A}, {0x740B, 0x740B}, {0x740C, 0x740C}, {0x740D, 0x740D}, {0x740E, 0x740E}, {0x740F, 0x740F}, + {0x7410, 0x7410}, {0x7411, 0x7411}, {0x7412, 0x7412}, {0x7413, 0x7413}, {0x7414, 0x7414}, {0x7415, 0x7415}, {0x7416, 0x7416}, + {0x7417, 0x7417}, {0x7418, 0x7418}, {0x7419, 0x7419}, {0x741A, 0x741A}, {0x741B, 0x741B}, {0x741C, 0x741C}, {0x741D, 0x741D}, + {0x741E, 0x741E}, {0x741F, 0x741F}, {0x7420, 0x7420}, {0x7421, 0x7421}, {0x7422, 0x7422}, {0x7423, 0x7423}, {0x7424, 0x7424}, + {0x7425, 0x7425}, {0x7426, 0x7426}, {0x7427, 0x7427}, {0x7428, 0x7428}, {0x7429, 0x7429}, {0x742A, 0x742A}, {0x742B, 0x742B}, + {0x742C, 0x742C}, {0x742D, 0x742D}, {0x742E, 0x742E}, {0x742F, 0x742F}, {0x7430, 0x7430}, {0x7431, 0x7431}, {0x7432, 0x7432}, + {0x7433, 0x7433}, {0x7434, 0x7434}, {0x7435, 0x7435}, {0x7436, 0x7436}, {0x7437, 0x7437}, {0x7438, 0x7438}, {0x7439, 0x7439}, + {0x743A, 0x743A}, {0x743B, 0x743B}, {0x743C, 0x743C}, {0x743D, 0x743D}, {0x743E, 0x743E}, {0x743F, 0x743F}, {0x7440, 0x7440}, + {0x7441, 0x7441}, {0x7442, 0x7442}, {0x7443, 0x7443}, {0x7444, 0x7444}, {0x7445, 0x7445}, {0x7446, 0x7446}, {0x7447, 0x7447}, + {0x7448, 0x7448}, {0x7449, 0x7449}, {0x744A, 0x744A}, {0x744B, 0x744B}, {0x744C, 0x744C}, {0x744D, 0x744D}, {0x744E, 0x744E}, + {0x744F, 0x744F}, {0x7450, 0x7450}, {0x7451, 0x7451}, {0x7452, 0x7452}, {0x7453, 0x7453}, {0x7454, 0x7454}, {0x7455, 0x7455}, + {0x7456, 0x7456}, {0x7457, 0x7457}, {0x7458, 0x7458}, {0x7459, 0x7459}, {0x745A, 0x745A}, {0x745B, 0x745B}, {0x745C, 0x745C}, + {0x745D, 0x745D}, {0x745E, 0x745E}, {0x745F, 0x745F}, {0x7460, 0x7460}, {0x7461, 0x7461}, {0x7462, 0x7462}, {0x7463, 0x7463}, + {0x7464, 0x7464}, {0x7465, 0x7465}, {0x7466, 0x7466}, {0x7467, 0x7467}, {0x7468, 0x7468}, {0x7469, 0x7469}, {0x746A, 0x746A}, + {0x746B, 0x746B}, {0x746C, 0x746C}, {0x746D, 0x746D}, {0x746E, 0x746E}, {0x746F, 0x746F}, {0x7470, 0x7470}, {0x7471, 0x7471}, + {0x7472, 0x7472}, {0x7473, 0x7473}, {0x7474, 0x7474}, {0x7475, 0x7475}, {0x7476, 0x7476}, {0x7477, 0x7477}, {0x7478, 0x7478}, + {0x7479, 0x7479}, {0x747A, 0x747A}, {0x747B, 0x747B}, {0x747C, 0x747C}, {0x747D, 0x747D}, {0x747E, 0x747E}, {0x747F, 0x747F}, + {0x7480, 0x7480}, {0x7481, 0x7481}, {0x7482, 0x7482}, {0x7483, 0x7483}, {0x7484, 0x7484}, {0x7485, 0x7485}, {0x7486, 0x7486}, + {0x7487, 0x7487}, {0x7488, 0x7488}, {0x7489, 0x7489}, {0x748A, 0x748A}, {0x748B, 0x748B}, {0x748C, 0x748C}, {0x748D, 0x748D}, + {0x748E, 0x748E}, {0x748F, 0x748F}, {0x7490, 0x7490}, {0x7491, 0x7491}, {0x7492, 0x7492}, {0x7493, 0x7493}, {0x7494, 0x7494}, + {0x7495, 0x7495}, {0x7496, 0x7496}, {0x7497, 0x7497}, {0x7498, 0x7498}, {0x7499, 0x7499}, {0x749A, 0x749A}, {0x749B, 0x749B}, + {0x749C, 0x749C}, {0x749D, 0x749D}, {0x749E, 0x749E}, {0x749F, 0x749F}, {0x74A0, 0x74A0}, {0x74A1, 0x74A1}, {0x74A2, 0x74A2}, + {0x74A3, 0x74A3}, {0x74A4, 0x74A4}, {0x74A5, 0x74A5}, {0x74A6, 0x74A6}, {0x74A7, 0x74A7}, {0x74A8, 0x74A8}, {0x74A9, 0x74A9}, + {0x74AA, 0x74AA}, {0x74AB, 0x74AB}, {0x74AC, 0x74AC}, {0x74AD, 0x74AD}, {0x74AE, 0x74AE}, {0x74AF, 0x74AF}, {0x74B0, 0x74B0}, + {0x74B1, 0x74B1}, {0x74B2, 0x74B2}, {0x74B3, 0x74B3}, {0x74B4, 0x74B4}, {0x74B5, 0x74B5}, {0x74B6, 0x74B6}, {0x74B7, 0x74B7}, + {0x74B8, 0x74B8}, {0x74B9, 0x74B9}, {0x74BA, 0x74BA}, {0x74BB, 0x74BB}, {0x74BC, 0x74BC}, {0x74BD, 0x74BD}, {0x74BE, 0x74BE}, + {0x74BF, 0x74BF}, {0x74C0, 0x74C0}, {0x74C1, 0x74C1}, {0x74C2, 0x74C2}, {0x74C3, 0x74C3}, {0x74C4, 0x74C4}, {0x74C5, 0x74C5}, + {0x74C6, 0x74C6}, {0x74C7, 0x74C7}, {0x74C8, 0x74C8}, {0x74C9, 0x74C9}, {0x74CA, 0x74CA}, {0x74CB, 0x74CB}, {0x74CC, 0x74CC}, + {0x74CD, 0x74CD}, {0x74CE, 0x74CE}, {0x74CF, 0x74CF}, {0x74D0, 0x74D0}, {0x74D1, 0x74D1}, {0x74D2, 0x74D2}, {0x74D3, 0x74D3}, + {0x74D4, 0x74D4}, {0x74D5, 0x74D5}, {0x74D6, 0x74D6}, {0x74D7, 0x74D7}, {0x74D8, 0x74D8}, {0x74D9, 0x74D9}, {0x74DA, 0x74DA}, + {0x74DB, 0x74DB}, {0x74DC, 0x74DC}, {0x74DD, 0x74DD}, {0x74DE, 0x74DE}, {0x74DF, 0x74DF}, {0x74E0, 0x74E0}, {0x74E1, 0x74E1}, + {0x74E2, 0x74E2}, {0x74E3, 0x74E3}, {0x74E4, 0x74E4}, {0x74E5, 0x74E5}, {0x74E6, 0x74E6}, {0x74E7, 0x74E7}, {0x74E8, 0x74E8}, + {0x74E9, 0x74E9}, {0x74EA, 0x74EA}, {0x74EB, 0x74EB}, {0x74EC, 0x74EC}, {0x74ED, 0x74ED}, {0x74EE, 0x74EE}, {0x74EF, 0x74EF}, + {0x74F0, 0x74F0}, {0x74F1, 0x74F1}, {0x74F2, 0x74F2}, {0x74F3, 0x74F3}, {0x74F4, 0x74F4}, {0x74F5, 0x74F5}, {0x74F6, 0x74F6}, + {0x74F7, 0x74F7}, {0x74F8, 0x74F8}, {0x74F9, 0x74F9}, {0x74FA, 0x74FA}, {0x74FB, 0x74FB}, {0x74FC, 0x74FC}, {0x74FD, 0x74FD}, + {0x74FE, 0x74FE}, {0x74FF, 0x74FF}, {0x7500, 0x7500}, {0x7501, 0x7501}, {0x7502, 0x7502}, {0x7503, 0x7503}, {0x7504, 0x7504}, + {0x7505, 0x7505}, {0x7506, 0x7506}, {0x7507, 0x7507}, {0x7508, 0x7508}, {0x7509, 0x7509}, {0x750A, 0x750A}, {0x750B, 0x750B}, + {0x750C, 0x750C}, {0x750D, 0x750D}, {0x750E, 0x750E}, {0x750F, 0x750F}, {0x7510, 0x7510}, {0x7511, 0x7511}, {0x7512, 0x7512}, + {0x7513, 0x7513}, {0x7514, 0x7514}, {0x7515, 0x7515}, {0x7516, 0x7516}, {0x7517, 0x7517}, {0x7518, 0x7518}, {0x7519, 0x7519}, + {0x751A, 0x751A}, {0x751B, 0x751B}, {0x751C, 0x751C}, {0x751D, 0x751D}, {0x751E, 0x751E}, {0x751F, 0x751F}, {0x7520, 0x7520}, + {0x7521, 0x7521}, {0x7522, 0x7522}, {0x7523, 0x7523}, {0x7524, 0x7524}, {0x7525, 0x7525}, {0x7526, 0x7526}, {0x7527, 0x7527}, + {0x7528, 0x7528}, {0x7529, 0x7529}, {0x752A, 0x752A}, {0x752B, 0x752B}, {0x752C, 0x752C}, {0x752D, 0x752D}, {0x752E, 0x752E}, + {0x752F, 0x752F}, {0x7530, 0x7530}, {0x7531, 0x7531}, {0x7532, 0x7532}, {0x7533, 0x7533}, {0x7534, 0x7534}, {0x7535, 0x7535}, + {0x7536, 0x7536}, {0x7537, 0x7537}, {0x7538, 0x7538}, {0x7539, 0x7539}, {0x753A, 0x753A}, {0x753B, 0x753B}, {0x753C, 0x753C}, + {0x753D, 0x753D}, {0x753E, 0x753E}, {0x753F, 0x753F}, {0x7540, 0x7540}, {0x7541, 0x7541}, {0x7542, 0x7542}, {0x7543, 0x7543}, + {0x7544, 0x7544}, {0x7545, 0x7545}, {0x7546, 0x7546}, {0x7547, 0x7547}, {0x7548, 0x7548}, {0x7549, 0x7549}, {0x754A, 0x754A}, + {0x754B, 0x754B}, {0x754C, 0x754C}, {0x754D, 0x754D}, {0x754E, 0x754E}, {0x754F, 0x754F}, {0x7550, 0x7550}, {0x7551, 0x7551}, + {0x7552, 0x7552}, {0x7553, 0x7553}, {0x7554, 0x7554}, {0x7555, 0x7555}, {0x7556, 0x7556}, {0x7557, 0x7557}, {0x7558, 0x7558}, + {0x7559, 0x7559}, {0x755A, 0x755A}, {0x755B, 0x755B}, {0x755C, 0x755C}, {0x755D, 0x755D}, {0x755E, 0x755E}, {0x755F, 0x755F}, + {0x7560, 0x7560}, {0x7561, 0x7561}, {0x7562, 0x7562}, {0x7563, 0x7563}, {0x7564, 0x7564}, {0x7565, 0x7565}, {0x7566, 0x7566}, + {0x7567, 0x7567}, {0x7568, 0x7568}, {0x7569, 0x7569}, {0x756A, 0x756A}, {0x756B, 0x756B}, {0x756C, 0x756C}, {0x756D, 0x756D}, + {0x756E, 0x756E}, {0x756F, 0x756F}, {0x7570, 0x7570}, {0x7571, 0x7571}, {0x7572, 0x7572}, {0x7573, 0x7573}, {0x7574, 0x7574}, + {0x7575, 0x7575}, {0x7576, 0x7576}, {0x7577, 0x7577}, {0x7578, 0x7578}, {0x7579, 0x7579}, {0x757A, 0x757A}, {0x757B, 0x757B}, + {0x757C, 0x757C}, {0x757D, 0x757D}, {0x757E, 0x757E}, {0x757F, 0x757F}, {0x7580, 0x7580}, {0x7581, 0x7581}, {0x7582, 0x7582}, + {0x7583, 0x7583}, {0x7584, 0x7584}, {0x7585, 0x7585}, {0x7586, 0x7586}, {0x7587, 0x7587}, {0x7588, 0x7588}, {0x7589, 0x7589}, + {0x758A, 0x758A}, {0x758B, 0x758B}, {0x758C, 0x758C}, {0x758D, 0x758D}, {0x758E, 0x758E}, {0x758F, 0x758F}, {0x7590, 0x7590}, + {0x7591, 0x7591}, {0x7592, 0x7592}, {0x7593, 0x7593}, {0x7594, 0x7594}, {0x7595, 0x7595}, {0x7596, 0x7596}, {0x7597, 0x7597}, + {0x7598, 0x7598}, {0x7599, 0x7599}, {0x759A, 0x759A}, {0x759B, 0x759B}, {0x759C, 0x759C}, {0x759D, 0x759D}, {0x759E, 0x759E}, + {0x759F, 0x759F}, {0x75A0, 0x75A0}, {0x75A1, 0x75A1}, {0x75A2, 0x75A2}, {0x75A3, 0x75A3}, {0x75A4, 0x75A4}, {0x75A5, 0x75A5}, + {0x75A6, 0x75A6}, {0x75A7, 0x75A7}, {0x75A8, 0x75A8}, {0x75A9, 0x75A9}, {0x75AA, 0x75AA}, {0x75AB, 0x75AB}, {0x75AC, 0x75AC}, + {0x75AD, 0x75AD}, {0x75AE, 0x75AE}, {0x75AF, 0x75AF}, {0x75B0, 0x75B0}, {0x75B1, 0x75B1}, {0x75B2, 0x75B2}, {0x75B3, 0x75B3}, + {0x75B4, 0x75B4}, {0x75B5, 0x75B5}, {0x75B6, 0x75B6}, {0x75B7, 0x75B7}, {0x75B8, 0x75B8}, {0x75B9, 0x75B9}, {0x75BA, 0x75BA}, + {0x75BB, 0x75BB}, {0x75BC, 0x75BC}, {0x75BD, 0x75BD}, {0x75BE, 0x75BE}, {0x75BF, 0x75BF}, {0x75C0, 0x75C0}, {0x75C1, 0x75C1}, + {0x75C2, 0x75C2}, {0x75C3, 0x75C3}, {0x75C4, 0x75C4}, {0x75C5, 0x75C5}, {0x75C6, 0x75C6}, {0x75C7, 0x75C7}, {0x75C8, 0x75C8}, + {0x75C9, 0x75C9}, {0x75CA, 0x75CA}, {0x75CB, 0x75CB}, {0x75CC, 0x75CC}, {0x75CD, 0x75CD}, {0x75CE, 0x75CE}, {0x75CF, 0x75CF}, + {0x75D0, 0x75D0}, {0x75D1, 0x75D1}, {0x75D2, 0x75D2}, {0x75D3, 0x75D3}, {0x75D4, 0x75D4}, {0x75D5, 0x75D5}, {0x75D6, 0x75D6}, + {0x75D7, 0x75D7}, {0x75D8, 0x75D8}, {0x75D9, 0x75D9}, {0x75DA, 0x75DA}, {0x75DB, 0x75DB}, {0x75DC, 0x75DC}, {0x75DD, 0x75DD}, + {0x75DE, 0x75DE}, {0x75DF, 0x75DF}, {0x75E0, 0x75E0}, {0x75E1, 0x75E1}, {0x75E2, 0x75E2}, {0x75E3, 0x75E3}, {0x75E4, 0x75E4}, + {0x75E5, 0x75E5}, {0x75E6, 0x75E6}, {0x75E7, 0x75E7}, {0x75E8, 0x75E8}, {0x75E9, 0x75E9}, {0x75EA, 0x75EA}, {0x75EB, 0x75EB}, + {0x75EC, 0x75EC}, {0x75ED, 0x75ED}, {0x75EE, 0x75EE}, {0x75EF, 0x75EF}, {0x75F0, 0x75F0}, {0x75F1, 0x75F1}, {0x75F2, 0x75F2}, + {0x75F3, 0x75F3}, {0x75F4, 0x75F4}, {0x75F5, 0x75F5}, {0x75F6, 0x75F6}, {0x75F7, 0x75F7}, {0x75F8, 0x75F8}, {0x75F9, 0x75F9}, + {0x75FA, 0x75FA}, {0x75FB, 0x75FB}, {0x75FC, 0x75FC}, {0x75FD, 0x75FD}, {0x75FE, 0x75FE}, {0x75FF, 0x75FF}, {0x7600, 0x7600}, + {0x7601, 0x7601}, {0x7602, 0x7602}, {0x7603, 0x7603}, {0x7604, 0x7604}, {0x7605, 0x7605}, {0x7606, 0x7606}, {0x7607, 0x7607}, + {0x7608, 0x7608}, {0x7609, 0x7609}, {0x760A, 0x760A}, {0x760B, 0x760B}, {0x760C, 0x760C}, {0x760D, 0x760D}, {0x760E, 0x760E}, + {0x760F, 0x760F}, {0x7610, 0x7610}, {0x7611, 0x7611}, {0x7612, 0x7612}, {0x7613, 0x7613}, {0x7614, 0x7614}, {0x7615, 0x7615}, + {0x7616, 0x7616}, {0x7617, 0x7617}, {0x7618, 0x7618}, {0x7619, 0x7619}, {0x761A, 0x761A}, {0x761B, 0x761B}, {0x761C, 0x761C}, + {0x761D, 0x761D}, {0x761E, 0x761E}, {0x761F, 0x761F}, {0x7620, 0x7620}, {0x7621, 0x7621}, {0x7622, 0x7622}, {0x7623, 0x7623}, + {0x7624, 0x7624}, {0x7625, 0x7625}, {0x7626, 0x7626}, {0x7627, 0x7627}, {0x7628, 0x7628}, {0x7629, 0x7629}, {0x762A, 0x762A}, + {0x762B, 0x762B}, {0x762C, 0x762C}, {0x762D, 0x762D}, {0x762E, 0x762E}, {0x762F, 0x762F}, {0x7630, 0x7630}, {0x7631, 0x7631}, + {0x7632, 0x7632}, {0x7633, 0x7633}, {0x7634, 0x7634}, {0x7635, 0x7635}, {0x7636, 0x7636}, {0x7637, 0x7637}, {0x7638, 0x7638}, + {0x7639, 0x7639}, {0x763A, 0x763A}, {0x763B, 0x763B}, {0x763C, 0x763C}, {0x763D, 0x763D}, {0x763E, 0x763E}, {0x763F, 0x763F}, + {0x7640, 0x7640}, {0x7641, 0x7641}, {0x7642, 0x7642}, {0x7643, 0x7643}, {0x7644, 0x7644}, {0x7645, 0x7645}, {0x7646, 0x7646}, + {0x7647, 0x7647}, {0x7648, 0x7648}, {0x7649, 0x7649}, {0x764A, 0x764A}, {0x764B, 0x764B}, {0x764C, 0x764C}, {0x764D, 0x764D}, + {0x764E, 0x764E}, {0x764F, 0x764F}, {0x7650, 0x7650}, {0x7651, 0x7651}, {0x7652, 0x7652}, {0x7653, 0x7653}, {0x7654, 0x7654}, + {0x7655, 0x7655}, {0x7656, 0x7656}, {0x7657, 0x7657}, {0x7658, 0x7658}, {0x7659, 0x7659}, {0x765A, 0x765A}, {0x765B, 0x765B}, + {0x765C, 0x765C}, {0x765D, 0x765D}, {0x765E, 0x765E}, {0x765F, 0x765F}, {0x7660, 0x7660}, {0x7661, 0x7661}, {0x7662, 0x7662}, + {0x7663, 0x7663}, {0x7664, 0x7664}, {0x7665, 0x7665}, {0x7666, 0x7666}, {0x7667, 0x7667}, {0x7668, 0x7668}, {0x7669, 0x7669}, + {0x766A, 0x766A}, {0x766B, 0x766B}, {0x766C, 0x766C}, {0x766D, 0x766D}, {0x766E, 0x766E}, {0x766F, 0x766F}, {0x7670, 0x7670}, + {0x7671, 0x7671}, {0x7672, 0x7672}, {0x7673, 0x7673}, {0x7674, 0x7674}, {0x7675, 0x7675}, {0x7676, 0x7676}, {0x7677, 0x7677}, + {0x7678, 0x7678}, {0x7679, 0x7679}, {0x767A, 0x767A}, {0x767B, 0x767B}, {0x767C, 0x767C}, {0x767D, 0x767D}, {0x767E, 0x767E}, + {0x767F, 0x767F}, {0x7680, 0x7680}, {0x7681, 0x7681}, {0x7682, 0x7682}, {0x7683, 0x7683}, {0x7684, 0x7684}, {0x7685, 0x7685}, + {0x7686, 0x7686}, {0x7687, 0x7687}, {0x7688, 0x7688}, {0x7689, 0x7689}, {0x768A, 0x768A}, {0x768B, 0x768B}, {0x768C, 0x768C}, + {0x768D, 0x768D}, {0x768E, 0x768E}, {0x768F, 0x768F}, {0x7690, 0x7690}, {0x7691, 0x7691}, {0x7692, 0x7692}, {0x7693, 0x7693}, + {0x7694, 0x7694}, {0x7695, 0x7695}, {0x7696, 0x7696}, {0x7697, 0x7697}, {0x7698, 0x7698}, {0x7699, 0x7699}, {0x769A, 0x769A}, + {0x769B, 0x769B}, {0x769C, 0x769C}, {0x769D, 0x769D}, {0x769E, 0x769E}, {0x769F, 0x769F}, {0x76A0, 0x76A0}, {0x76A1, 0x76A1}, + {0x76A2, 0x76A2}, {0x76A3, 0x76A3}, {0x76A4, 0x76A4}, {0x76A5, 0x76A5}, {0x76A6, 0x76A6}, {0x76A7, 0x76A7}, {0x76A8, 0x76A8}, + {0x76A9, 0x76A9}, {0x76AA, 0x76AA}, {0x76AB, 0x76AB}, {0x76AC, 0x76AC}, {0x76AD, 0x76AD}, {0x76AE, 0x76AE}, {0x76AF, 0x76AF}, + {0x76B0, 0x76B0}, {0x76B1, 0x76B1}, {0x76B2, 0x76B2}, {0x76B3, 0x76B3}, {0x76B4, 0x76B4}, {0x76B5, 0x76B5}, {0x76B6, 0x76B6}, + {0x76B7, 0x76B7}, {0x76B8, 0x76B8}, {0x76B9, 0x76B9}, {0x76BA, 0x76BA}, {0x76BB, 0x76BB}, {0x76BC, 0x76BC}, {0x76BD, 0x76BD}, + {0x76BE, 0x76BE}, {0x76BF, 0x76BF}, {0x76C0, 0x76C0}, {0x76C1, 0x76C1}, {0x76C2, 0x76C2}, {0x76C3, 0x76C3}, {0x76C4, 0x76C4}, + {0x76C5, 0x76C5}, {0x76C6, 0x76C6}, {0x76C7, 0x76C7}, {0x76C8, 0x76C8}, {0x76C9, 0x76C9}, {0x76CA, 0x76CA}, {0x76CB, 0x76CB}, + {0x76CC, 0x76CC}, {0x76CD, 0x76CD}, {0x76CE, 0x76CE}, {0x76CF, 0x76CF}, {0x76D0, 0x76D0}, {0x76D1, 0x76D1}, {0x76D2, 0x76D2}, + {0x76D3, 0x76D3}, {0x76D4, 0x76D4}, {0x76D5, 0x76D5}, {0x76D6, 0x76D6}, {0x76D7, 0x76D7}, {0x76D8, 0x76D8}, {0x76D9, 0x76D9}, + {0x76DA, 0x76DA}, {0x76DB, 0x76DB}, {0x76DC, 0x76DC}, {0x76DD, 0x76DD}, {0x76DE, 0x76DE}, {0x76DF, 0x76DF}, {0x76E0, 0x76E0}, + {0x76E1, 0x76E1}, {0x76E2, 0x76E2}, {0x76E3, 0x76E3}, {0x76E4, 0x76E4}, {0x76E5, 0x76E5}, {0x76E6, 0x76E6}, {0x76E7, 0x76E7}, + {0x76E8, 0x76E8}, {0x76E9, 0x76E9}, {0x76EA, 0x76EA}, {0x76EB, 0x76EB}, {0x76EC, 0x76EC}, {0x76ED, 0x76ED}, {0x76EE, 0x76EE}, + {0x76EF, 0x76EF}, {0x76F0, 0x76F0}, {0x76F1, 0x76F1}, {0x76F2, 0x76F2}, {0x76F3, 0x76F3}, {0x76F4, 0x76F4}, {0x76F5, 0x76F5}, + {0x76F6, 0x76F6}, {0x76F7, 0x76F7}, {0x76F8, 0x76F8}, {0x76F9, 0x76F9}, {0x76FA, 0x76FA}, {0x76FB, 0x76FB}, {0x76FC, 0x76FC}, + {0x76FD, 0x76FD}, {0x76FE, 0x76FE}, {0x76FF, 0x76FF}, {0x7700, 0x7700}, {0x7701, 0x7701}, {0x7702, 0x7702}, {0x7703, 0x7703}, + {0x7704, 0x7704}, {0x7705, 0x7705}, {0x7706, 0x7706}, {0x7707, 0x7707}, {0x7708, 0x7708}, {0x7709, 0x7709}, {0x770A, 0x770A}, + {0x770B, 0x770B}, {0x770C, 0x770C}, {0x770D, 0x770D}, {0x770E, 0x770E}, {0x770F, 0x770F}, {0x7710, 0x7710}, {0x7711, 0x7711}, + {0x7712, 0x7712}, {0x7713, 0x7713}, {0x7714, 0x7714}, {0x7715, 0x7715}, {0x7716, 0x7716}, {0x7717, 0x7717}, {0x7718, 0x7718}, + {0x7719, 0x7719}, {0x771A, 0x771A}, {0x771B, 0x771B}, {0x771C, 0x771C}, {0x771D, 0x771D}, {0x771E, 0x771E}, {0x771F, 0x771F}, + {0x7720, 0x7720}, {0x7721, 0x7721}, {0x7722, 0x7722}, {0x7723, 0x7723}, {0x7724, 0x7724}, {0x7725, 0x7725}, {0x7726, 0x7726}, + {0x7727, 0x7727}, {0x7728, 0x7728}, {0x7729, 0x7729}, {0x772A, 0x772A}, {0x772B, 0x772B}, {0x772C, 0x772C}, {0x772D, 0x772D}, + {0x772E, 0x772E}, {0x772F, 0x772F}, {0x7730, 0x7730}, {0x7731, 0x7731}, {0x7732, 0x7732}, {0x7733, 0x7733}, {0x7734, 0x7734}, + {0x7735, 0x7735}, {0x7736, 0x7736}, {0x7737, 0x7737}, {0x7738, 0x7738}, {0x7739, 0x7739}, {0x773A, 0x773A}, {0x773B, 0x773B}, + {0x773C, 0x773C}, {0x773D, 0x773D}, {0x773E, 0x773E}, {0x773F, 0x773F}, {0x7740, 0x7740}, {0x7741, 0x7741}, {0x7742, 0x7742}, + {0x7743, 0x7743}, {0x7744, 0x7744}, {0x7745, 0x7745}, {0x7746, 0x7746}, {0x7747, 0x7747}, {0x7748, 0x7748}, {0x7749, 0x7749}, + {0x774A, 0x774A}, {0x774B, 0x774B}, {0x774C, 0x774C}, {0x774D, 0x774D}, {0x774E, 0x774E}, {0x774F, 0x774F}, {0x7750, 0x7750}, + {0x7751, 0x7751}, {0x7752, 0x7752}, {0x7753, 0x7753}, {0x7754, 0x7754}, {0x7755, 0x7755}, {0x7756, 0x7756}, {0x7757, 0x7757}, + {0x7758, 0x7758}, {0x7759, 0x7759}, {0x775A, 0x775A}, {0x775B, 0x775B}, {0x775C, 0x775C}, {0x775D, 0x775D}, {0x775E, 0x775E}, + {0x775F, 0x775F}, {0x7760, 0x7760}, {0x7761, 0x7761}, {0x7762, 0x7762}, {0x7763, 0x7763}, {0x7764, 0x7764}, {0x7765, 0x7765}, + {0x7766, 0x7766}, {0x7767, 0x7767}, {0x7768, 0x7768}, {0x7769, 0x7769}, {0x776A, 0x776A}, {0x776B, 0x776B}, {0x776C, 0x776C}, + {0x776D, 0x776D}, {0x776E, 0x776E}, {0x776F, 0x776F}, {0x7770, 0x7770}, {0x7771, 0x7771}, {0x7772, 0x7772}, {0x7773, 0x7773}, + {0x7774, 0x7774}, {0x7775, 0x7775}, {0x7776, 0x7776}, {0x7777, 0x7777}, {0x7778, 0x7778}, {0x7779, 0x7779}, {0x777A, 0x777A}, + {0x777B, 0x777B}, {0x777C, 0x777C}, {0x777D, 0x777D}, {0x777E, 0x777E}, {0x777F, 0x777F}, {0x7780, 0x7780}, {0x7781, 0x7781}, + {0x7782, 0x7782}, {0x7783, 0x7783}, {0x7784, 0x7784}, {0x7785, 0x7785}, {0x7786, 0x7786}, {0x7787, 0x7787}, {0x7788, 0x7788}, + {0x7789, 0x7789}, {0x778A, 0x778A}, {0x778B, 0x778B}, {0x778C, 0x778C}, {0x778D, 0x778D}, {0x778E, 0x778E}, {0x778F, 0x778F}, + {0x7790, 0x7790}, {0x7791, 0x7791}, {0x7792, 0x7792}, {0x7793, 0x7793}, {0x7794, 0x7794}, {0x7795, 0x7795}, {0x7796, 0x7796}, + {0x7797, 0x7797}, {0x7798, 0x7798}, {0x7799, 0x7799}, {0x779A, 0x779A}, {0x779B, 0x779B}, {0x779C, 0x779C}, {0x779D, 0x779D}, + {0x779E, 0x779E}, {0x779F, 0x779F}, {0x77A0, 0x77A0}, {0x77A1, 0x77A1}, {0x77A2, 0x77A2}, {0x77A3, 0x77A3}, {0x77A4, 0x77A4}, + {0x77A5, 0x77A5}, {0x77A6, 0x77A6}, {0x77A7, 0x77A7}, {0x77A8, 0x77A8}, {0x77A9, 0x77A9}, {0x77AA, 0x77AA}, {0x77AB, 0x77AB}, + {0x77AC, 0x77AC}, {0x77AD, 0x77AD}, {0x77AE, 0x77AE}, {0x77AF, 0x77AF}, {0x77B0, 0x77B0}, {0x77B1, 0x77B1}, {0x77B2, 0x77B2}, + {0x77B3, 0x77B3}, {0x77B4, 0x77B4}, {0x77B5, 0x77B5}, {0x77B6, 0x77B6}, {0x77B7, 0x77B7}, {0x77B8, 0x77B8}, {0x77B9, 0x77B9}, + {0x77BA, 0x77BA}, {0x77BB, 0x77BB}, {0x77BC, 0x77BC}, {0x77BD, 0x77BD}, {0x77BE, 0x77BE}, {0x77BF, 0x77BF}, {0x77C0, 0x77C0}, + {0x77C1, 0x77C1}, {0x77C2, 0x77C2}, {0x77C3, 0x77C3}, {0x77C4, 0x77C4}, {0x77C5, 0x77C5}, {0x77C6, 0x77C6}, {0x77C7, 0x77C7}, + {0x77C8, 0x77C8}, {0x77C9, 0x77C9}, {0x77CA, 0x77CA}, {0x77CB, 0x77CB}, {0x77CC, 0x77CC}, {0x77CD, 0x77CD}, {0x77CE, 0x77CE}, + {0x77CF, 0x77CF}, {0x77D0, 0x77D0}, {0x77D1, 0x77D1}, {0x77D2, 0x77D2}, {0x77D3, 0x77D3}, {0x77D4, 0x77D4}, {0x77D5, 0x77D5}, + {0x77D6, 0x77D6}, {0x77D7, 0x77D7}, {0x77D8, 0x77D8}, {0x77D9, 0x77D9}, {0x77DA, 0x77DA}, {0x77DB, 0x77DB}, {0x77DC, 0x77DC}, + {0x77DD, 0x77DD}, {0x77DE, 0x77DE}, {0x77DF, 0x77DF}, {0x77E0, 0x77E0}, {0x77E1, 0x77E1}, {0x77E2, 0x77E2}, {0x77E3, 0x77E3}, + {0x77E4, 0x77E4}, {0x77E5, 0x77E5}, {0x77E6, 0x77E6}, {0x77E7, 0x77E7}, {0x77E8, 0x77E8}, {0x77E9, 0x77E9}, {0x77EA, 0x77EA}, + {0x77EB, 0x77EB}, {0x77EC, 0x77EC}, {0x77ED, 0x77ED}, {0x77EE, 0x77EE}, {0x77EF, 0x77EF}, {0x77F0, 0x77F0}, {0x77F1, 0x77F1}, + {0x77F2, 0x77F2}, {0x77F3, 0x77F3}, {0x77F4, 0x77F4}, {0x77F5, 0x77F5}, {0x77F6, 0x77F6}, {0x77F7, 0x77F7}, {0x77F8, 0x77F8}, + {0x77F9, 0x77F9}, {0x77FA, 0x77FA}, {0x77FB, 0x77FB}, {0x77FC, 0x77FC}, {0x77FD, 0x77FD}, {0x77FE, 0x77FE}, {0x77FF, 0x77FF}, + {0x7800, 0x7800}, {0x7801, 0x7801}, {0x7802, 0x7802}, {0x7803, 0x7803}, {0x7804, 0x7804}, {0x7805, 0x7805}, {0x7806, 0x7806}, + {0x7807, 0x7807}, {0x7808, 0x7808}, {0x7809, 0x7809}, {0x780A, 0x780A}, {0x780B, 0x780B}, {0x780C, 0x780C}, {0x780D, 0x780D}, + {0x780E, 0x780E}, {0x780F, 0x780F}, {0x7810, 0x7810}, {0x7811, 0x7811}, {0x7812, 0x7812}, {0x7813, 0x7813}, {0x7814, 0x7814}, + {0x7815, 0x7815}, {0x7816, 0x7816}, {0x7817, 0x7817}, {0x7818, 0x7818}, {0x7819, 0x7819}, {0x781A, 0x781A}, {0x781B, 0x781B}, + {0x781C, 0x781C}, {0x781D, 0x781D}, {0x781E, 0x781E}, {0x781F, 0x781F}, {0x7820, 0x7820}, {0x7821, 0x7821}, {0x7822, 0x7822}, + {0x7823, 0x7823}, {0x7824, 0x7824}, {0x7825, 0x7825}, {0x7826, 0x7826}, {0x7827, 0x7827}, {0x7828, 0x7828}, {0x7829, 0x7829}, + {0x782A, 0x782A}, {0x782B, 0x782B}, {0x782C, 0x782C}, {0x782D, 0x782D}, {0x782E, 0x782E}, {0x782F, 0x782F}, {0x7830, 0x7830}, + {0x7831, 0x7831}, {0x7832, 0x7832}, {0x7833, 0x7833}, {0x7834, 0x7834}, {0x7835, 0x7835}, {0x7836, 0x7836}, {0x7837, 0x7837}, + {0x7838, 0x7838}, {0x7839, 0x7839}, {0x783A, 0x783A}, {0x783B, 0x783B}, {0x783C, 0x783C}, {0x783D, 0x783D}, {0x783E, 0x783E}, + {0x783F, 0x783F}, {0x7840, 0x7840}, {0x7841, 0x7841}, {0x7842, 0x7842}, {0x7843, 0x7843}, {0x7844, 0x7844}, {0x7845, 0x7845}, + {0x7846, 0x7846}, {0x7847, 0x7847}, {0x7848, 0x7848}, {0x7849, 0x7849}, {0x784A, 0x784A}, {0x784B, 0x784B}, {0x784C, 0x784C}, + {0x784D, 0x784D}, {0x784E, 0x784E}, {0x784F, 0x784F}, {0x7850, 0x7850}, {0x7851, 0x7851}, {0x7852, 0x7852}, {0x7853, 0x7853}, + {0x7854, 0x7854}, {0x7855, 0x7855}, {0x7856, 0x7856}, {0x7857, 0x7857}, {0x7858, 0x7858}, {0x7859, 0x7859}, {0x785A, 0x785A}, + {0x785B, 0x785B}, {0x785C, 0x785C}, {0x785D, 0x785D}, {0x785E, 0x785E}, {0x785F, 0x785F}, {0x7860, 0x7860}, {0x7861, 0x7861}, + {0x7862, 0x7862}, {0x7863, 0x7863}, {0x7864, 0x7864}, {0x7865, 0x7865}, {0x7866, 0x7866}, {0x7867, 0x7867}, {0x7868, 0x7868}, + {0x7869, 0x7869}, {0x786A, 0x786A}, {0x786B, 0x786B}, {0x786C, 0x786C}, {0x786D, 0x786D}, {0x786E, 0x786E}, {0x786F, 0x786F}, + {0x7870, 0x7870}, {0x7871, 0x7871}, {0x7872, 0x7872}, {0x7873, 0x7873}, {0x7874, 0x7874}, {0x7875, 0x7875}, {0x7876, 0x7876}, + {0x7877, 0x7877}, {0x7878, 0x7878}, {0x7879, 0x7879}, {0x787A, 0x787A}, {0x787B, 0x787B}, {0x787C, 0x787C}, {0x787D, 0x787D}, + {0x787E, 0x787E}, {0x787F, 0x787F}, {0x7880, 0x7880}, {0x7881, 0x7881}, {0x7882, 0x7882}, {0x7883, 0x7883}, {0x7884, 0x7884}, + {0x7885, 0x7885}, {0x7886, 0x7886}, {0x7887, 0x7887}, {0x7888, 0x7888}, {0x7889, 0x7889}, {0x788A, 0x788A}, {0x788B, 0x788B}, + {0x788C, 0x788C}, {0x788D, 0x788D}, {0x788E, 0x788E}, {0x788F, 0x788F}, {0x7890, 0x7890}, {0x7891, 0x7891}, {0x7892, 0x7892}, + {0x7893, 0x7893}, {0x7894, 0x7894}, {0x7895, 0x7895}, {0x7896, 0x7896}, {0x7897, 0x7897}, {0x7898, 0x7898}, {0x7899, 0x7899}, + {0x789A, 0x789A}, {0x789B, 0x789B}, {0x789C, 0x789C}, {0x789D, 0x789D}, {0x789E, 0x789E}, {0x789F, 0x789F}, {0x78A0, 0x78A0}, + {0x78A1, 0x78A1}, {0x78A2, 0x78A2}, {0x78A3, 0x78A3}, {0x78A4, 0x78A4}, {0x78A5, 0x78A5}, {0x78A6, 0x78A6}, {0x78A7, 0x78A7}, + {0x78A8, 0x78A8}, {0x78A9, 0x78A9}, {0x78AA, 0x78AA}, {0x78AB, 0x78AB}, {0x78AC, 0x78AC}, {0x78AD, 0x78AD}, {0x78AE, 0x78AE}, + {0x78AF, 0x78AF}, {0x78B0, 0x78B0}, {0x78B1, 0x78B1}, {0x78B2, 0x78B2}, {0x78B3, 0x78B3}, {0x78B4, 0x78B4}, {0x78B5, 0x78B5}, + {0x78B6, 0x78B6}, {0x78B7, 0x78B7}, {0x78B8, 0x78B8}, {0x78B9, 0x78B9}, {0x78BA, 0x78BA}, {0x78BB, 0x78BB}, {0x78BC, 0x78BC}, + {0x78BD, 0x78BD}, {0x78BE, 0x78BE}, {0x78BF, 0x78BF}, {0x78C0, 0x78C0}, {0x78C1, 0x78C1}, {0x78C2, 0x78C2}, {0x78C3, 0x78C3}, + {0x78C4, 0x78C4}, {0x78C5, 0x78C5}, {0x78C6, 0x78C6}, {0x78C7, 0x78C7}, {0x78C8, 0x78C8}, {0x78C9, 0x78C9}, {0x78CA, 0x78CA}, + {0x78CB, 0x78CB}, {0x78CC, 0x78CC}, {0x78CD, 0x78CD}, {0x78CE, 0x78CE}, {0x78CF, 0x78CF}, {0x78D0, 0x78D0}, {0x78D1, 0x78D1}, + {0x78D2, 0x78D2}, {0x78D3, 0x78D3}, {0x78D4, 0x78D4}, {0x78D5, 0x78D5}, {0x78D6, 0x78D6}, {0x78D7, 0x78D7}, {0x78D8, 0x78D8}, + {0x78D9, 0x78D9}, {0x78DA, 0x78DA}, {0x78DB, 0x78DB}, {0x78DC, 0x78DC}, {0x78DD, 0x78DD}, {0x78DE, 0x78DE}, {0x78DF, 0x78DF}, + {0x78E0, 0x78E0}, {0x78E1, 0x78E1}, {0x78E2, 0x78E2}, {0x78E3, 0x78E3}, {0x78E4, 0x78E4}, {0x78E5, 0x78E5}, {0x78E6, 0x78E6}, + {0x78E7, 0x78E7}, {0x78E8, 0x78E8}, {0x78E9, 0x78E9}, {0x78EA, 0x78EA}, {0x78EB, 0x78EB}, {0x78EC, 0x78EC}, {0x78ED, 0x78ED}, + {0x78EE, 0x78EE}, {0x78EF, 0x78EF}, {0x78F0, 0x78F0}, {0x78F1, 0x78F1}, {0x78F2, 0x78F2}, {0x78F3, 0x78F3}, {0x78F4, 0x78F4}, + {0x78F5, 0x78F5}, {0x78F6, 0x78F6}, {0x78F7, 0x78F7}, {0x78F8, 0x78F8}, {0x78F9, 0x78F9}, {0x78FA, 0x78FA}, {0x78FB, 0x78FB}, + {0x78FC, 0x78FC}, {0x78FD, 0x78FD}, {0x78FE, 0x78FE}, {0x78FF, 0x78FF}, {0x7900, 0x7900}, {0x7901, 0x7901}, {0x7902, 0x7902}, + {0x7903, 0x7903}, {0x7904, 0x7904}, {0x7905, 0x7905}, {0x7906, 0x7906}, {0x7907, 0x7907}, {0x7908, 0x7908}, {0x7909, 0x7909}, + {0x790A, 0x790A}, {0x790B, 0x790B}, {0x790C, 0x790C}, {0x790D, 0x790D}, {0x790E, 0x790E}, {0x790F, 0x790F}, {0x7910, 0x7910}, + {0x7911, 0x7911}, {0x7912, 0x7912}, {0x7913, 0x7913}, {0x7914, 0x7914}, {0x7915, 0x7915}, {0x7916, 0x7916}, {0x7917, 0x7917}, + {0x7918, 0x7918}, {0x7919, 0x7919}, {0x791A, 0x791A}, {0x791B, 0x791B}, {0x791C, 0x791C}, {0x791D, 0x791D}, {0x791E, 0x791E}, + {0x791F, 0x791F}, {0x7920, 0x7920}, {0x7921, 0x7921}, {0x7922, 0x7922}, {0x7923, 0x7923}, {0x7924, 0x7924}, {0x7925, 0x7925}, + {0x7926, 0x7926}, {0x7927, 0x7927}, {0x7928, 0x7928}, {0x7929, 0x7929}, {0x792A, 0x792A}, {0x792B, 0x792B}, {0x792C, 0x792C}, + {0x792D, 0x792D}, {0x792E, 0x792E}, {0x792F, 0x792F}, {0x7930, 0x7930}, {0x7931, 0x7931}, {0x7932, 0x7932}, {0x7933, 0x7933}, + {0x7934, 0x7934}, {0x7935, 0x7935}, {0x7936, 0x7936}, {0x7937, 0x7937}, {0x7938, 0x7938}, {0x7939, 0x7939}, {0x793A, 0x793A}, + {0x793B, 0x793B}, {0x793C, 0x793C}, {0x793D, 0x793D}, {0x793E, 0x793E}, {0x793F, 0x793F}, {0x7940, 0x7940}, {0x7941, 0x7941}, + {0x7942, 0x7942}, {0x7943, 0x7943}, {0x7944, 0x7944}, {0x7945, 0x7945}, {0x7946, 0x7946}, {0x7947, 0x7947}, {0x7948, 0x7948}, + {0x7949, 0x7949}, {0x794A, 0x794A}, {0x794B, 0x794B}, {0x794C, 0x794C}, {0x794D, 0x794D}, {0x794E, 0x794E}, {0x794F, 0x794F}, + {0x7950, 0x7950}, {0x7951, 0x7951}, {0x7952, 0x7952}, {0x7953, 0x7953}, {0x7954, 0x7954}, {0x7955, 0x7955}, {0x7956, 0x7956}, + {0x7957, 0x7957}, {0x7958, 0x7958}, {0x7959, 0x7959}, {0x795A, 0x795A}, {0x795B, 0x795B}, {0x795C, 0x795C}, {0x795D, 0x795D}, + {0x795E, 0x795E}, {0x795F, 0x795F}, {0x7960, 0x7960}, {0x7961, 0x7961}, {0x7962, 0x7962}, {0x7963, 0x7963}, {0x7964, 0x7964}, + {0x7965, 0x7965}, {0x7966, 0x7966}, {0x7967, 0x7967}, {0x7968, 0x7968}, {0x7969, 0x7969}, {0x796A, 0x796A}, {0x796B, 0x796B}, + {0x796C, 0x796C}, {0x796D, 0x796D}, {0x796E, 0x796E}, {0x796F, 0x796F}, {0x7970, 0x7970}, {0x7971, 0x7971}, {0x7972, 0x7972}, + {0x7973, 0x7973}, {0x7974, 0x7974}, {0x7975, 0x7975}, {0x7976, 0x7976}, {0x7977, 0x7977}, {0x7978, 0x7978}, {0x7979, 0x7979}, + {0x797A, 0x797A}, {0x797B, 0x797B}, {0x797C, 0x797C}, {0x797D, 0x797D}, {0x797E, 0x797E}, {0x797F, 0x797F}, {0x7980, 0x7980}, + {0x7981, 0x7981}, {0x7982, 0x7982}, {0x7983, 0x7983}, {0x7984, 0x7984}, {0x7985, 0x7985}, {0x7986, 0x7986}, {0x7987, 0x7987}, + {0x7988, 0x7988}, {0x7989, 0x7989}, {0x798A, 0x798A}, {0x798B, 0x798B}, {0x798C, 0x798C}, {0x798D, 0x798D}, {0x798E, 0x798E}, + {0x798F, 0x798F}, {0x7990, 0x7990}, {0x7991, 0x7991}, {0x7992, 0x7992}, {0x7993, 0x7993}, {0x7994, 0x7994}, {0x7995, 0x7995}, + {0x7996, 0x7996}, {0x7997, 0x7997}, {0x7998, 0x7998}, {0x7999, 0x7999}, {0x799A, 0x799A}, {0x799B, 0x799B}, {0x799C, 0x799C}, + {0x799D, 0x799D}, {0x799E, 0x799E}, {0x799F, 0x799F}, {0x79A0, 0x79A0}, {0x79A1, 0x79A1}, {0x79A2, 0x79A2}, {0x79A3, 0x79A3}, + {0x79A4, 0x79A4}, {0x79A5, 0x79A5}, {0x79A6, 0x79A6}, {0x79A7, 0x79A7}, {0x79A8, 0x79A8}, {0x79A9, 0x79A9}, {0x79AA, 0x79AA}, + {0x79AB, 0x79AB}, {0x79AC, 0x79AC}, {0x79AD, 0x79AD}, {0x79AE, 0x79AE}, {0x79AF, 0x79AF}, {0x79B0, 0x79B0}, {0x79B1, 0x79B1}, + {0x79B2, 0x79B2}, {0x79B3, 0x79B3}, {0x79B4, 0x79B4}, {0x79B5, 0x79B5}, {0x79B6, 0x79B6}, {0x79B7, 0x79B7}, {0x79B8, 0x79B8}, + {0x79B9, 0x79B9}, {0x79BA, 0x79BA}, {0x79BB, 0x79BB}, {0x79BC, 0x79BC}, {0x79BD, 0x79BD}, {0x79BE, 0x79BE}, {0x79BF, 0x79BF}, + {0x79C0, 0x79C0}, {0x79C1, 0x79C1}, {0x79C2, 0x79C2}, {0x79C3, 0x79C3}, {0x79C4, 0x79C4}, {0x79C5, 0x79C5}, {0x79C6, 0x79C6}, + {0x79C7, 0x79C7}, {0x79C8, 0x79C8}, {0x79C9, 0x79C9}, {0x79CA, 0x79CA}, {0x79CB, 0x79CB}, {0x79CC, 0x79CC}, {0x79CD, 0x79CD}, + {0x79CE, 0x79CE}, {0x79CF, 0x79CF}, {0x79D0, 0x79D0}, {0x79D1, 0x79D1}, {0x79D2, 0x79D2}, {0x79D3, 0x79D3}, {0x79D4, 0x79D4}, + {0x79D5, 0x79D5}, {0x79D6, 0x79D6}, {0x79D7, 0x79D7}, {0x79D8, 0x79D8}, {0x79D9, 0x79D9}, {0x79DA, 0x79DA}, {0x79DB, 0x79DB}, + {0x79DC, 0x79DC}, {0x79DD, 0x79DD}, {0x79DE, 0x79DE}, {0x79DF, 0x79DF}, {0x79E0, 0x79E0}, {0x79E1, 0x79E1}, {0x79E2, 0x79E2}, + {0x79E3, 0x79E3}, {0x79E4, 0x79E4}, {0x79E5, 0x79E5}, {0x79E6, 0x79E6}, {0x79E7, 0x79E7}, {0x79E8, 0x79E8}, {0x79E9, 0x79E9}, + {0x79EA, 0x79EA}, {0x79EB, 0x79EB}, {0x79EC, 0x79EC}, {0x79ED, 0x79ED}, {0x79EE, 0x79EE}, {0x79EF, 0x79EF}, {0x79F0, 0x79F0}, + {0x79F1, 0x79F1}, {0x79F2, 0x79F2}, {0x79F3, 0x79F3}, {0x79F4, 0x79F4}, {0x79F5, 0x79F5}, {0x79F6, 0x79F6}, {0x79F7, 0x79F7}, + {0x79F8, 0x79F8}, {0x79F9, 0x79F9}, {0x79FA, 0x79FA}, {0x79FB, 0x79FB}, {0x79FC, 0x79FC}, {0x79FD, 0x79FD}, {0x79FE, 0x79FE}, + {0x79FF, 0x79FF}, {0x7A00, 0x7A00}, {0x7A01, 0x7A01}, {0x7A02, 0x7A02}, {0x7A03, 0x7A03}, {0x7A04, 0x7A04}, {0x7A05, 0x7A05}, + {0x7A06, 0x7A06}, {0x7A07, 0x7A07}, {0x7A08, 0x7A08}, {0x7A09, 0x7A09}, {0x7A0A, 0x7A0A}, {0x7A0B, 0x7A0B}, {0x7A0C, 0x7A0C}, + {0x7A0D, 0x7A0D}, {0x7A0E, 0x7A0E}, {0x7A0F, 0x7A0F}, {0x7A10, 0x7A10}, {0x7A11, 0x7A11}, {0x7A12, 0x7A12}, {0x7A13, 0x7A13}, + {0x7A14, 0x7A14}, {0x7A15, 0x7A15}, {0x7A16, 0x7A16}, {0x7A17, 0x7A17}, {0x7A18, 0x7A18}, {0x7A19, 0x7A19}, {0x7A1A, 0x7A1A}, + {0x7A1B, 0x7A1B}, {0x7A1C, 0x7A1C}, {0x7A1D, 0x7A1D}, {0x7A1E, 0x7A1E}, {0x7A1F, 0x7A1F}, {0x7A20, 0x7A20}, {0x7A21, 0x7A21}, + {0x7A22, 0x7A22}, {0x7A23, 0x7A23}, {0x7A24, 0x7A24}, {0x7A25, 0x7A25}, {0x7A26, 0x7A26}, {0x7A27, 0x7A27}, {0x7A28, 0x7A28}, + {0x7A29, 0x7A29}, {0x7A2A, 0x7A2A}, {0x7A2B, 0x7A2B}, {0x7A2C, 0x7A2C}, {0x7A2D, 0x7A2D}, {0x7A2E, 0x7A2E}, {0x7A2F, 0x7A2F}, + {0x7A30, 0x7A30}, {0x7A31, 0x7A31}, {0x7A32, 0x7A32}, {0x7A33, 0x7A33}, {0x7A34, 0x7A34}, {0x7A35, 0x7A35}, {0x7A36, 0x7A36}, + {0x7A37, 0x7A37}, {0x7A38, 0x7A38}, {0x7A39, 0x7A39}, {0x7A3A, 0x7A3A}, {0x7A3B, 0x7A3B}, {0x7A3C, 0x7A3C}, {0x7A3D, 0x7A3D}, + {0x7A3E, 0x7A3E}, {0x7A3F, 0x7A3F}, {0x7A40, 0x7A40}, {0x7A41, 0x7A41}, {0x7A42, 0x7A42}, {0x7A43, 0x7A43}, {0x7A44, 0x7A44}, + {0x7A45, 0x7A45}, {0x7A46, 0x7A46}, {0x7A47, 0x7A47}, {0x7A48, 0x7A48}, {0x7A49, 0x7A49}, {0x7A4A, 0x7A4A}, {0x7A4B, 0x7A4B}, + {0x7A4C, 0x7A4C}, {0x7A4D, 0x7A4D}, {0x7A4E, 0x7A4E}, {0x7A4F, 0x7A4F}, {0x7A50, 0x7A50}, {0x7A51, 0x7A51}, {0x7A52, 0x7A52}, + {0x7A53, 0x7A53}, {0x7A54, 0x7A54}, {0x7A55, 0x7A55}, {0x7A56, 0x7A56}, {0x7A57, 0x7A57}, {0x7A58, 0x7A58}, {0x7A59, 0x7A59}, + {0x7A5A, 0x7A5A}, {0x7A5B, 0x7A5B}, {0x7A5C, 0x7A5C}, {0x7A5D, 0x7A5D}, {0x7A5E, 0x7A5E}, {0x7A5F, 0x7A5F}, {0x7A60, 0x7A60}, + {0x7A61, 0x7A61}, {0x7A62, 0x7A62}, {0x7A63, 0x7A63}, {0x7A64, 0x7A64}, {0x7A65, 0x7A65}, {0x7A66, 0x7A66}, {0x7A67, 0x7A67}, + {0x7A68, 0x7A68}, {0x7A69, 0x7A69}, {0x7A6A, 0x7A6A}, {0x7A6B, 0x7A6B}, {0x7A6C, 0x7A6C}, {0x7A6D, 0x7A6D}, {0x7A6E, 0x7A6E}, + {0x7A6F, 0x7A6F}, {0x7A70, 0x7A70}, {0x7A71, 0x7A71}, {0x7A72, 0x7A72}, {0x7A73, 0x7A73}, {0x7A74, 0x7A74}, {0x7A75, 0x7A75}, + {0x7A76, 0x7A76}, {0x7A77, 0x7A77}, {0x7A78, 0x7A78}, {0x7A79, 0x7A79}, {0x7A7A, 0x7A7A}, {0x7A7B, 0x7A7B}, {0x7A7C, 0x7A7C}, + {0x7A7D, 0x7A7D}, {0x7A7E, 0x7A7E}, {0x7A7F, 0x7A7F}, {0x7A80, 0x7A80}, {0x7A81, 0x7A81}, {0x7A82, 0x7A82}, {0x7A83, 0x7A83}, + {0x7A84, 0x7A84}, {0x7A85, 0x7A85}, {0x7A86, 0x7A86}, {0x7A87, 0x7A87}, {0x7A88, 0x7A88}, {0x7A89, 0x7A89}, {0x7A8A, 0x7A8A}, + {0x7A8B, 0x7A8B}, {0x7A8C, 0x7A8C}, {0x7A8D, 0x7A8D}, {0x7A8E, 0x7A8E}, {0x7A8F, 0x7A8F}, {0x7A90, 0x7A90}, {0x7A91, 0x7A91}, + {0x7A92, 0x7A92}, {0x7A93, 0x7A93}, {0x7A94, 0x7A94}, {0x7A95, 0x7A95}, {0x7A96, 0x7A96}, {0x7A97, 0x7A97}, {0x7A98, 0x7A98}, + {0x7A99, 0x7A99}, {0x7A9A, 0x7A9A}, {0x7A9B, 0x7A9B}, {0x7A9C, 0x7A9C}, {0x7A9D, 0x7A9D}, {0x7A9E, 0x7A9E}, {0x7A9F, 0x7A9F}, + {0x7AA0, 0x7AA0}, {0x7AA1, 0x7AA1}, {0x7AA2, 0x7AA2}, {0x7AA3, 0x7AA3}, {0x7AA4, 0x7AA4}, {0x7AA5, 0x7AA5}, {0x7AA6, 0x7AA6}, + {0x7AA7, 0x7AA7}, {0x7AA8, 0x7AA8}, {0x7AA9, 0x7AA9}, {0x7AAA, 0x7AAA}, {0x7AAB, 0x7AAB}, {0x7AAC, 0x7AAC}, {0x7AAD, 0x7AAD}, + {0x7AAE, 0x7AAE}, {0x7AAF, 0x7AAF}, {0x7AB0, 0x7AB0}, {0x7AB1, 0x7AB1}, {0x7AB2, 0x7AB2}, {0x7AB3, 0x7AB3}, {0x7AB4, 0x7AB4}, + {0x7AB5, 0x7AB5}, {0x7AB6, 0x7AB6}, {0x7AB7, 0x7AB7}, {0x7AB8, 0x7AB8}, {0x7AB9, 0x7AB9}, {0x7ABA, 0x7ABA}, {0x7ABB, 0x7ABB}, + {0x7ABC, 0x7ABC}, {0x7ABD, 0x7ABD}, {0x7ABE, 0x7ABE}, {0x7ABF, 0x7ABF}, {0x7AC0, 0x7AC0}, {0x7AC1, 0x7AC1}, {0x7AC2, 0x7AC2}, + {0x7AC3, 0x7AC3}, {0x7AC4, 0x7AC4}, {0x7AC5, 0x7AC5}, {0x7AC6, 0x7AC6}, {0x7AC7, 0x7AC7}, {0x7AC8, 0x7AC8}, {0x7AC9, 0x7AC9}, + {0x7ACA, 0x7ACA}, {0x7ACB, 0x7ACB}, {0x7ACC, 0x7ACC}, {0x7ACD, 0x7ACD}, {0x7ACE, 0x7ACE}, {0x7ACF, 0x7ACF}, {0x7AD0, 0x7AD0}, + {0x7AD1, 0x7AD1}, {0x7AD2, 0x7AD2}, {0x7AD3, 0x7AD3}, {0x7AD4, 0x7AD4}, {0x7AD5, 0x7AD5}, {0x7AD6, 0x7AD6}, {0x7AD7, 0x7AD7}, + {0x7AD8, 0x7AD8}, {0x7AD9, 0x7AD9}, {0x7ADA, 0x7ADA}, {0x7ADB, 0x7ADB}, {0x7ADC, 0x7ADC}, {0x7ADD, 0x7ADD}, {0x7ADE, 0x7ADE}, + {0x7ADF, 0x7ADF}, {0x7AE0, 0x7AE0}, {0x7AE1, 0x7AE1}, {0x7AE2, 0x7AE2}, {0x7AE3, 0x7AE3}, {0x7AE4, 0x7AE4}, {0x7AE5, 0x7AE5}, + {0x7AE6, 0x7AE6}, {0x7AE7, 0x7AE7}, {0x7AE8, 0x7AE8}, {0x7AE9, 0x7AE9}, {0x7AEA, 0x7AEA}, {0x7AEB, 0x7AEB}, {0x7AEC, 0x7AEC}, + {0x7AED, 0x7AED}, {0x7AEE, 0x7AEE}, {0x7AEF, 0x7AEF}, {0x7AF0, 0x7AF0}, {0x7AF1, 0x7AF1}, {0x7AF2, 0x7AF2}, {0x7AF3, 0x7AF3}, + {0x7AF4, 0x7AF4}, {0x7AF5, 0x7AF5}, {0x7AF6, 0x7AF6}, {0x7AF7, 0x7AF7}, {0x7AF8, 0x7AF8}, {0x7AF9, 0x7AF9}, {0x7AFA, 0x7AFA}, + {0x7AFB, 0x7AFB}, {0x7AFC, 0x7AFC}, {0x7AFD, 0x7AFD}, {0x7AFE, 0x7AFE}, {0x7AFF, 0x7AFF}, {0x7B00, 0x7B00}, {0x7B01, 0x7B01}, + {0x7B02, 0x7B02}, {0x7B03, 0x7B03}, {0x7B04, 0x7B04}, {0x7B05, 0x7B05}, {0x7B06, 0x7B06}, {0x7B07, 0x7B07}, {0x7B08, 0x7B08}, + {0x7B09, 0x7B09}, {0x7B0A, 0x7B0A}, {0x7B0B, 0x7B0B}, {0x7B0C, 0x7B0C}, {0x7B0D, 0x7B0D}, {0x7B0E, 0x7B0E}, {0x7B0F, 0x7B0F}, + {0x7B10, 0x7B10}, {0x7B11, 0x7B11}, {0x7B12, 0x7B12}, {0x7B13, 0x7B13}, {0x7B14, 0x7B14}, {0x7B15, 0x7B15}, {0x7B16, 0x7B16}, + {0x7B17, 0x7B17}, {0x7B18, 0x7B18}, {0x7B19, 0x7B19}, {0x7B1A, 0x7B1A}, {0x7B1B, 0x7B1B}, {0x7B1C, 0x7B1C}, {0x7B1D, 0x7B1D}, + {0x7B1E, 0x7B1E}, {0x7B1F, 0x7B1F}, {0x7B20, 0x7B20}, {0x7B21, 0x7B21}, {0x7B22, 0x7B22}, {0x7B23, 0x7B23}, {0x7B24, 0x7B24}, + {0x7B25, 0x7B25}, {0x7B26, 0x7B26}, {0x7B27, 0x7B27}, {0x7B28, 0x7B28}, {0x7B29, 0x7B29}, {0x7B2A, 0x7B2A}, {0x7B2B, 0x7B2B}, + {0x7B2C, 0x7B2C}, {0x7B2D, 0x7B2D}, {0x7B2E, 0x7B2E}, {0x7B2F, 0x7B2F}, {0x7B30, 0x7B30}, {0x7B31, 0x7B31}, {0x7B32, 0x7B32}, + {0x7B33, 0x7B33}, {0x7B34, 0x7B34}, {0x7B35, 0x7B35}, {0x7B36, 0x7B36}, {0x7B37, 0x7B37}, {0x7B38, 0x7B38}, {0x7B39, 0x7B39}, + {0x7B3A, 0x7B3A}, {0x7B3B, 0x7B3B}, {0x7B3C, 0x7B3C}, {0x7B3D, 0x7B3D}, {0x7B3E, 0x7B3E}, {0x7B3F, 0x7B3F}, {0x7B40, 0x7B40}, + {0x7B41, 0x7B41}, {0x7B42, 0x7B42}, {0x7B43, 0x7B43}, {0x7B44, 0x7B44}, {0x7B45, 0x7B45}, {0x7B46, 0x7B46}, {0x7B47, 0x7B47}, + {0x7B48, 0x7B48}, {0x7B49, 0x7B49}, {0x7B4A, 0x7B4A}, {0x7B4B, 0x7B4B}, {0x7B4C, 0x7B4C}, {0x7B4D, 0x7B4D}, {0x7B4E, 0x7B4E}, + {0x7B4F, 0x7B4F}, {0x7B50, 0x7B50}, {0x7B51, 0x7B51}, {0x7B52, 0x7B52}, {0x7B53, 0x7B53}, {0x7B54, 0x7B54}, {0x7B55, 0x7B55}, + {0x7B56, 0x7B56}, {0x7B57, 0x7B57}, {0x7B58, 0x7B58}, {0x7B59, 0x7B59}, {0x7B5A, 0x7B5A}, {0x7B5B, 0x7B5B}, {0x7B5C, 0x7B5C}, + {0x7B5D, 0x7B5D}, {0x7B5E, 0x7B5E}, {0x7B5F, 0x7B5F}, {0x7B60, 0x7B60}, {0x7B61, 0x7B61}, {0x7B62, 0x7B62}, {0x7B63, 0x7B63}, + {0x7B64, 0x7B64}, {0x7B65, 0x7B65}, {0x7B66, 0x7B66}, {0x7B67, 0x7B67}, {0x7B68, 0x7B68}, {0x7B69, 0x7B69}, {0x7B6A, 0x7B6A}, + {0x7B6B, 0x7B6B}, {0x7B6C, 0x7B6C}, {0x7B6D, 0x7B6D}, {0x7B6E, 0x7B6E}, {0x7B6F, 0x7B6F}, {0x7B70, 0x7B70}, {0x7B71, 0x7B71}, + {0x7B72, 0x7B72}, {0x7B73, 0x7B73}, {0x7B74, 0x7B74}, {0x7B75, 0x7B75}, {0x7B76, 0x7B76}, {0x7B77, 0x7B77}, {0x7B78, 0x7B78}, + {0x7B79, 0x7B79}, {0x7B7A, 0x7B7A}, {0x7B7B, 0x7B7B}, {0x7B7C, 0x7B7C}, {0x7B7D, 0x7B7D}, {0x7B7E, 0x7B7E}, {0x7B7F, 0x7B7F}, + {0x7B80, 0x7B80}, {0x7B81, 0x7B81}, {0x7B82, 0x7B82}, {0x7B83, 0x7B83}, {0x7B84, 0x7B84}, {0x7B85, 0x7B85}, {0x7B86, 0x7B86}, + {0x7B87, 0x7B87}, {0x7B88, 0x7B88}, {0x7B89, 0x7B89}, {0x7B8A, 0x7B8A}, {0x7B8B, 0x7B8B}, {0x7B8C, 0x7B8C}, {0x7B8D, 0x7B8D}, + {0x7B8E, 0x7B8E}, {0x7B8F, 0x7B8F}, {0x7B90, 0x7B90}, {0x7B91, 0x7B91}, {0x7B92, 0x7B92}, {0x7B93, 0x7B93}, {0x7B94, 0x7B94}, + {0x7B95, 0x7B95}, {0x7B96, 0x7B96}, {0x7B97, 0x7B97}, {0x7B98, 0x7B98}, {0x7B99, 0x7B99}, {0x7B9A, 0x7B9A}, {0x7B9B, 0x7B9B}, + {0x7B9C, 0x7B9C}, {0x7B9D, 0x7B9D}, {0x7B9E, 0x7B9E}, {0x7B9F, 0x7B9F}, {0x7BA0, 0x7BA0}, {0x7BA1, 0x7BA1}, {0x7BA2, 0x7BA2}, + {0x7BA3, 0x7BA3}, {0x7BA4, 0x7BA4}, {0x7BA5, 0x7BA5}, {0x7BA6, 0x7BA6}, {0x7BA7, 0x7BA7}, {0x7BA8, 0x7BA8}, {0x7BA9, 0x7BA9}, + {0x7BAA, 0x7BAA}, {0x7BAB, 0x7BAB}, {0x7BAC, 0x7BAC}, {0x7BAD, 0x7BAD}, {0x7BAE, 0x7BAE}, {0x7BAF, 0x7BAF}, {0x7BB0, 0x7BB0}, + {0x7BB1, 0x7BB1}, {0x7BB2, 0x7BB2}, {0x7BB3, 0x7BB3}, {0x7BB4, 0x7BB4}, {0x7BB5, 0x7BB5}, {0x7BB6, 0x7BB6}, {0x7BB7, 0x7BB7}, + {0x7BB8, 0x7BB8}, {0x7BB9, 0x7BB9}, {0x7BBA, 0x7BBA}, {0x7BBB, 0x7BBB}, {0x7BBC, 0x7BBC}, {0x7BBD, 0x7BBD}, {0x7BBE, 0x7BBE}, + {0x7BBF, 0x7BBF}, {0x7BC0, 0x7BC0}, {0x7BC1, 0x7BC1}, {0x7BC2, 0x7BC2}, {0x7BC3, 0x7BC3}, {0x7BC4, 0x7BC4}, {0x7BC5, 0x7BC5}, + {0x7BC6, 0x7BC6}, {0x7BC7, 0x7BC7}, {0x7BC8, 0x7BC8}, {0x7BC9, 0x7BC9}, {0x7BCA, 0x7BCA}, {0x7BCB, 0x7BCB}, {0x7BCC, 0x7BCC}, + {0x7BCD, 0x7BCD}, {0x7BCE, 0x7BCE}, {0x7BCF, 0x7BCF}, {0x7BD0, 0x7BD0}, {0x7BD1, 0x7BD1}, {0x7BD2, 0x7BD2}, {0x7BD3, 0x7BD3}, + {0x7BD4, 0x7BD4}, {0x7BD5, 0x7BD5}, {0x7BD6, 0x7BD6}, {0x7BD7, 0x7BD7}, {0x7BD8, 0x7BD8}, {0x7BD9, 0x7BD9}, {0x7BDA, 0x7BDA}, + {0x7BDB, 0x7BDB}, {0x7BDC, 0x7BDC}, {0x7BDD, 0x7BDD}, {0x7BDE, 0x7BDE}, {0x7BDF, 0x7BDF}, {0x7BE0, 0x7BE0}, {0x7BE1, 0x7BE1}, + {0x7BE2, 0x7BE2}, {0x7BE3, 0x7BE3}, {0x7BE4, 0x7BE4}, {0x7BE5, 0x7BE5}, {0x7BE6, 0x7BE6}, {0x7BE7, 0x7BE7}, {0x7BE8, 0x7BE8}, + {0x7BE9, 0x7BE9}, {0x7BEA, 0x7BEA}, {0x7BEB, 0x7BEB}, {0x7BEC, 0x7BEC}, {0x7BED, 0x7BED}, {0x7BEE, 0x7BEE}, {0x7BEF, 0x7BEF}, + {0x7BF0, 0x7BF0}, {0x7BF1, 0x7BF1}, {0x7BF2, 0x7BF2}, {0x7BF3, 0x7BF3}, {0x7BF4, 0x7BF4}, {0x7BF5, 0x7BF5}, {0x7BF6, 0x7BF6}, + {0x7BF7, 0x7BF7}, {0x7BF8, 0x7BF8}, {0x7BF9, 0x7BF9}, {0x7BFA, 0x7BFA}, {0x7BFB, 0x7BFB}, {0x7BFC, 0x7BFC}, {0x7BFD, 0x7BFD}, + {0x7BFE, 0x7BFE}, {0x7BFF, 0x7BFF}, {0x7C00, 0x7C00}, {0x7C01, 0x7C01}, {0x7C02, 0x7C02}, {0x7C03, 0x7C03}, {0x7C04, 0x7C04}, + {0x7C05, 0x7C05}, {0x7C06, 0x7C06}, {0x7C07, 0x7C07}, {0x7C08, 0x7C08}, {0x7C09, 0x7C09}, {0x7C0A, 0x7C0A}, {0x7C0B, 0x7C0B}, + {0x7C0C, 0x7C0C}, {0x7C0D, 0x7C0D}, {0x7C0E, 0x7C0E}, {0x7C0F, 0x7C0F}, {0x7C10, 0x7C10}, {0x7C11, 0x7C11}, {0x7C12, 0x7C12}, + {0x7C13, 0x7C13}, {0x7C14, 0x7C14}, {0x7C15, 0x7C15}, {0x7C16, 0x7C16}, {0x7C17, 0x7C17}, {0x7C18, 0x7C18}, {0x7C19, 0x7C19}, + {0x7C1A, 0x7C1A}, {0x7C1B, 0x7C1B}, {0x7C1C, 0x7C1C}, {0x7C1D, 0x7C1D}, {0x7C1E, 0x7C1E}, {0x7C1F, 0x7C1F}, {0x7C20, 0x7C20}, + {0x7C21, 0x7C21}, {0x7C22, 0x7C22}, {0x7C23, 0x7C23}, {0x7C24, 0x7C24}, {0x7C25, 0x7C25}, {0x7C26, 0x7C26}, {0x7C27, 0x7C27}, + {0x7C28, 0x7C28}, {0x7C29, 0x7C29}, {0x7C2A, 0x7C2A}, {0x7C2B, 0x7C2B}, {0x7C2C, 0x7C2C}, {0x7C2D, 0x7C2D}, {0x7C2E, 0x7C2E}, + {0x7C2F, 0x7C2F}, {0x7C30, 0x7C30}, {0x7C31, 0x7C31}, {0x7C32, 0x7C32}, {0x7C33, 0x7C33}, {0x7C34, 0x7C34}, {0x7C35, 0x7C35}, + {0x7C36, 0x7C36}, {0x7C37, 0x7C37}, {0x7C38, 0x7C38}, {0x7C39, 0x7C39}, {0x7C3A, 0x7C3A}, {0x7C3B, 0x7C3B}, {0x7C3C, 0x7C3C}, + {0x7C3D, 0x7C3D}, {0x7C3E, 0x7C3E}, {0x7C3F, 0x7C3F}, {0x7C40, 0x7C40}, {0x7C41, 0x7C41}, {0x7C42, 0x7C42}, {0x7C43, 0x7C43}, + {0x7C44, 0x7C44}, {0x7C45, 0x7C45}, {0x7C46, 0x7C46}, {0x7C47, 0x7C47}, {0x7C48, 0x7C48}, {0x7C49, 0x7C49}, {0x7C4A, 0x7C4A}, + {0x7C4B, 0x7C4B}, {0x7C4C, 0x7C4C}, {0x7C4D, 0x7C4D}, {0x7C4E, 0x7C4E}, {0x7C4F, 0x7C4F}, {0x7C50, 0x7C50}, {0x7C51, 0x7C51}, + {0x7C52, 0x7C52}, {0x7C53, 0x7C53}, {0x7C54, 0x7C54}, {0x7C55, 0x7C55}, {0x7C56, 0x7C56}, {0x7C57, 0x7C57}, {0x7C58, 0x7C58}, + {0x7C59, 0x7C59}, {0x7C5A, 0x7C5A}, {0x7C5B, 0x7C5B}, {0x7C5C, 0x7C5C}, {0x7C5D, 0x7C5D}, {0x7C5E, 0x7C5E}, {0x7C5F, 0x7C5F}, + {0x7C60, 0x7C60}, {0x7C61, 0x7C61}, {0x7C62, 0x7C62}, {0x7C63, 0x7C63}, {0x7C64, 0x7C64}, {0x7C65, 0x7C65}, {0x7C66, 0x7C66}, + {0x7C67, 0x7C67}, {0x7C68, 0x7C68}, {0x7C69, 0x7C69}, {0x7C6A, 0x7C6A}, {0x7C6B, 0x7C6B}, {0x7C6C, 0x7C6C}, {0x7C6D, 0x7C6D}, + {0x7C6E, 0x7C6E}, {0x7C6F, 0x7C6F}, {0x7C70, 0x7C70}, {0x7C71, 0x7C71}, {0x7C72, 0x7C72}, {0x7C73, 0x7C73}, {0x7C74, 0x7C74}, + {0x7C75, 0x7C75}, {0x7C76, 0x7C76}, {0x7C77, 0x7C77}, {0x7C78, 0x7C78}, {0x7C79, 0x7C79}, {0x7C7A, 0x7C7A}, {0x7C7B, 0x7C7B}, + {0x7C7C, 0x7C7C}, {0x7C7D, 0x7C7D}, {0x7C7E, 0x7C7E}, {0x7C7F, 0x7C7F}, {0x7C80, 0x7C80}, {0x7C81, 0x7C81}, {0x7C82, 0x7C82}, + {0x7C83, 0x7C83}, {0x7C84, 0x7C84}, {0x7C85, 0x7C85}, {0x7C86, 0x7C86}, {0x7C87, 0x7C87}, {0x7C88, 0x7C88}, {0x7C89, 0x7C89}, + {0x7C8A, 0x7C8A}, {0x7C8B, 0x7C8B}, {0x7C8C, 0x7C8C}, {0x7C8D, 0x7C8D}, {0x7C8E, 0x7C8E}, {0x7C8F, 0x7C8F}, {0x7C90, 0x7C90}, + {0x7C91, 0x7C91}, {0x7C92, 0x7C92}, {0x7C93, 0x7C93}, {0x7C94, 0x7C94}, {0x7C95, 0x7C95}, {0x7C96, 0x7C96}, {0x7C97, 0x7C97}, + {0x7C98, 0x7C98}, {0x7C99, 0x7C99}, {0x7C9A, 0x7C9A}, {0x7C9B, 0x7C9B}, {0x7C9C, 0x7C9C}, {0x7C9D, 0x7C9D}, {0x7C9E, 0x7C9E}, + {0x7C9F, 0x7C9F}, {0x7CA0, 0x7CA0}, {0x7CA1, 0x7CA1}, {0x7CA2, 0x7CA2}, {0x7CA3, 0x7CA3}, {0x7CA4, 0x7CA4}, {0x7CA5, 0x7CA5}, + {0x7CA6, 0x7CA6}, {0x7CA7, 0x7CA7}, {0x7CA8, 0x7CA8}, {0x7CA9, 0x7CA9}, {0x7CAA, 0x7CAA}, {0x7CAB, 0x7CAB}, {0x7CAC, 0x7CAC}, + {0x7CAD, 0x7CAD}, {0x7CAE, 0x7CAE}, {0x7CAF, 0x7CAF}, {0x7CB0, 0x7CB0}, {0x7CB1, 0x7CB1}, {0x7CB2, 0x7CB2}, {0x7CB3, 0x7CB3}, + {0x7CB4, 0x7CB4}, {0x7CB5, 0x7CB5}, {0x7CB6, 0x7CB6}, {0x7CB7, 0x7CB7}, {0x7CB8, 0x7CB8}, {0x7CB9, 0x7CB9}, {0x7CBA, 0x7CBA}, + {0x7CBB, 0x7CBB}, {0x7CBC, 0x7CBC}, {0x7CBD, 0x7CBD}, {0x7CBE, 0x7CBE}, {0x7CBF, 0x7CBF}, {0x7CC0, 0x7CC0}, {0x7CC1, 0x7CC1}, + {0x7CC2, 0x7CC2}, {0x7CC3, 0x7CC3}, {0x7CC4, 0x7CC4}, {0x7CC5, 0x7CC5}, {0x7CC6, 0x7CC6}, {0x7CC7, 0x7CC7}, {0x7CC8, 0x7CC8}, + {0x7CC9, 0x7CC9}, {0x7CCA, 0x7CCA}, {0x7CCB, 0x7CCB}, {0x7CCC, 0x7CCC}, {0x7CCD, 0x7CCD}, {0x7CCE, 0x7CCE}, {0x7CCF, 0x7CCF}, + {0x7CD0, 0x7CD0}, {0x7CD1, 0x7CD1}, {0x7CD2, 0x7CD2}, {0x7CD3, 0x7CD3}, {0x7CD4, 0x7CD4}, {0x7CD5, 0x7CD5}, {0x7CD6, 0x7CD6}, + {0x7CD7, 0x7CD7}, {0x7CD8, 0x7CD8}, {0x7CD9, 0x7CD9}, {0x7CDA, 0x7CDA}, {0x7CDB, 0x7CDB}, {0x7CDC, 0x7CDC}, {0x7CDD, 0x7CDD}, + {0x7CDE, 0x7CDE}, {0x7CDF, 0x7CDF}, {0x7CE0, 0x7CE0}, {0x7CE1, 0x7CE1}, {0x7CE2, 0x7CE2}, {0x7CE3, 0x7CE3}, {0x7CE4, 0x7CE4}, + {0x7CE5, 0x7CE5}, {0x7CE6, 0x7CE6}, {0x7CE7, 0x7CE7}, {0x7CE8, 0x7CE8}, {0x7CE9, 0x7CE9}, {0x7CEA, 0x7CEA}, {0x7CEB, 0x7CEB}, + {0x7CEC, 0x7CEC}, {0x7CED, 0x7CED}, {0x7CEE, 0x7CEE}, {0x7CEF, 0x7CEF}, {0x7CF0, 0x7CF0}, {0x7CF1, 0x7CF1}, {0x7CF2, 0x7CF2}, + {0x7CF3, 0x7CF3}, {0x7CF4, 0x7CF4}, {0x7CF5, 0x7CF5}, {0x7CF6, 0x7CF6}, {0x7CF7, 0x7CF7}, {0x7CF8, 0x7CF8}, {0x7CF9, 0x7CF9}, + {0x7CFA, 0x7CFA}, {0x7CFB, 0x7CFB}, {0x7CFC, 0x7CFC}, {0x7CFD, 0x7CFD}, {0x7CFE, 0x7CFE}, {0x7CFF, 0x7CFF}, {0x7D00, 0x7D00}, + {0x7D01, 0x7D01}, {0x7D02, 0x7D02}, {0x7D03, 0x7D03}, {0x7D04, 0x7D04}, {0x7D05, 0x7D05}, {0x7D06, 0x7D06}, {0x7D07, 0x7D07}, + {0x7D08, 0x7D08}, {0x7D09, 0x7D09}, {0x7D0A, 0x7D0A}, {0x7D0B, 0x7D0B}, {0x7D0C, 0x7D0C}, {0x7D0D, 0x7D0D}, {0x7D0E, 0x7D0E}, + {0x7D0F, 0x7D0F}, {0x7D10, 0x7D10}, {0x7D11, 0x7D11}, {0x7D12, 0x7D12}, {0x7D13, 0x7D13}, {0x7D14, 0x7D14}, {0x7D15, 0x7D15}, + {0x7D16, 0x7D16}, {0x7D17, 0x7D17}, {0x7D18, 0x7D18}, {0x7D19, 0x7D19}, {0x7D1A, 0x7D1A}, {0x7D1B, 0x7D1B}, {0x7D1C, 0x7D1C}, + {0x7D1D, 0x7D1D}, {0x7D1E, 0x7D1E}, {0x7D1F, 0x7D1F}, {0x7D20, 0x7D20}, {0x7D21, 0x7D21}, {0x7D22, 0x7D22}, {0x7D23, 0x7D23}, + {0x7D24, 0x7D24}, {0x7D25, 0x7D25}, {0x7D26, 0x7D26}, {0x7D27, 0x7D27}, {0x7D28, 0x7D28}, {0x7D29, 0x7D29}, {0x7D2A, 0x7D2A}, + {0x7D2B, 0x7D2B}, {0x7D2C, 0x7D2C}, {0x7D2D, 0x7D2D}, {0x7D2E, 0x7D2E}, {0x7D2F, 0x7D2F}, {0x7D30, 0x7D30}, {0x7D31, 0x7D31}, + {0x7D32, 0x7D32}, {0x7D33, 0x7D33}, {0x7D34, 0x7D34}, {0x7D35, 0x7D35}, {0x7D36, 0x7D36}, {0x7D37, 0x7D37}, {0x7D38, 0x7D38}, + {0x7D39, 0x7D39}, {0x7D3A, 0x7D3A}, {0x7D3B, 0x7D3B}, {0x7D3C, 0x7D3C}, {0x7D3D, 0x7D3D}, {0x7D3E, 0x7D3E}, {0x7D3F, 0x7D3F}, + {0x7D40, 0x7D40}, {0x7D41, 0x7D41}, {0x7D42, 0x7D42}, {0x7D43, 0x7D43}, {0x7D44, 0x7D44}, {0x7D45, 0x7D45}, {0x7D46, 0x7D46}, + {0x7D47, 0x7D47}, {0x7D48, 0x7D48}, {0x7D49, 0x7D49}, {0x7D4A, 0x7D4A}, {0x7D4B, 0x7D4B}, {0x7D4C, 0x7D4C}, {0x7D4D, 0x7D4D}, + {0x7D4E, 0x7D4E}, {0x7D4F, 0x7D4F}, {0x7D50, 0x7D50}, {0x7D51, 0x7D51}, {0x7D52, 0x7D52}, {0x7D53, 0x7D53}, {0x7D54, 0x7D54}, + {0x7D55, 0x7D55}, {0x7D56, 0x7D56}, {0x7D57, 0x7D57}, {0x7D58, 0x7D58}, {0x7D59, 0x7D59}, {0x7D5A, 0x7D5A}, {0x7D5B, 0x7D5B}, + {0x7D5C, 0x7D5C}, {0x7D5D, 0x7D5D}, {0x7D5E, 0x7D5E}, {0x7D5F, 0x7D5F}, {0x7D60, 0x7D60}, {0x7D61, 0x7D61}, {0x7D62, 0x7D62}, + {0x7D63, 0x7D63}, {0x7D64, 0x7D64}, {0x7D65, 0x7D65}, {0x7D66, 0x7D66}, {0x7D67, 0x7D67}, {0x7D68, 0x7D68}, {0x7D69, 0x7D69}, + {0x7D6A, 0x7D6A}, {0x7D6B, 0x7D6B}, {0x7D6C, 0x7D6C}, {0x7D6D, 0x7D6D}, {0x7D6E, 0x7D6E}, {0x7D6F, 0x7D6F}, {0x7D70, 0x7D70}, + {0x7D71, 0x7D71}, {0x7D72, 0x7D72}, {0x7D73, 0x7D73}, {0x7D74, 0x7D74}, {0x7D75, 0x7D75}, {0x7D76, 0x7D76}, {0x7D77, 0x7D77}, + {0x7D78, 0x7D78}, {0x7D79, 0x7D79}, {0x7D7A, 0x7D7A}, {0x7D7B, 0x7D7B}, {0x7D7C, 0x7D7C}, {0x7D7D, 0x7D7D}, {0x7D7E, 0x7D7E}, + {0x7D7F, 0x7D7F}, {0x7D80, 0x7D80}, {0x7D81, 0x7D81}, {0x7D82, 0x7D82}, {0x7D83, 0x7D83}, {0x7D84, 0x7D84}, {0x7D85, 0x7D85}, + {0x7D86, 0x7D86}, {0x7D87, 0x7D87}, {0x7D88, 0x7D88}, {0x7D89, 0x7D89}, {0x7D8A, 0x7D8A}, {0x7D8B, 0x7D8B}, {0x7D8C, 0x7D8C}, + {0x7D8D, 0x7D8D}, {0x7D8E, 0x7D8E}, {0x7D8F, 0x7D8F}, {0x7D90, 0x7D90}, {0x7D91, 0x7D91}, {0x7D92, 0x7D92}, {0x7D93, 0x7D93}, + {0x7D94, 0x7D94}, {0x7D95, 0x7D95}, {0x7D96, 0x7D96}, {0x7D97, 0x7D97}, {0x7D98, 0x7D98}, {0x7D99, 0x7D99}, {0x7D9A, 0x7D9A}, + {0x7D9B, 0x7D9B}, {0x7D9C, 0x7D9C}, {0x7D9D, 0x7D9D}, {0x7D9E, 0x7D9E}, {0x7D9F, 0x7D9F}, {0x7DA0, 0x7DA0}, {0x7DA1, 0x7DA1}, + {0x7DA2, 0x7DA2}, {0x7DA3, 0x7DA3}, {0x7DA4, 0x7DA4}, {0x7DA5, 0x7DA5}, {0x7DA6, 0x7DA6}, {0x7DA7, 0x7DA7}, {0x7DA8, 0x7DA8}, + {0x7DA9, 0x7DA9}, {0x7DAA, 0x7DAA}, {0x7DAB, 0x7DAB}, {0x7DAC, 0x7DAC}, {0x7DAD, 0x7DAD}, {0x7DAE, 0x7DAE}, {0x7DAF, 0x7DAF}, + {0x7DB0, 0x7DB0}, {0x7DB1, 0x7DB1}, {0x7DB2, 0x7DB2}, {0x7DB3, 0x7DB3}, {0x7DB4, 0x7DB4}, {0x7DB5, 0x7DB5}, {0x7DB6, 0x7DB6}, + {0x7DB7, 0x7DB7}, {0x7DB8, 0x7DB8}, {0x7DB9, 0x7DB9}, {0x7DBA, 0x7DBA}, {0x7DBB, 0x7DBB}, {0x7DBC, 0x7DBC}, {0x7DBD, 0x7DBD}, + {0x7DBE, 0x7DBE}, {0x7DBF, 0x7DBF}, {0x7DC0, 0x7DC0}, {0x7DC1, 0x7DC1}, {0x7DC2, 0x7DC2}, {0x7DC3, 0x7DC3}, {0x7DC4, 0x7DC4}, + {0x7DC5, 0x7DC5}, {0x7DC6, 0x7DC6}, {0x7DC7, 0x7DC7}, {0x7DC8, 0x7DC8}, {0x7DC9, 0x7DC9}, {0x7DCA, 0x7DCA}, {0x7DCB, 0x7DCB}, + {0x7DCC, 0x7DCC}, {0x7DCD, 0x7DCD}, {0x7DCE, 0x7DCE}, {0x7DCF, 0x7DCF}, {0x7DD0, 0x7DD0}, {0x7DD1, 0x7DD1}, {0x7DD2, 0x7DD2}, + {0x7DD3, 0x7DD3}, {0x7DD4, 0x7DD4}, {0x7DD5, 0x7DD5}, {0x7DD6, 0x7DD6}, {0x7DD7, 0x7DD7}, {0x7DD8, 0x7DD8}, {0x7DD9, 0x7DD9}, + {0x7DDA, 0x7DDA}, {0x7DDB, 0x7DDB}, {0x7DDC, 0x7DDC}, {0x7DDD, 0x7DDD}, {0x7DDE, 0x7DDE}, {0x7DDF, 0x7DDF}, {0x7DE0, 0x7DE0}, + {0x7DE1, 0x7DE1}, {0x7DE2, 0x7DE2}, {0x7DE3, 0x7DE3}, {0x7DE4, 0x7DE4}, {0x7DE5, 0x7DE5}, {0x7DE6, 0x7DE6}, {0x7DE7, 0x7DE7}, + {0x7DE8, 0x7DE8}, {0x7DE9, 0x7DE9}, {0x7DEA, 0x7DEA}, {0x7DEB, 0x7DEB}, {0x7DEC, 0x7DEC}, {0x7DED, 0x7DED}, {0x7DEE, 0x7DEE}, + {0x7DEF, 0x7DEF}, {0x7DF0, 0x7DF0}, {0x7DF1, 0x7DF1}, {0x7DF2, 0x7DF2}, {0x7DF3, 0x7DF3}, {0x7DF4, 0x7DF4}, {0x7DF5, 0x7DF5}, + {0x7DF6, 0x7DF6}, {0x7DF7, 0x7DF7}, {0x7DF8, 0x7DF8}, {0x7DF9, 0x7DF9}, {0x7DFA, 0x7DFA}, {0x7DFB, 0x7DFB}, {0x7DFC, 0x7DFC}, + {0x7DFD, 0x7DFD}, {0x7DFE, 0x7DFE}, {0x7DFF, 0x7DFF}, {0x7E00, 0x7E00}, {0x7E01, 0x7E01}, {0x7E02, 0x7E02}, {0x7E03, 0x7E03}, + {0x7E04, 0x7E04}, {0x7E05, 0x7E05}, {0x7E06, 0x7E06}, {0x7E07, 0x7E07}, {0x7E08, 0x7E08}, {0x7E09, 0x7E09}, {0x7E0A, 0x7E0A}, + {0x7E0B, 0x7E0B}, {0x7E0C, 0x7E0C}, {0x7E0D, 0x7E0D}, {0x7E0E, 0x7E0E}, {0x7E0F, 0x7E0F}, {0x7E10, 0x7E10}, {0x7E11, 0x7E11}, + {0x7E12, 0x7E12}, {0x7E13, 0x7E13}, {0x7E14, 0x7E14}, {0x7E15, 0x7E15}, {0x7E16, 0x7E16}, {0x7E17, 0x7E17}, {0x7E18, 0x7E18}, + {0x7E19, 0x7E19}, {0x7E1A, 0x7E1A}, {0x7E1B, 0x7E1B}, {0x7E1C, 0x7E1C}, {0x7E1D, 0x7E1D}, {0x7E1E, 0x7E1E}, {0x7E1F, 0x7E1F}, + {0x7E20, 0x7E20}, {0x7E21, 0x7E21}, {0x7E22, 0x7E22}, {0x7E23, 0x7E23}, {0x7E24, 0x7E24}, {0x7E25, 0x7E25}, {0x7E26, 0x7E26}, + {0x7E27, 0x7E27}, {0x7E28, 0x7E28}, {0x7E29, 0x7E29}, {0x7E2A, 0x7E2A}, {0x7E2B, 0x7E2B}, {0x7E2C, 0x7E2C}, {0x7E2D, 0x7E2D}, + {0x7E2E, 0x7E2E}, {0x7E2F, 0x7E2F}, {0x7E30, 0x7E30}, {0x7E31, 0x7E31}, {0x7E32, 0x7E32}, {0x7E33, 0x7E33}, {0x7E34, 0x7E34}, + {0x7E35, 0x7E35}, {0x7E36, 0x7E36}, {0x7E37, 0x7E37}, {0x7E38, 0x7E38}, {0x7E39, 0x7E39}, {0x7E3A, 0x7E3A}, {0x7E3B, 0x7E3B}, + {0x7E3C, 0x7E3C}, {0x7E3D, 0x7E3D}, {0x7E3E, 0x7E3E}, {0x7E3F, 0x7E3F}, {0x7E40, 0x7E40}, {0x7E41, 0x7E41}, {0x7E42, 0x7E42}, + {0x7E43, 0x7E43}, {0x7E44, 0x7E44}, {0x7E45, 0x7E45}, {0x7E46, 0x7E46}, {0x7E47, 0x7E47}, {0x7E48, 0x7E48}, {0x7E49, 0x7E49}, + {0x7E4A, 0x7E4A}, {0x7E4B, 0x7E4B}, {0x7E4C, 0x7E4C}, {0x7E4D, 0x7E4D}, {0x7E4E, 0x7E4E}, {0x7E4F, 0x7E4F}, {0x7E50, 0x7E50}, + {0x7E51, 0x7E51}, {0x7E52, 0x7E52}, {0x7E53, 0x7E53}, {0x7E54, 0x7E54}, {0x7E55, 0x7E55}, {0x7E56, 0x7E56}, {0x7E57, 0x7E57}, + {0x7E58, 0x7E58}, {0x7E59, 0x7E59}, {0x7E5A, 0x7E5A}, {0x7E5B, 0x7E5B}, {0x7E5C, 0x7E5C}, {0x7E5D, 0x7E5D}, {0x7E5E, 0x7E5E}, + {0x7E5F, 0x7E5F}, {0x7E60, 0x7E60}, {0x7E61, 0x7E61}, {0x7E62, 0x7E62}, {0x7E63, 0x7E63}, {0x7E64, 0x7E64}, {0x7E65, 0x7E65}, + {0x7E66, 0x7E66}, {0x7E67, 0x7E67}, {0x7E68, 0x7E68}, {0x7E69, 0x7E69}, {0x7E6A, 0x7E6A}, {0x7E6B, 0x7E6B}, {0x7E6C, 0x7E6C}, + {0x7E6D, 0x7E6D}, {0x7E6E, 0x7E6E}, {0x7E6F, 0x7E6F}, {0x7E70, 0x7E70}, {0x7E71, 0x7E71}, {0x7E72, 0x7E72}, {0x7E73, 0x7E73}, + {0x7E74, 0x7E74}, {0x7E75, 0x7E75}, {0x7E76, 0x7E76}, {0x7E77, 0x7E77}, {0x7E78, 0x7E78}, {0x7E79, 0x7E79}, {0x7E7A, 0x7E7A}, + {0x7E7B, 0x7E7B}, {0x7E7C, 0x7E7C}, {0x7E7D, 0x7E7D}, {0x7E7E, 0x7E7E}, {0x7E7F, 0x7E7F}, {0x7E80, 0x7E80}, {0x7E81, 0x7E81}, + {0x7E82, 0x7E82}, {0x7E83, 0x7E83}, {0x7E84, 0x7E84}, {0x7E85, 0x7E85}, {0x7E86, 0x7E86}, {0x7E87, 0x7E87}, {0x7E88, 0x7E88}, + {0x7E89, 0x7E89}, {0x7E8A, 0x7E8A}, {0x7E8B, 0x7E8B}, {0x7E8C, 0x7E8C}, {0x7E8D, 0x7E8D}, {0x7E8E, 0x7E8E}, {0x7E8F, 0x7E8F}, + {0x7E90, 0x7E90}, {0x7E91, 0x7E91}, {0x7E92, 0x7E92}, {0x7E93, 0x7E93}, {0x7E94, 0x7E94}, {0x7E95, 0x7E95}, {0x7E96, 0x7E96}, + {0x7E97, 0x7E97}, {0x7E98, 0x7E98}, {0x7E99, 0x7E99}, {0x7E9A, 0x7E9A}, {0x7E9B, 0x7E9B}, {0x7E9C, 0x7E9C}, {0x7E9D, 0x7E9D}, + {0x7E9E, 0x7E9E}, {0x7E9F, 0x7E9F}, {0x7EA0, 0x7EA0}, {0x7EA1, 0x7EA1}, {0x7EA2, 0x7EA2}, {0x7EA3, 0x7EA3}, {0x7EA4, 0x7EA4}, + {0x7EA5, 0x7EA5}, {0x7EA6, 0x7EA6}, {0x7EA7, 0x7EA7}, {0x7EA8, 0x7EA8}, {0x7EA9, 0x7EA9}, {0x7EAA, 0x7EAA}, {0x7EAB, 0x7EAB}, + {0x7EAC, 0x7EAC}, {0x7EAD, 0x7EAD}, {0x7EAE, 0x7EAE}, {0x7EAF, 0x7EAF}, {0x7EB0, 0x7EB0}, {0x7EB1, 0x7EB1}, {0x7EB2, 0x7EB2}, + {0x7EB3, 0x7EB3}, {0x7EB4, 0x7EB4}, {0x7EB5, 0x7EB5}, {0x7EB6, 0x7EB6}, {0x7EB7, 0x7EB7}, {0x7EB8, 0x7EB8}, {0x7EB9, 0x7EB9}, + {0x7EBA, 0x7EBA}, {0x7EBB, 0x7EBB}, {0x7EBC, 0x7EBC}, {0x7EBD, 0x7EBD}, {0x7EBE, 0x7EBE}, {0x7EBF, 0x7EBF}, {0x7EC0, 0x7EC0}, + {0x7EC1, 0x7EC1}, {0x7EC2, 0x7EC2}, {0x7EC3, 0x7EC3}, {0x7EC4, 0x7EC4}, {0x7EC5, 0x7EC5}, {0x7EC6, 0x7EC6}, {0x7EC7, 0x7EC7}, + {0x7EC8, 0x7EC8}, {0x7EC9, 0x7EC9}, {0x7ECA, 0x7ECA}, {0x7ECB, 0x7ECB}, {0x7ECC, 0x7ECC}, {0x7ECD, 0x7ECD}, {0x7ECE, 0x7ECE}, + {0x7ECF, 0x7ECF}, {0x7ED0, 0x7ED0}, {0x7ED1, 0x7ED1}, {0x7ED2, 0x7ED2}, {0x7ED3, 0x7ED3}, {0x7ED4, 0x7ED4}, {0x7ED5, 0x7ED5}, + {0x7ED6, 0x7ED6}, {0x7ED7, 0x7ED7}, {0x7ED8, 0x7ED8}, {0x7ED9, 0x7ED9}, {0x7EDA, 0x7EDA}, {0x7EDB, 0x7EDB}, {0x7EDC, 0x7EDC}, + {0x7EDD, 0x7EDD}, {0x7EDE, 0x7EDE}, {0x7EDF, 0x7EDF}, {0x7EE0, 0x7EE0}, {0x7EE1, 0x7EE1}, {0x7EE2, 0x7EE2}, {0x7EE3, 0x7EE3}, + {0x7EE4, 0x7EE4}, {0x7EE5, 0x7EE5}, {0x7EE6, 0x7EE6}, {0x7EE7, 0x7EE7}, {0x7EE8, 0x7EE8}, {0x7EE9, 0x7EE9}, {0x7EEA, 0x7EEA}, + {0x7EEB, 0x7EEB}, {0x7EEC, 0x7EEC}, {0x7EED, 0x7EED}, {0x7EEE, 0x7EEE}, {0x7EEF, 0x7EEF}, {0x7EF0, 0x7EF0}, {0x7EF1, 0x7EF1}, + {0x7EF2, 0x7EF2}, {0x7EF3, 0x7EF3}, {0x7EF4, 0x7EF4}, {0x7EF5, 0x7EF5}, {0x7EF6, 0x7EF6}, {0x7EF7, 0x7EF7}, {0x7EF8, 0x7EF8}, + {0x7EF9, 0x7EF9}, {0x7EFA, 0x7EFA}, {0x7EFB, 0x7EFB}, {0x7EFC, 0x7EFC}, {0x7EFD, 0x7EFD}, {0x7EFE, 0x7EFE}, {0x7EFF, 0x7EFF}, + {0x7F00, 0x7F00}, {0x7F01, 0x7F01}, {0x7F02, 0x7F02}, {0x7F03, 0x7F03}, {0x7F04, 0x7F04}, {0x7F05, 0x7F05}, {0x7F06, 0x7F06}, + {0x7F07, 0x7F07}, {0x7F08, 0x7F08}, {0x7F09, 0x7F09}, {0x7F0A, 0x7F0A}, {0x7F0B, 0x7F0B}, {0x7F0C, 0x7F0C}, {0x7F0D, 0x7F0D}, + {0x7F0E, 0x7F0E}, {0x7F0F, 0x7F0F}, {0x7F10, 0x7F10}, {0x7F11, 0x7F11}, {0x7F12, 0x7F12}, {0x7F13, 0x7F13}, {0x7F14, 0x7F14}, + {0x7F15, 0x7F15}, {0x7F16, 0x7F16}, {0x7F17, 0x7F17}, {0x7F18, 0x7F18}, {0x7F19, 0x7F19}, {0x7F1A, 0x7F1A}, {0x7F1B, 0x7F1B}, + {0x7F1C, 0x7F1C}, {0x7F1D, 0x7F1D}, {0x7F1E, 0x7F1E}, {0x7F1F, 0x7F1F}, {0x7F20, 0x7F20}, {0x7F21, 0x7F21}, {0x7F22, 0x7F22}, + {0x7F23, 0x7F23}, {0x7F24, 0x7F24}, {0x7F25, 0x7F25}, {0x7F26, 0x7F26}, {0x7F27, 0x7F27}, {0x7F28, 0x7F28}, {0x7F29, 0x7F29}, + {0x7F2A, 0x7F2A}, {0x7F2B, 0x7F2B}, {0x7F2C, 0x7F2C}, {0x7F2D, 0x7F2D}, {0x7F2E, 0x7F2E}, {0x7F2F, 0x7F2F}, {0x7F30, 0x7F30}, + {0x7F31, 0x7F31}, {0x7F32, 0x7F32}, {0x7F33, 0x7F33}, {0x7F34, 0x7F34}, {0x7F35, 0x7F35}, {0x7F36, 0x7F36}, {0x7F37, 0x7F37}, + {0x7F38, 0x7F38}, {0x7F39, 0x7F39}, {0x7F3A, 0x7F3A}, {0x7F3B, 0x7F3B}, {0x7F3C, 0x7F3C}, {0x7F3D, 0x7F3D}, {0x7F3E, 0x7F3E}, + {0x7F3F, 0x7F3F}, {0x7F40, 0x7F40}, {0x7F41, 0x7F41}, {0x7F42, 0x7F42}, {0x7F43, 0x7F43}, {0x7F44, 0x7F44}, {0x7F45, 0x7F45}, + {0x7F46, 0x7F46}, {0x7F47, 0x7F47}, {0x7F48, 0x7F48}, {0x7F49, 0x7F49}, {0x7F4A, 0x7F4A}, {0x7F4B, 0x7F4B}, {0x7F4C, 0x7F4C}, + {0x7F4D, 0x7F4D}, {0x7F4E, 0x7F4E}, {0x7F4F, 0x7F4F}, {0x7F50, 0x7F50}, {0x7F51, 0x7F51}, {0x7F52, 0x7F52}, {0x7F53, 0x7F53}, + {0x7F54, 0x7F54}, {0x7F55, 0x7F55}, {0x7F56, 0x7F56}, {0x7F57, 0x7F57}, {0x7F58, 0x7F58}, {0x7F59, 0x7F59}, {0x7F5A, 0x7F5A}, + {0x7F5B, 0x7F5B}, {0x7F5C, 0x7F5C}, {0x7F5D, 0x7F5D}, {0x7F5E, 0x7F5E}, {0x7F5F, 0x7F5F}, {0x7F60, 0x7F60}, {0x7F61, 0x7F61}, + {0x7F62, 0x7F62}, {0x7F63, 0x7F63}, {0x7F64, 0x7F64}, {0x7F65, 0x7F65}, {0x7F66, 0x7F66}, {0x7F67, 0x7F67}, {0x7F68, 0x7F68}, + {0x7F69, 0x7F69}, {0x7F6A, 0x7F6A}, {0x7F6B, 0x7F6B}, {0x7F6C, 0x7F6C}, {0x7F6D, 0x7F6D}, {0x7F6E, 0x7F6E}, {0x7F6F, 0x7F6F}, + {0x7F70, 0x7F70}, {0x7F71, 0x7F71}, {0x7F72, 0x7F72}, {0x7F73, 0x7F73}, {0x7F74, 0x7F74}, {0x7F75, 0x7F75}, {0x7F76, 0x7F76}, + {0x7F77, 0x7F77}, {0x7F78, 0x7F78}, {0x7F79, 0x7F79}, {0x7F7A, 0x7F7A}, {0x7F7B, 0x7F7B}, {0x7F7C, 0x7F7C}, {0x7F7D, 0x7F7D}, + {0x7F7E, 0x7F7E}, {0x7F7F, 0x7F7F}, {0x7F80, 0x7F80}, {0x7F81, 0x7F81}, {0x7F82, 0x7F82}, {0x7F83, 0x7F83}, {0x7F84, 0x7F84}, + {0x7F85, 0x7F85}, {0x7F86, 0x7F86}, {0x7F87, 0x7F87}, {0x7F88, 0x7F88}, {0x7F89, 0x7F89}, {0x7F8A, 0x7F8A}, {0x7F8B, 0x7F8B}, + {0x7F8C, 0x7F8C}, {0x7F8D, 0x7F8D}, {0x7F8E, 0x7F8E}, {0x7F8F, 0x7F8F}, {0x7F90, 0x7F90}, {0x7F91, 0x7F91}, {0x7F92, 0x7F92}, + {0x7F93, 0x7F93}, {0x7F94, 0x7F94}, {0x7F95, 0x7F95}, {0x7F96, 0x7F96}, {0x7F97, 0x7F97}, {0x7F98, 0x7F98}, {0x7F99, 0x7F99}, + {0x7F9A, 0x7F9A}, {0x7F9B, 0x7F9B}, {0x7F9C, 0x7F9C}, {0x7F9D, 0x7F9D}, {0x7F9E, 0x7F9E}, {0x7F9F, 0x7F9F}, {0x7FA0, 0x7FA0}, + {0x7FA1, 0x7FA1}, {0x7FA2, 0x7FA2}, {0x7FA3, 0x7FA3}, {0x7FA4, 0x7FA4}, {0x7FA5, 0x7FA5}, {0x7FA6, 0x7FA6}, {0x7FA7, 0x7FA7}, + {0x7FA8, 0x7FA8}, {0x7FA9, 0x7FA9}, {0x7FAA, 0x7FAA}, {0x7FAB, 0x7FAB}, {0x7FAC, 0x7FAC}, {0x7FAD, 0x7FAD}, {0x7FAE, 0x7FAE}, + {0x7FAF, 0x7FAF}, {0x7FB0, 0x7FB0}, {0x7FB1, 0x7FB1}, {0x7FB2, 0x7FB2}, {0x7FB3, 0x7FB3}, {0x7FB4, 0x7FB4}, {0x7FB5, 0x7FB5}, + {0x7FB6, 0x7FB6}, {0x7FB7, 0x7FB7}, {0x7FB8, 0x7FB8}, {0x7FB9, 0x7FB9}, {0x7FBA, 0x7FBA}, {0x7FBB, 0x7FBB}, {0x7FBC, 0x7FBC}, + {0x7FBD, 0x7FBD}, {0x7FBE, 0x7FBE}, {0x7FBF, 0x7FBF}, {0x7FC0, 0x7FC0}, {0x7FC1, 0x7FC1}, {0x7FC2, 0x7FC2}, {0x7FC3, 0x7FC3}, + {0x7FC4, 0x7FC4}, {0x7FC5, 0x7FC5}, {0x7FC6, 0x7FC6}, {0x7FC7, 0x7FC7}, {0x7FC8, 0x7FC8}, {0x7FC9, 0x7FC9}, {0x7FCA, 0x7FCA}, + {0x7FCB, 0x7FCB}, {0x7FCC, 0x7FCC}, {0x7FCD, 0x7FCD}, {0x7FCE, 0x7FCE}, {0x7FCF, 0x7FCF}, {0x7FD0, 0x7FD0}, {0x7FD1, 0x7FD1}, + {0x7FD2, 0x7FD2}, {0x7FD3, 0x7FD3}, {0x7FD4, 0x7FD4}, {0x7FD5, 0x7FD5}, {0x7FD6, 0x7FD6}, {0x7FD7, 0x7FD7}, {0x7FD8, 0x7FD8}, + {0x7FD9, 0x7FD9}, {0x7FDA, 0x7FDA}, {0x7FDB, 0x7FDB}, {0x7FDC, 0x7FDC}, {0x7FDD, 0x7FDD}, {0x7FDE, 0x7FDE}, {0x7FDF, 0x7FDF}, + {0x7FE0, 0x7FE0}, {0x7FE1, 0x7FE1}, {0x7FE2, 0x7FE2}, {0x7FE3, 0x7FE3}, {0x7FE4, 0x7FE4}, {0x7FE5, 0x7FE5}, {0x7FE6, 0x7FE6}, + {0x7FE7, 0x7FE7}, {0x7FE8, 0x7FE8}, {0x7FE9, 0x7FE9}, {0x7FEA, 0x7FEA}, {0x7FEB, 0x7FEB}, {0x7FEC, 0x7FEC}, {0x7FED, 0x7FED}, + {0x7FEE, 0x7FEE}, {0x7FEF, 0x7FEF}, {0x7FF0, 0x7FF0}, {0x7FF1, 0x7FF1}, {0x7FF2, 0x7FF2}, {0x7FF3, 0x7FF3}, {0x7FF4, 0x7FF4}, + {0x7FF5, 0x7FF5}, {0x7FF6, 0x7FF6}, {0x7FF7, 0x7FF7}, {0x7FF8, 0x7FF8}, {0x7FF9, 0x7FF9}, {0x7FFA, 0x7FFA}, {0x7FFB, 0x7FFB}, + {0x7FFC, 0x7FFC}, {0x7FFD, 0x7FFD}, {0x7FFE, 0x7FFE}, {0x7FFF, 0x7FFF}, {0x8000, 0x8000}, {0x8001, 0x8001}, {0x8002, 0x8002}, + {0x8003, 0x8003}, {0x8004, 0x8004}, {0x8005, 0x8005}, {0x8006, 0x8006}, {0x8007, 0x8007}, {0x8008, 0x8008}, {0x8009, 0x8009}, + {0x800A, 0x800A}, {0x800B, 0x800B}, {0x800C, 0x800C}, {0x800D, 0x800D}, {0x800E, 0x800E}, {0x800F, 0x800F}, {0x8010, 0x8010}, + {0x8011, 0x8011}, {0x8012, 0x8012}, {0x8013, 0x8013}, {0x8014, 0x8014}, {0x8015, 0x8015}, {0x8016, 0x8016}, {0x8017, 0x8017}, + {0x8018, 0x8018}, {0x8019, 0x8019}, {0x801A, 0x801A}, {0x801B, 0x801B}, {0x801C, 0x801C}, {0x801D, 0x801D}, {0x801E, 0x801E}, + {0x801F, 0x801F}, {0x8020, 0x8020}, {0x8021, 0x8021}, {0x8022, 0x8022}, {0x8023, 0x8023}, {0x8024, 0x8024}, {0x8025, 0x8025}, + {0x8026, 0x8026}, {0x8027, 0x8027}, {0x8028, 0x8028}, {0x8029, 0x8029}, {0x802A, 0x802A}, {0x802B, 0x802B}, {0x802C, 0x802C}, + {0x802D, 0x802D}, {0x802E, 0x802E}, {0x802F, 0x802F}, {0x8030, 0x8030}, {0x8031, 0x8031}, {0x8032, 0x8032}, {0x8033, 0x8033}, + {0x8034, 0x8034}, {0x8035, 0x8035}, {0x8036, 0x8036}, {0x8037, 0x8037}, {0x8038, 0x8038}, {0x8039, 0x8039}, {0x803A, 0x803A}, + {0x803B, 0x803B}, {0x803C, 0x803C}, {0x803D, 0x803D}, {0x803E, 0x803E}, {0x803F, 0x803F}, {0x8040, 0x8040}, {0x8041, 0x8041}, + {0x8042, 0x8042}, {0x8043, 0x8043}, {0x8044, 0x8044}, {0x8045, 0x8045}, {0x8046, 0x8046}, {0x8047, 0x8047}, {0x8048, 0x8048}, + {0x8049, 0x8049}, {0x804A, 0x804A}, {0x804B, 0x804B}, {0x804C, 0x804C}, {0x804D, 0x804D}, {0x804E, 0x804E}, {0x804F, 0x804F}, + {0x8050, 0x8050}, {0x8051, 0x8051}, {0x8052, 0x8052}, {0x8053, 0x8053}, {0x8054, 0x8054}, {0x8055, 0x8055}, {0x8056, 0x8056}, + {0x8057, 0x8057}, {0x8058, 0x8058}, {0x8059, 0x8059}, {0x805A, 0x805A}, {0x805B, 0x805B}, {0x805C, 0x805C}, {0x805D, 0x805D}, + {0x805E, 0x805E}, {0x805F, 0x805F}, {0x8060, 0x8060}, {0x8061, 0x8061}, {0x8062, 0x8062}, {0x8063, 0x8063}, {0x8064, 0x8064}, + {0x8065, 0x8065}, {0x8066, 0x8066}, {0x8067, 0x8067}, {0x8068, 0x8068}, {0x8069, 0x8069}, {0x806A, 0x806A}, {0x806B, 0x806B}, + {0x806C, 0x806C}, {0x806D, 0x806D}, {0x806E, 0x806E}, {0x806F, 0x806F}, {0x8070, 0x8070}, {0x8071, 0x8071}, {0x8072, 0x8072}, + {0x8073, 0x8073}, {0x8074, 0x8074}, {0x8075, 0x8075}, {0x8076, 0x8076}, {0x8077, 0x8077}, {0x8078, 0x8078}, {0x8079, 0x8079}, + {0x807A, 0x807A}, {0x807B, 0x807B}, {0x807C, 0x807C}, {0x807D, 0x807D}, {0x807E, 0x807E}, {0x807F, 0x807F}, {0x8080, 0x8080}, + {0x8081, 0x8081}, {0x8082, 0x8082}, {0x8083, 0x8083}, {0x8084, 0x8084}, {0x8085, 0x8085}, {0x8086, 0x8086}, {0x8087, 0x8087}, + {0x8088, 0x8088}, {0x8089, 0x8089}, {0x808A, 0x808A}, {0x808B, 0x808B}, {0x808C, 0x808C}, {0x808D, 0x808D}, {0x808E, 0x808E}, + {0x808F, 0x808F}, {0x8090, 0x8090}, {0x8091, 0x8091}, {0x8092, 0x8092}, {0x8093, 0x8093}, {0x8094, 0x8094}, {0x8095, 0x8095}, + {0x8096, 0x8096}, {0x8097, 0x8097}, {0x8098, 0x8098}, {0x8099, 0x8099}, {0x809A, 0x809A}, {0x809B, 0x809B}, {0x809C, 0x809C}, + {0x809D, 0x809D}, {0x809E, 0x809E}, {0x809F, 0x809F}, {0x80A0, 0x80A0}, {0x80A1, 0x80A1}, {0x80A2, 0x80A2}, {0x80A3, 0x80A3}, + {0x80A4, 0x80A4}, {0x80A5, 0x80A5}, {0x80A6, 0x80A6}, {0x80A7, 0x80A7}, {0x80A8, 0x80A8}, {0x80A9, 0x80A9}, {0x80AA, 0x80AA}, + {0x80AB, 0x80AB}, {0x80AC, 0x80AC}, {0x80AD, 0x80AD}, {0x80AE, 0x80AE}, {0x80AF, 0x80AF}, {0x80B0, 0x80B0}, {0x80B1, 0x80B1}, + {0x80B2, 0x80B2}, {0x80B3, 0x80B3}, {0x80B4, 0x80B4}, {0x80B5, 0x80B5}, {0x80B6, 0x80B6}, {0x80B7, 0x80B7}, {0x80B8, 0x80B8}, + {0x80B9, 0x80B9}, {0x80BA, 0x80BA}, {0x80BB, 0x80BB}, {0x80BC, 0x80BC}, {0x80BD, 0x80BD}, {0x80BE, 0x80BE}, {0x80BF, 0x80BF}, + {0x80C0, 0x80C0}, {0x80C1, 0x80C1}, {0x80C2, 0x80C2}, {0x80C3, 0x80C3}, {0x80C4, 0x80C4}, {0x80C5, 0x80C5}, {0x80C6, 0x80C6}, + {0x80C7, 0x80C7}, {0x80C8, 0x80C8}, {0x80C9, 0x80C9}, {0x80CA, 0x80CA}, {0x80CB, 0x80CB}, {0x80CC, 0x80CC}, {0x80CD, 0x80CD}, + {0x80CE, 0x80CE}, {0x80CF, 0x80CF}, {0x80D0, 0x80D0}, {0x80D1, 0x80D1}, {0x80D2, 0x80D2}, {0x80D3, 0x80D3}, {0x80D4, 0x80D4}, + {0x80D5, 0x80D5}, {0x80D6, 0x80D6}, {0x80D7, 0x80D7}, {0x80D8, 0x80D8}, {0x80D9, 0x80D9}, {0x80DA, 0x80DA}, {0x80DB, 0x80DB}, + {0x80DC, 0x80DC}, {0x80DD, 0x80DD}, {0x80DE, 0x80DE}, {0x80DF, 0x80DF}, {0x80E0, 0x80E0}, {0x80E1, 0x80E1}, {0x80E2, 0x80E2}, + {0x80E3, 0x80E3}, {0x80E4, 0x80E4}, {0x80E5, 0x80E5}, {0x80E6, 0x80E6}, {0x80E7, 0x80E7}, {0x80E8, 0x80E8}, {0x80E9, 0x80E9}, + {0x80EA, 0x80EA}, {0x80EB, 0x80EB}, {0x80EC, 0x80EC}, {0x80ED, 0x80ED}, {0x80EE, 0x80EE}, {0x80EF, 0x80EF}, {0x80F0, 0x80F0}, + {0x80F1, 0x80F1}, {0x80F2, 0x80F2}, {0x80F3, 0x80F3}, {0x80F4, 0x80F4}, {0x80F5, 0x80F5}, {0x80F6, 0x80F6}, {0x80F7, 0x80F7}, + {0x80F8, 0x80F8}, {0x80F9, 0x80F9}, {0x80FA, 0x80FA}, {0x80FB, 0x80FB}, {0x80FC, 0x80FC}, {0x80FD, 0x80FD}, {0x80FE, 0x80FE}, + {0x80FF, 0x80FF}, {0x8100, 0x8100}, {0x8101, 0x8101}, {0x8102, 0x8102}, {0x8103, 0x8103}, {0x8104, 0x8104}, {0x8105, 0x8105}, + {0x8106, 0x8106}, {0x8107, 0x8107}, {0x8108, 0x8108}, {0x8109, 0x8109}, {0x810A, 0x810A}, {0x810B, 0x810B}, {0x810C, 0x810C}, + {0x810D, 0x810D}, {0x810E, 0x810E}, {0x810F, 0x810F}, {0x8110, 0x8110}, {0x8111, 0x8111}, {0x8112, 0x8112}, {0x8113, 0x8113}, + {0x8114, 0x8114}, {0x8115, 0x8115}, {0x8116, 0x8116}, {0x8117, 0x8117}, {0x8118, 0x8118}, {0x8119, 0x8119}, {0x811A, 0x811A}, + {0x811B, 0x811B}, {0x811C, 0x811C}, {0x811D, 0x811D}, {0x811E, 0x811E}, {0x811F, 0x811F}, {0x8120, 0x8120}, {0x8121, 0x8121}, + {0x8122, 0x8122}, {0x8123, 0x8123}, {0x8124, 0x8124}, {0x8125, 0x8125}, {0x8126, 0x8126}, {0x8127, 0x8127}, {0x8128, 0x8128}, + {0x8129, 0x8129}, {0x812A, 0x812A}, {0x812B, 0x812B}, {0x812C, 0x812C}, {0x812D, 0x812D}, {0x812E, 0x812E}, {0x812F, 0x812F}, + {0x8130, 0x8130}, {0x8131, 0x8131}, {0x8132, 0x8132}, {0x8133, 0x8133}, {0x8134, 0x8134}, {0x8135, 0x8135}, {0x8136, 0x8136}, + {0x8137, 0x8137}, {0x8138, 0x8138}, {0x8139, 0x8139}, {0x813A, 0x813A}, {0x813B, 0x813B}, {0x813C, 0x813C}, {0x813D, 0x813D}, + {0x813E, 0x813E}, {0x813F, 0x813F}, {0x8140, 0x8140}, {0x8141, 0x8141}, {0x8142, 0x8142}, {0x8143, 0x8143}, {0x8144, 0x8144}, + {0x8145, 0x8145}, {0x8146, 0x8146}, {0x8147, 0x8147}, {0x8148, 0x8148}, {0x8149, 0x8149}, {0x814A, 0x814A}, {0x814B, 0x814B}, + {0x814C, 0x814C}, {0x814D, 0x814D}, {0x814E, 0x814E}, {0x814F, 0x814F}, {0x8150, 0x8150}, {0x8151, 0x8151}, {0x8152, 0x8152}, + {0x8153, 0x8153}, {0x8154, 0x8154}, {0x8155, 0x8155}, {0x8156, 0x8156}, {0x8157, 0x8157}, {0x8158, 0x8158}, {0x8159, 0x8159}, + {0x815A, 0x815A}, {0x815B, 0x815B}, {0x815C, 0x815C}, {0x815D, 0x815D}, {0x815E, 0x815E}, {0x815F, 0x815F}, {0x8160, 0x8160}, + {0x8161, 0x8161}, {0x8162, 0x8162}, {0x8163, 0x8163}, {0x8164, 0x8164}, {0x8165, 0x8165}, {0x8166, 0x8166}, {0x8167, 0x8167}, + {0x8168, 0x8168}, {0x8169, 0x8169}, {0x816A, 0x816A}, {0x816B, 0x816B}, {0x816C, 0x816C}, {0x816D, 0x816D}, {0x816E, 0x816E}, + {0x816F, 0x816F}, {0x8170, 0x8170}, {0x8171, 0x8171}, {0x8172, 0x8172}, {0x8173, 0x8173}, {0x8174, 0x8174}, {0x8175, 0x8175}, + {0x8176, 0x8176}, {0x8177, 0x8177}, {0x8178, 0x8178}, {0x8179, 0x8179}, {0x817A, 0x817A}, {0x817B, 0x817B}, {0x817C, 0x817C}, + {0x817D, 0x817D}, {0x817E, 0x817E}, {0x817F, 0x817F}, {0x8180, 0x8180}, {0x8181, 0x8181}, {0x8182, 0x8182}, {0x8183, 0x8183}, + {0x8184, 0x8184}, {0x8185, 0x8185}, {0x8186, 0x8186}, {0x8187, 0x8187}, {0x8188, 0x8188}, {0x8189, 0x8189}, {0x818A, 0x818A}, + {0x818B, 0x818B}, {0x818C, 0x818C}, {0x818D, 0x818D}, {0x818E, 0x818E}, {0x818F, 0x818F}, {0x8190, 0x8190}, {0x8191, 0x8191}, + {0x8192, 0x8192}, {0x8193, 0x8193}, {0x8194, 0x8194}, {0x8195, 0x8195}, {0x8196, 0x8196}, {0x8197, 0x8197}, {0x8198, 0x8198}, + {0x8199, 0x8199}, {0x819A, 0x819A}, {0x819B, 0x819B}, {0x819C, 0x819C}, {0x819D, 0x819D}, {0x819E, 0x819E}, {0x819F, 0x819F}, + {0x81A0, 0x81A0}, {0x81A1, 0x81A1}, {0x81A2, 0x81A2}, {0x81A3, 0x81A3}, {0x81A4, 0x81A4}, {0x81A5, 0x81A5}, {0x81A6, 0x81A6}, + {0x81A7, 0x81A7}, {0x81A8, 0x81A8}, {0x81A9, 0x81A9}, {0x81AA, 0x81AA}, {0x81AB, 0x81AB}, {0x81AC, 0x81AC}, {0x81AD, 0x81AD}, + {0x81AE, 0x81AE}, {0x81AF, 0x81AF}, {0x81B0, 0x81B0}, {0x81B1, 0x81B1}, {0x81B2, 0x81B2}, {0x81B3, 0x81B3}, {0x81B4, 0x81B4}, + {0x81B5, 0x81B5}, {0x81B6, 0x81B6}, {0x81B7, 0x81B7}, {0x81B8, 0x81B8}, {0x81B9, 0x81B9}, {0x81BA, 0x81BA}, {0x81BB, 0x81BB}, + {0x81BC, 0x81BC}, {0x81BD, 0x81BD}, {0x81BE, 0x81BE}, {0x81BF, 0x81BF}, {0x81C0, 0x81C0}, {0x81C1, 0x81C1}, {0x81C2, 0x81C2}, + {0x81C3, 0x81C3}, {0x81C4, 0x81C4}, {0x81C5, 0x81C5}, {0x81C6, 0x81C6}, {0x81C7, 0x81C7}, {0x81C8, 0x81C8}, {0x81C9, 0x81C9}, + {0x81CA, 0x81CA}, {0x81CB, 0x81CB}, {0x81CC, 0x81CC}, {0x81CD, 0x81CD}, {0x81CE, 0x81CE}, {0x81CF, 0x81CF}, {0x81D0, 0x81D0}, + {0x81D1, 0x81D1}, {0x81D2, 0x81D2}, {0x81D3, 0x81D3}, {0x81D4, 0x81D4}, {0x81D5, 0x81D5}, {0x81D6, 0x81D6}, {0x81D7, 0x81D7}, + {0x81D8, 0x81D8}, {0x81D9, 0x81D9}, {0x81DA, 0x81DA}, {0x81DB, 0x81DB}, {0x81DC, 0x81DC}, {0x81DD, 0x81DD}, {0x81DE, 0x81DE}, + {0x81DF, 0x81DF}, {0x81E0, 0x81E0}, {0x81E1, 0x81E1}, {0x81E2, 0x81E2}, {0x81E3, 0x81E3}, {0x81E4, 0x81E4}, {0x81E5, 0x81E5}, + {0x81E6, 0x81E6}, {0x81E7, 0x81E7}, {0x81E8, 0x81E8}, {0x81E9, 0x81E9}, {0x81EA, 0x81EA}, {0x81EB, 0x81EB}, {0x81EC, 0x81EC}, + {0x81ED, 0x81ED}, {0x81EE, 0x81EE}, {0x81EF, 0x81EF}, {0x81F0, 0x81F0}, {0x81F1, 0x81F1}, {0x81F2, 0x81F2}, {0x81F3, 0x81F3}, + {0x81F4, 0x81F4}, {0x81F5, 0x81F5}, {0x81F6, 0x81F6}, {0x81F7, 0x81F7}, {0x81F8, 0x81F8}, {0x81F9, 0x81F9}, {0x81FA, 0x81FA}, + {0x81FB, 0x81FB}, {0x81FC, 0x81FC}, {0x81FD, 0x81FD}, {0x81FE, 0x81FE}, {0x81FF, 0x81FF}, {0x8200, 0x8200}, {0x8201, 0x8201}, + {0x8202, 0x8202}, {0x8203, 0x8203}, {0x8204, 0x8204}, {0x8205, 0x8205}, {0x8206, 0x8206}, {0x8207, 0x8207}, {0x8208, 0x8208}, + {0x8209, 0x8209}, {0x820A, 0x820A}, {0x820B, 0x820B}, {0x820C, 0x820C}, {0x820D, 0x820D}, {0x820E, 0x820E}, {0x820F, 0x820F}, + {0x8210, 0x8210}, {0x8211, 0x8211}, {0x8212, 0x8212}, {0x8213, 0x8213}, {0x8214, 0x8214}, {0x8215, 0x8215}, {0x8216, 0x8216}, + {0x8217, 0x8217}, {0x8218, 0x8218}, {0x8219, 0x8219}, {0x821A, 0x821A}, {0x821B, 0x821B}, {0x821C, 0x821C}, {0x821D, 0x821D}, + {0x821E, 0x821E}, {0x821F, 0x821F}, {0x8220, 0x8220}, {0x8221, 0x8221}, {0x8222, 0x8222}, {0x8223, 0x8223}, {0x8224, 0x8224}, + {0x8225, 0x8225}, {0x8226, 0x8226}, {0x8227, 0x8227}, {0x8228, 0x8228}, {0x8229, 0x8229}, {0x822A, 0x822A}, {0x822B, 0x822B}, + {0x822C, 0x822C}, {0x822D, 0x822D}, {0x822E, 0x822E}, {0x822F, 0x822F}, {0x8230, 0x8230}, {0x8231, 0x8231}, {0x8232, 0x8232}, + {0x8233, 0x8233}, {0x8234, 0x8234}, {0x8235, 0x8235}, {0x8236, 0x8236}, {0x8237, 0x8237}, {0x8238, 0x8238}, {0x8239, 0x8239}, + {0x823A, 0x823A}, {0x823B, 0x823B}, {0x823C, 0x823C}, {0x823D, 0x823D}, {0x823E, 0x823E}, {0x823F, 0x823F}, {0x8240, 0x8240}, + {0x8241, 0x8241}, {0x8242, 0x8242}, {0x8243, 0x8243}, {0x8244, 0x8244}, {0x8245, 0x8245}, {0x8246, 0x8246}, {0x8247, 0x8247}, + {0x8248, 0x8248}, {0x8249, 0x8249}, {0x824A, 0x824A}, {0x824B, 0x824B}, {0x824C, 0x824C}, {0x824D, 0x824D}, {0x824E, 0x824E}, + {0x824F, 0x824F}, {0x8250, 0x8250}, {0x8251, 0x8251}, {0x8252, 0x8252}, {0x8253, 0x8253}, {0x8254, 0x8254}, {0x8255, 0x8255}, + {0x8256, 0x8256}, {0x8257, 0x8257}, {0x8258, 0x8258}, {0x8259, 0x8259}, {0x825A, 0x825A}, {0x825B, 0x825B}, {0x825C, 0x825C}, + {0x825D, 0x825D}, {0x825E, 0x825E}, {0x825F, 0x825F}, {0x8260, 0x8260}, {0x8261, 0x8261}, {0x8262, 0x8262}, {0x8263, 0x8263}, + {0x8264, 0x8264}, {0x8265, 0x8265}, {0x8266, 0x8266}, {0x8267, 0x8267}, {0x8268, 0x8268}, {0x8269, 0x8269}, {0x826A, 0x826A}, + {0x826B, 0x826B}, {0x826C, 0x826C}, {0x826D, 0x826D}, {0x826E, 0x826E}, {0x826F, 0x826F}, {0x8270, 0x8270}, {0x8271, 0x8271}, + {0x8272, 0x8272}, {0x8273, 0x8273}, {0x8274, 0x8274}, {0x8275, 0x8275}, {0x8276, 0x8276}, {0x8277, 0x8277}, {0x8278, 0x8278}, + {0x8279, 0x8279}, {0x827A, 0x827A}, {0x827B, 0x827B}, {0x827C, 0x827C}, {0x827D, 0x827D}, {0x827E, 0x827E}, {0x827F, 0x827F}, + {0x8280, 0x8280}, {0x8281, 0x8281}, {0x8282, 0x8282}, {0x8283, 0x8283}, {0x8284, 0x8284}, {0x8285, 0x8285}, {0x8286, 0x8286}, + {0x8287, 0x8287}, {0x8288, 0x8288}, {0x8289, 0x8289}, {0x828A, 0x828A}, {0x828B, 0x828B}, {0x828C, 0x828C}, {0x828D, 0x828D}, + {0x828E, 0x828E}, {0x828F, 0x828F}, {0x8290, 0x8290}, {0x8291, 0x8291}, {0x8292, 0x8292}, {0x8293, 0x8293}, {0x8294, 0x8294}, + {0x8295, 0x8295}, {0x8296, 0x8296}, {0x8297, 0x8297}, {0x8298, 0x8298}, {0x8299, 0x8299}, {0x829A, 0x829A}, {0x829B, 0x829B}, + {0x829C, 0x829C}, {0x829D, 0x829D}, {0x829E, 0x829E}, {0x829F, 0x829F}, {0x82A0, 0x82A0}, {0x82A1, 0x82A1}, {0x82A2, 0x82A2}, + {0x82A3, 0x82A3}, {0x82A4, 0x82A4}, {0x82A5, 0x82A5}, {0x82A6, 0x82A6}, {0x82A7, 0x82A7}, {0x82A8, 0x82A8}, {0x82A9, 0x82A9}, + {0x82AA, 0x82AA}, {0x82AB, 0x82AB}, {0x82AC, 0x82AC}, {0x82AD, 0x82AD}, {0x82AE, 0x82AE}, {0x82AF, 0x82AF}, {0x82B0, 0x82B0}, + {0x82B1, 0x82B1}, {0x82B2, 0x82B2}, {0x82B3, 0x82B3}, {0x82B4, 0x82B4}, {0x82B5, 0x82B5}, {0x82B6, 0x82B6}, {0x82B7, 0x82B7}, + {0x82B8, 0x82B8}, {0x82B9, 0x82B9}, {0x82BA, 0x82BA}, {0x82BB, 0x82BB}, {0x82BC, 0x82BC}, {0x82BD, 0x82BD}, {0x82BE, 0x82BE}, + {0x82BF, 0x82BF}, {0x82C0, 0x82C0}, {0x82C1, 0x82C1}, {0x82C2, 0x82C2}, {0x82C3, 0x82C3}, {0x82C4, 0x82C4}, {0x82C5, 0x82C5}, + {0x82C6, 0x82C6}, {0x82C7, 0x82C7}, {0x82C8, 0x82C8}, {0x82C9, 0x82C9}, {0x82CA, 0x82CA}, {0x82CB, 0x82CB}, {0x82CC, 0x82CC}, + {0x82CD, 0x82CD}, {0x82CE, 0x82CE}, {0x82CF, 0x82CF}, {0x82D0, 0x82D0}, {0x82D1, 0x82D1}, {0x82D2, 0x82D2}, {0x82D3, 0x82D3}, + {0x82D4, 0x82D4}, {0x82D5, 0x82D5}, {0x82D6, 0x82D6}, {0x82D7, 0x82D7}, {0x82D8, 0x82D8}, {0x82D9, 0x82D9}, {0x82DA, 0x82DA}, + {0x82DB, 0x82DB}, {0x82DC, 0x82DC}, {0x82DD, 0x82DD}, {0x82DE, 0x82DE}, {0x82DF, 0x82DF}, {0x82E0, 0x82E0}, {0x82E1, 0x82E1}, + {0x82E2, 0x82E2}, {0x82E3, 0x82E3}, {0x82E4, 0x82E4}, {0x82E5, 0x82E5}, {0x82E6, 0x82E6}, {0x82E7, 0x82E7}, {0x82E8, 0x82E8}, + {0x82E9, 0x82E9}, {0x82EA, 0x82EA}, {0x82EB, 0x82EB}, {0x82EC, 0x82EC}, {0x82ED, 0x82ED}, {0x82EE, 0x82EE}, {0x82EF, 0x82EF}, + {0x82F0, 0x82F0}, {0x82F1, 0x82F1}, {0x82F2, 0x82F2}, {0x82F3, 0x82F3}, {0x82F4, 0x82F4}, {0x82F5, 0x82F5}, {0x82F6, 0x82F6}, + {0x82F7, 0x82F7}, {0x82F8, 0x82F8}, {0x82F9, 0x82F9}, {0x82FA, 0x82FA}, {0x82FB, 0x82FB}, {0x82FC, 0x82FC}, {0x82FD, 0x82FD}, + {0x82FE, 0x82FE}, {0x82FF, 0x82FF}, {0x8300, 0x8300}, {0x8301, 0x8301}, {0x8302, 0x8302}, {0x8303, 0x8303}, {0x8304, 0x8304}, + {0x8305, 0x8305}, {0x8306, 0x8306}, {0x8307, 0x8307}, {0x8308, 0x8308}, {0x8309, 0x8309}, {0x830A, 0x830A}, {0x830B, 0x830B}, + {0x830C, 0x830C}, {0x830D, 0x830D}, {0x830E, 0x830E}, {0x830F, 0x830F}, {0x8310, 0x8310}, {0x8311, 0x8311}, {0x8312, 0x8312}, + {0x8313, 0x8313}, {0x8314, 0x8314}, {0x8315, 0x8315}, {0x8316, 0x8316}, {0x8317, 0x8317}, {0x8318, 0x8318}, {0x8319, 0x8319}, + {0x831A, 0x831A}, {0x831B, 0x831B}, {0x831C, 0x831C}, {0x831D, 0x831D}, {0x831E, 0x831E}, {0x831F, 0x831F}, {0x8320, 0x8320}, + {0x8321, 0x8321}, {0x8322, 0x8322}, {0x8323, 0x8323}, {0x8324, 0x8324}, {0x8325, 0x8325}, {0x8326, 0x8326}, {0x8327, 0x8327}, + {0x8328, 0x8328}, {0x8329, 0x8329}, {0x832A, 0x832A}, {0x832B, 0x832B}, {0x832C, 0x832C}, {0x832D, 0x832D}, {0x832E, 0x832E}, + {0x832F, 0x832F}, {0x8330, 0x8330}, {0x8331, 0x8331}, {0x8332, 0x8332}, {0x8333, 0x8333}, {0x8334, 0x8334}, {0x8335, 0x8335}, + {0x8336, 0x8336}, {0x8337, 0x8337}, {0x8338, 0x8338}, {0x8339, 0x8339}, {0x833A, 0x833A}, {0x833B, 0x833B}, {0x833C, 0x833C}, + {0x833D, 0x833D}, {0x833E, 0x833E}, {0x833F, 0x833F}, {0x8340, 0x8340}, {0x8341, 0x8341}, {0x8342, 0x8342}, {0x8343, 0x8343}, + {0x8344, 0x8344}, {0x8345, 0x8345}, {0x8346, 0x8346}, {0x8347, 0x8347}, {0x8348, 0x8348}, {0x8349, 0x8349}, {0x834A, 0x834A}, + {0x834B, 0x834B}, {0x834C, 0x834C}, {0x834D, 0x834D}, {0x834E, 0x834E}, {0x834F, 0x834F}, {0x8350, 0x8350}, {0x8351, 0x8351}, + {0x8352, 0x8352}, {0x8353, 0x8353}, {0x8354, 0x8354}, {0x8355, 0x8355}, {0x8356, 0x8356}, {0x8357, 0x8357}, {0x8358, 0x8358}, + {0x8359, 0x8359}, {0x835A, 0x835A}, {0x835B, 0x835B}, {0x835C, 0x835C}, {0x835D, 0x835D}, {0x835E, 0x835E}, {0x835F, 0x835F}, + {0x8360, 0x8360}, {0x8361, 0x8361}, {0x8362, 0x8362}, {0x8363, 0x8363}, {0x8364, 0x8364}, {0x8365, 0x8365}, {0x8366, 0x8366}, + {0x8367, 0x8367}, {0x8368, 0x8368}, {0x8369, 0x8369}, {0x836A, 0x836A}, {0x836B, 0x836B}, {0x836C, 0x836C}, {0x836D, 0x836D}, + {0x836E, 0x836E}, {0x836F, 0x836F}, {0x8370, 0x8370}, {0x8371, 0x8371}, {0x8372, 0x8372}, {0x8373, 0x8373}, {0x8374, 0x8374}, + {0x8375, 0x8375}, {0x8376, 0x8376}, {0x8377, 0x8377}, {0x8378, 0x8378}, {0x8379, 0x8379}, {0x837A, 0x837A}, {0x837B, 0x837B}, + {0x837C, 0x837C}, {0x837D, 0x837D}, {0x837E, 0x837E}, {0x837F, 0x837F}, {0x8380, 0x8380}, {0x8381, 0x8381}, {0x8382, 0x8382}, + {0x8383, 0x8383}, {0x8384, 0x8384}, {0x8385, 0x8385}, {0x8386, 0x8386}, {0x8387, 0x8387}, {0x8388, 0x8388}, {0x8389, 0x8389}, + {0x838A, 0x838A}, {0x838B, 0x838B}, {0x838C, 0x838C}, {0x838D, 0x838D}, {0x838E, 0x838E}, {0x838F, 0x838F}, {0x8390, 0x8390}, + {0x8391, 0x8391}, {0x8392, 0x8392}, {0x8393, 0x8393}, {0x8394, 0x8394}, {0x8395, 0x8395}, {0x8396, 0x8396}, {0x8397, 0x8397}, + {0x8398, 0x8398}, {0x8399, 0x8399}, {0x839A, 0x839A}, {0x839B, 0x839B}, {0x839C, 0x839C}, {0x839D, 0x839D}, {0x839E, 0x839E}, + {0x839F, 0x839F}, {0x83A0, 0x83A0}, {0x83A1, 0x83A1}, {0x83A2, 0x83A2}, {0x83A3, 0x83A3}, {0x83A4, 0x83A4}, {0x83A5, 0x83A5}, + {0x83A6, 0x83A6}, {0x83A7, 0x83A7}, {0x83A8, 0x83A8}, {0x83A9, 0x83A9}, {0x83AA, 0x83AA}, {0x83AB, 0x83AB}, {0x83AC, 0x83AC}, + {0x83AD, 0x83AD}, {0x83AE, 0x83AE}, {0x83AF, 0x83AF}, {0x83B0, 0x83B0}, {0x83B1, 0x83B1}, {0x83B2, 0x83B2}, {0x83B3, 0x83B3}, + {0x83B4, 0x83B4}, {0x83B5, 0x83B5}, {0x83B6, 0x83B6}, {0x83B7, 0x83B7}, {0x83B8, 0x83B8}, {0x83B9, 0x83B9}, {0x83BA, 0x83BA}, + {0x83BB, 0x83BB}, {0x83BC, 0x83BC}, {0x83BD, 0x83BD}, {0x83BE, 0x83BE}, {0x83BF, 0x83BF}, {0x83C0, 0x83C0}, {0x83C1, 0x83C1}, + {0x83C2, 0x83C2}, {0x83C3, 0x83C3}, {0x83C4, 0x83C4}, {0x83C5, 0x83C5}, {0x83C6, 0x83C6}, {0x83C7, 0x83C7}, {0x83C8, 0x83C8}, + {0x83C9, 0x83C9}, {0x83CA, 0x83CA}, {0x83CB, 0x83CB}, {0x83CC, 0x83CC}, {0x83CD, 0x83CD}, {0x83CE, 0x83CE}, {0x83CF, 0x83CF}, + {0x83D0, 0x83D0}, {0x83D1, 0x83D1}, {0x83D2, 0x83D2}, {0x83D3, 0x83D3}, {0x83D4, 0x83D4}, {0x83D5, 0x83D5}, {0x83D6, 0x83D6}, + {0x83D7, 0x83D7}, {0x83D8, 0x83D8}, {0x83D9, 0x83D9}, {0x83DA, 0x83DA}, {0x83DB, 0x83DB}, {0x83DC, 0x83DC}, {0x83DD, 0x83DD}, + {0x83DE, 0x83DE}, {0x83DF, 0x83DF}, {0x83E0, 0x83E0}, {0x83E1, 0x83E1}, {0x83E2, 0x83E2}, {0x83E3, 0x83E3}, {0x83E4, 0x83E4}, + {0x83E5, 0x83E5}, {0x83E6, 0x83E6}, {0x83E7, 0x83E7}, {0x83E8, 0x83E8}, {0x83E9, 0x83E9}, {0x83EA, 0x83EA}, {0x83EB, 0x83EB}, + {0x83EC, 0x83EC}, {0x83ED, 0x83ED}, {0x83EE, 0x83EE}, {0x83EF, 0x83EF}, {0x83F0, 0x83F0}, {0x83F1, 0x83F1}, {0x83F2, 0x83F2}, + {0x83F3, 0x83F3}, {0x83F4, 0x83F4}, {0x83F5, 0x83F5}, {0x83F6, 0x83F6}, {0x83F7, 0x83F7}, {0x83F8, 0x83F8}, {0x83F9, 0x83F9}, + {0x83FA, 0x83FA}, {0x83FB, 0x83FB}, {0x83FC, 0x83FC}, {0x83FD, 0x83FD}, {0x83FE, 0x83FE}, {0x83FF, 0x83FF}, {0x8400, 0x8400}, + {0x8401, 0x8401}, {0x8402, 0x8402}, {0x8403, 0x8403}, {0x8404, 0x8404}, {0x8405, 0x8405}, {0x8406, 0x8406}, {0x8407, 0x8407}, + {0x8408, 0x8408}, {0x8409, 0x8409}, {0x840A, 0x840A}, {0x840B, 0x840B}, {0x840C, 0x840C}, {0x840D, 0x840D}, {0x840E, 0x840E}, + {0x840F, 0x840F}, {0x8410, 0x8410}, {0x8411, 0x8411}, {0x8412, 0x8412}, {0x8413, 0x8413}, {0x8414, 0x8414}, {0x8415, 0x8415}, + {0x8416, 0x8416}, {0x8417, 0x8417}, {0x8418, 0x8418}, {0x8419, 0x8419}, {0x841A, 0x841A}, {0x841B, 0x841B}, {0x841C, 0x841C}, + {0x841D, 0x841D}, {0x841E, 0x841E}, {0x841F, 0x841F}, {0x8420, 0x8420}, {0x8421, 0x8421}, {0x8422, 0x8422}, {0x8423, 0x8423}, + {0x8424, 0x8424}, {0x8425, 0x8425}, {0x8426, 0x8426}, {0x8427, 0x8427}, {0x8428, 0x8428}, {0x8429, 0x8429}, {0x842A, 0x842A}, + {0x842B, 0x842B}, {0x842C, 0x842C}, {0x842D, 0x842D}, {0x842E, 0x842E}, {0x842F, 0x842F}, {0x8430, 0x8430}, {0x8431, 0x8431}, + {0x8432, 0x8432}, {0x8433, 0x8433}, {0x8434, 0x8434}, {0x8435, 0x8435}, {0x8436, 0x8436}, {0x8437, 0x8437}, {0x8438, 0x8438}, + {0x8439, 0x8439}, {0x843A, 0x843A}, {0x843B, 0x843B}, {0x843C, 0x843C}, {0x843D, 0x843D}, {0x843E, 0x843E}, {0x843F, 0x843F}, + {0x8440, 0x8440}, {0x8441, 0x8441}, {0x8442, 0x8442}, {0x8443, 0x8443}, {0x8444, 0x8444}, {0x8445, 0x8445}, {0x8446, 0x8446}, + {0x8447, 0x8447}, {0x8448, 0x8448}, {0x8449, 0x8449}, {0x844A, 0x844A}, {0x844B, 0x844B}, {0x844C, 0x844C}, {0x844D, 0x844D}, + {0x844E, 0x844E}, {0x844F, 0x844F}, {0x8450, 0x8450}, {0x8451, 0x8451}, {0x8452, 0x8452}, {0x8453, 0x8453}, {0x8454, 0x8454}, + {0x8455, 0x8455}, {0x8456, 0x8456}, {0x8457, 0x8457}, {0x8458, 0x8458}, {0x8459, 0x8459}, {0x845A, 0x845A}, {0x845B, 0x845B}, + {0x845C, 0x845C}, {0x845D, 0x845D}, {0x845E, 0x845E}, {0x845F, 0x845F}, {0x8460, 0x8460}, {0x8461, 0x8461}, {0x8462, 0x8462}, + {0x8463, 0x8463}, {0x8464, 0x8464}, {0x8465, 0x8465}, {0x8466, 0x8466}, {0x8467, 0x8467}, {0x8468, 0x8468}, {0x8469, 0x8469}, + {0x846A, 0x846A}, {0x846B, 0x846B}, {0x846C, 0x846C}, {0x846D, 0x846D}, {0x846E, 0x846E}, {0x846F, 0x846F}, {0x8470, 0x8470}, + {0x8471, 0x8471}, {0x8472, 0x8472}, {0x8473, 0x8473}, {0x8474, 0x8474}, {0x8475, 0x8475}, {0x8476, 0x8476}, {0x8477, 0x8477}, + {0x8478, 0x8478}, {0x8479, 0x8479}, {0x847A, 0x847A}, {0x847B, 0x847B}, {0x847C, 0x847C}, {0x847D, 0x847D}, {0x847E, 0x847E}, + {0x847F, 0x847F}, {0x8480, 0x8480}, {0x8481, 0x8481}, {0x8482, 0x8482}, {0x8483, 0x8483}, {0x8484, 0x8484}, {0x8485, 0x8485}, + {0x8486, 0x8486}, {0x8487, 0x8487}, {0x8488, 0x8488}, {0x8489, 0x8489}, {0x848A, 0x848A}, {0x848B, 0x848B}, {0x848C, 0x848C}, + {0x848D, 0x848D}, {0x848E, 0x848E}, {0x848F, 0x848F}, {0x8490, 0x8490}, {0x8491, 0x8491}, {0x8492, 0x8492}, {0x8493, 0x8493}, + {0x8494, 0x8494}, {0x8495, 0x8495}, {0x8496, 0x8496}, {0x8497, 0x8497}, {0x8498, 0x8498}, {0x8499, 0x8499}, {0x849A, 0x849A}, + {0x849B, 0x849B}, {0x849C, 0x849C}, {0x849D, 0x849D}, {0x849E, 0x849E}, {0x849F, 0x849F}, {0x84A0, 0x84A0}, {0x84A1, 0x84A1}, + {0x84A2, 0x84A2}, {0x84A3, 0x84A3}, {0x84A4, 0x84A4}, {0x84A5, 0x84A5}, {0x84A6, 0x84A6}, {0x84A7, 0x84A7}, {0x84A8, 0x84A8}, + {0x84A9, 0x84A9}, {0x84AA, 0x84AA}, {0x84AB, 0x84AB}, {0x84AC, 0x84AC}, {0x84AD, 0x84AD}, {0x84AE, 0x84AE}, {0x84AF, 0x84AF}, + {0x84B0, 0x84B0}, {0x84B1, 0x84B1}, {0x84B2, 0x84B2}, {0x84B3, 0x84B3}, {0x84B4, 0x84B4}, {0x84B5, 0x84B5}, {0x84B6, 0x84B6}, + {0x84B7, 0x84B7}, {0x84B8, 0x84B8}, {0x84B9, 0x84B9}, {0x84BA, 0x84BA}, {0x84BB, 0x84BB}, {0x84BC, 0x84BC}, {0x84BD, 0x84BD}, + {0x84BE, 0x84BE}, {0x84BF, 0x84BF}, {0x84C0, 0x84C0}, {0x84C1, 0x84C1}, {0x84C2, 0x84C2}, {0x84C3, 0x84C3}, {0x84C4, 0x84C4}, + {0x84C5, 0x84C5}, {0x84C6, 0x84C6}, {0x84C7, 0x84C7}, {0x84C8, 0x84C8}, {0x84C9, 0x84C9}, {0x84CA, 0x84CA}, {0x84CB, 0x84CB}, + {0x84CC, 0x84CC}, {0x84CD, 0x84CD}, {0x84CE, 0x84CE}, {0x84CF, 0x84CF}, {0x84D0, 0x84D0}, {0x84D1, 0x84D1}, {0x84D2, 0x84D2}, + {0x84D3, 0x84D3}, {0x84D4, 0x84D4}, {0x84D5, 0x84D5}, {0x84D6, 0x84D6}, {0x84D7, 0x84D7}, {0x84D8, 0x84D8}, {0x84D9, 0x84D9}, + {0x84DA, 0x84DA}, {0x84DB, 0x84DB}, {0x84DC, 0x84DC}, {0x84DD, 0x84DD}, {0x84DE, 0x84DE}, {0x84DF, 0x84DF}, {0x84E0, 0x84E0}, + {0x84E1, 0x84E1}, {0x84E2, 0x84E2}, {0x84E3, 0x84E3}, {0x84E4, 0x84E4}, {0x84E5, 0x84E5}, {0x84E6, 0x84E6}, {0x84E7, 0x84E7}, + {0x84E8, 0x84E8}, {0x84E9, 0x84E9}, {0x84EA, 0x84EA}, {0x84EB, 0x84EB}, {0x84EC, 0x84EC}, {0x84ED, 0x84ED}, {0x84EE, 0x84EE}, + {0x84EF, 0x84EF}, {0x84F0, 0x84F0}, {0x84F1, 0x84F1}, {0x84F2, 0x84F2}, {0x84F3, 0x84F3}, {0x84F4, 0x84F4}, {0x84F5, 0x84F5}, + {0x84F6, 0x84F6}, {0x84F7, 0x84F7}, {0x84F8, 0x84F8}, {0x84F9, 0x84F9}, {0x84FA, 0x84FA}, {0x84FB, 0x84FB}, {0x84FC, 0x84FC}, + {0x84FD, 0x84FD}, {0x84FE, 0x84FE}, {0x84FF, 0x84FF}, {0x8500, 0x8500}, {0x8501, 0x8501}, {0x8502, 0x8502}, {0x8503, 0x8503}, + {0x8504, 0x8504}, {0x8505, 0x8505}, {0x8506, 0x8506}, {0x8507, 0x8507}, {0x8508, 0x8508}, {0x8509, 0x8509}, {0x850A, 0x850A}, + {0x850B, 0x850B}, {0x850C, 0x850C}, {0x850D, 0x850D}, {0x850E, 0x850E}, {0x850F, 0x850F}, {0x8510, 0x8510}, {0x8511, 0x8511}, + {0x8512, 0x8512}, {0x8513, 0x8513}, {0x8514, 0x8514}, {0x8515, 0x8515}, {0x8516, 0x8516}, {0x8517, 0x8517}, {0x8518, 0x8518}, + {0x8519, 0x8519}, {0x851A, 0x851A}, {0x851B, 0x851B}, {0x851C, 0x851C}, {0x851D, 0x851D}, {0x851E, 0x851E}, {0x851F, 0x851F}, + {0x8520, 0x8520}, {0x8521, 0x8521}, {0x8522, 0x8522}, {0x8523, 0x8523}, {0x8524, 0x8524}, {0x8525, 0x8525}, {0x8526, 0x8526}, + {0x8527, 0x8527}, {0x8528, 0x8528}, {0x8529, 0x8529}, {0x852A, 0x852A}, {0x852B, 0x852B}, {0x852C, 0x852C}, {0x852D, 0x852D}, + {0x852E, 0x852E}, {0x852F, 0x852F}, {0x8530, 0x8530}, {0x8531, 0x8531}, {0x8532, 0x8532}, {0x8533, 0x8533}, {0x8534, 0x8534}, + {0x8535, 0x8535}, {0x8536, 0x8536}, {0x8537, 0x8537}, {0x8538, 0x8538}, {0x8539, 0x8539}, {0x853A, 0x853A}, {0x853B, 0x853B}, + {0x853C, 0x853C}, {0x853D, 0x853D}, {0x853E, 0x853E}, {0x853F, 0x853F}, {0x8540, 0x8540}, {0x8541, 0x8541}, {0x8542, 0x8542}, + {0x8543, 0x8543}, {0x8544, 0x8544}, {0x8545, 0x8545}, {0x8546, 0x8546}, {0x8547, 0x8547}, {0x8548, 0x8548}, {0x8549, 0x8549}, + {0x854A, 0x854A}, {0x854B, 0x854B}, {0x854C, 0x854C}, {0x854D, 0x854D}, {0x854E, 0x854E}, {0x854F, 0x854F}, {0x8550, 0x8550}, + {0x8551, 0x8551}, {0x8552, 0x8552}, {0x8553, 0x8553}, {0x8554, 0x8554}, {0x8555, 0x8555}, {0x8556, 0x8556}, {0x8557, 0x8557}, + {0x8558, 0x8558}, {0x8559, 0x8559}, {0x855A, 0x855A}, {0x855B, 0x855B}, {0x855C, 0x855C}, {0x855D, 0x855D}, {0x855E, 0x855E}, + {0x855F, 0x855F}, {0x8560, 0x8560}, {0x8561, 0x8561}, {0x8562, 0x8562}, {0x8563, 0x8563}, {0x8564, 0x8564}, {0x8565, 0x8565}, + {0x8566, 0x8566}, {0x8567, 0x8567}, {0x8568, 0x8568}, {0x8569, 0x8569}, {0x856A, 0x856A}, {0x856B, 0x856B}, {0x856C, 0x856C}, + {0x856D, 0x856D}, {0x856E, 0x856E}, {0x856F, 0x856F}, {0x8570, 0x8570}, {0x8571, 0x8571}, {0x8572, 0x8572}, {0x8573, 0x8573}, + {0x8574, 0x8574}, {0x8575, 0x8575}, {0x8576, 0x8576}, {0x8577, 0x8577}, {0x8578, 0x8578}, {0x8579, 0x8579}, {0x857A, 0x857A}, + {0x857B, 0x857B}, {0x857C, 0x857C}, {0x857D, 0x857D}, {0x857E, 0x857E}, {0x857F, 0x857F}, {0x8580, 0x8580}, {0x8581, 0x8581}, + {0x8582, 0x8582}, {0x8583, 0x8583}, {0x8584, 0x8584}, {0x8585, 0x8585}, {0x8586, 0x8586}, {0x8587, 0x8587}, {0x8588, 0x8588}, + {0x8589, 0x8589}, {0x858A, 0x858A}, {0x858B, 0x858B}, {0x858C, 0x858C}, {0x858D, 0x858D}, {0x858E, 0x858E}, {0x858F, 0x858F}, + {0x8590, 0x8590}, {0x8591, 0x8591}, {0x8592, 0x8592}, {0x8593, 0x8593}, {0x8594, 0x8594}, {0x8595, 0x8595}, {0x8596, 0x8596}, + {0x8597, 0x8597}, {0x8598, 0x8598}, {0x8599, 0x8599}, {0x859A, 0x859A}, {0x859B, 0x859B}, {0x859C, 0x859C}, {0x859D, 0x859D}, + {0x859E, 0x859E}, {0x859F, 0x859F}, {0x85A0, 0x85A0}, {0x85A1, 0x85A1}, {0x85A2, 0x85A2}, {0x85A3, 0x85A3}, {0x85A4, 0x85A4}, + {0x85A5, 0x85A5}, {0x85A6, 0x85A6}, {0x85A7, 0x85A7}, {0x85A8, 0x85A8}, {0x85A9, 0x85A9}, {0x85AA, 0x85AA}, {0x85AB, 0x85AB}, + {0x85AC, 0x85AC}, {0x85AD, 0x85AD}, {0x85AE, 0x85AE}, {0x85AF, 0x85AF}, {0x85B0, 0x85B0}, {0x85B1, 0x85B1}, {0x85B2, 0x85B2}, + {0x85B3, 0x85B3}, {0x85B4, 0x85B4}, {0x85B5, 0x85B5}, {0x85B6, 0x85B6}, {0x85B7, 0x85B7}, {0x85B8, 0x85B8}, {0x85B9, 0x85B9}, + {0x85BA, 0x85BA}, {0x85BB, 0x85BB}, {0x85BC, 0x85BC}, {0x85BD, 0x85BD}, {0x85BE, 0x85BE}, {0x85BF, 0x85BF}, {0x85C0, 0x85C0}, + {0x85C1, 0x85C1}, {0x85C2, 0x85C2}, {0x85C3, 0x85C3}, {0x85C4, 0x85C4}, {0x85C5, 0x85C5}, {0x85C6, 0x85C6}, {0x85C7, 0x85C7}, + {0x85C8, 0x85C8}, {0x85C9, 0x85C9}, {0x85CA, 0x85CA}, {0x85CB, 0x85CB}, {0x85CC, 0x85CC}, {0x85CD, 0x85CD}, {0x85CE, 0x85CE}, + {0x85CF, 0x85CF}, {0x85D0, 0x85D0}, {0x85D1, 0x85D1}, {0x85D2, 0x85D2}, {0x85D3, 0x85D3}, {0x85D4, 0x85D4}, {0x85D5, 0x85D5}, + {0x85D6, 0x85D6}, {0x85D7, 0x85D7}, {0x85D8, 0x85D8}, {0x85D9, 0x85D9}, {0x85DA, 0x85DA}, {0x85DB, 0x85DB}, {0x85DC, 0x85DC}, + {0x85DD, 0x85DD}, {0x85DE, 0x85DE}, {0x85DF, 0x85DF}, {0x85E0, 0x85E0}, {0x85E1, 0x85E1}, {0x85E2, 0x85E2}, {0x85E3, 0x85E3}, + {0x85E4, 0x85E4}, {0x85E5, 0x85E5}, {0x85E6, 0x85E6}, {0x85E7, 0x85E7}, {0x85E8, 0x85E8}, {0x85E9, 0x85E9}, {0x85EA, 0x85EA}, + {0x85EB, 0x85EB}, {0x85EC, 0x85EC}, {0x85ED, 0x85ED}, {0x85EE, 0x85EE}, {0x85EF, 0x85EF}, {0x85F0, 0x85F0}, {0x85F1, 0x85F1}, + {0x85F2, 0x85F2}, {0x85F3, 0x85F3}, {0x85F4, 0x85F4}, {0x85F5, 0x85F5}, {0x85F6, 0x85F6}, {0x85F7, 0x85F7}, {0x85F8, 0x85F8}, + {0x85F9, 0x85F9}, {0x85FA, 0x85FA}, {0x85FB, 0x85FB}, {0x85FC, 0x85FC}, {0x85FD, 0x85FD}, {0x85FE, 0x85FE}, {0x85FF, 0x85FF}, + {0x8600, 0x8600}, {0x8601, 0x8601}, {0x8602, 0x8602}, {0x8603, 0x8603}, {0x8604, 0x8604}, {0x8605, 0x8605}, {0x8606, 0x8606}, + {0x8607, 0x8607}, {0x8608, 0x8608}, {0x8609, 0x8609}, {0x860A, 0x860A}, {0x860B, 0x860B}, {0x860C, 0x860C}, {0x860D, 0x860D}, + {0x860E, 0x860E}, {0x860F, 0x860F}, {0x8610, 0x8610}, {0x8611, 0x8611}, {0x8612, 0x8612}, {0x8613, 0x8613}, {0x8614, 0x8614}, + {0x8615, 0x8615}, {0x8616, 0x8616}, {0x8617, 0x8617}, {0x8618, 0x8618}, {0x8619, 0x8619}, {0x861A, 0x861A}, {0x861B, 0x861B}, + {0x861C, 0x861C}, {0x861D, 0x861D}, {0x861E, 0x861E}, {0x861F, 0x861F}, {0x8620, 0x8620}, {0x8621, 0x8621}, {0x8622, 0x8622}, + {0x8623, 0x8623}, {0x8624, 0x8624}, {0x8625, 0x8625}, {0x8626, 0x8626}, {0x8627, 0x8627}, {0x8628, 0x8628}, {0x8629, 0x8629}, + {0x862A, 0x862A}, {0x862B, 0x862B}, {0x862C, 0x862C}, {0x862D, 0x862D}, {0x862E, 0x862E}, {0x862F, 0x862F}, {0x8630, 0x8630}, + {0x8631, 0x8631}, {0x8632, 0x8632}, {0x8633, 0x8633}, {0x8634, 0x8634}, {0x8635, 0x8635}, {0x8636, 0x8636}, {0x8637, 0x8637}, + {0x8638, 0x8638}, {0x8639, 0x8639}, {0x863A, 0x863A}, {0x863B, 0x863B}, {0x863C, 0x863C}, {0x863D, 0x863D}, {0x863E, 0x863E}, + {0x863F, 0x863F}, {0x8640, 0x8640}, {0x8641, 0x8641}, {0x8642, 0x8642}, {0x8643, 0x8643}, {0x8644, 0x8644}, {0x8645, 0x8645}, + {0x8646, 0x8646}, {0x8647, 0x8647}, {0x8648, 0x8648}, {0x8649, 0x8649}, {0x864A, 0x864A}, {0x864B, 0x864B}, {0x864C, 0x864C}, + {0x864D, 0x864D}, {0x864E, 0x864E}, {0x864F, 0x864F}, {0x8650, 0x8650}, {0x8651, 0x8651}, {0x8652, 0x8652}, {0x8653, 0x8653}, + {0x8654, 0x8654}, {0x8655, 0x8655}, {0x8656, 0x8656}, {0x8657, 0x8657}, {0x8658, 0x8658}, {0x8659, 0x8659}, {0x865A, 0x865A}, + {0x865B, 0x865B}, {0x865C, 0x865C}, {0x865D, 0x865D}, {0x865E, 0x865E}, {0x865F, 0x865F}, {0x8660, 0x8660}, {0x8661, 0x8661}, + {0x8662, 0x8662}, {0x8663, 0x8663}, {0x8664, 0x8664}, {0x8665, 0x8665}, {0x8666, 0x8666}, {0x8667, 0x8667}, {0x8668, 0x8668}, + {0x8669, 0x8669}, {0x866A, 0x866A}, {0x866B, 0x866B}, {0x866C, 0x866C}, {0x866D, 0x866D}, {0x866E, 0x866E}, {0x866F, 0x866F}, + {0x8670, 0x8670}, {0x8671, 0x8671}, {0x8672, 0x8672}, {0x8673, 0x8673}, {0x8674, 0x8674}, {0x8675, 0x8675}, {0x8676, 0x8676}, + {0x8677, 0x8677}, {0x8678, 0x8678}, {0x8679, 0x8679}, {0x867A, 0x867A}, {0x867B, 0x867B}, {0x867C, 0x867C}, {0x867D, 0x867D}, + {0x867E, 0x867E}, {0x867F, 0x867F}, {0x8680, 0x8680}, {0x8681, 0x8681}, {0x8682, 0x8682}, {0x8683, 0x8683}, {0x8684, 0x8684}, + {0x8685, 0x8685}, {0x8686, 0x8686}, {0x8687, 0x8687}, {0x8688, 0x8688}, {0x8689, 0x8689}, {0x868A, 0x868A}, {0x868B, 0x868B}, + {0x868C, 0x868C}, {0x868D, 0x868D}, {0x868E, 0x868E}, {0x868F, 0x868F}, {0x8690, 0x8690}, {0x8691, 0x8691}, {0x8692, 0x8692}, + {0x8693, 0x8693}, {0x8694, 0x8694}, {0x8695, 0x8695}, {0x8696, 0x8696}, {0x8697, 0x8697}, {0x8698, 0x8698}, {0x8699, 0x8699}, + {0x869A, 0x869A}, {0x869B, 0x869B}, {0x869C, 0x869C}, {0x869D, 0x869D}, {0x869E, 0x869E}, {0x869F, 0x869F}, {0x86A0, 0x86A0}, + {0x86A1, 0x86A1}, {0x86A2, 0x86A2}, {0x86A3, 0x86A3}, {0x86A4, 0x86A4}, {0x86A5, 0x86A5}, {0x86A6, 0x86A6}, {0x86A7, 0x86A7}, + {0x86A8, 0x86A8}, {0x86A9, 0x86A9}, {0x86AA, 0x86AA}, {0x86AB, 0x86AB}, {0x86AC, 0x86AC}, {0x86AD, 0x86AD}, {0x86AE, 0x86AE}, + {0x86AF, 0x86AF}, {0x86B0, 0x86B0}, {0x86B1, 0x86B1}, {0x86B2, 0x86B2}, {0x86B3, 0x86B3}, {0x86B4, 0x86B4}, {0x86B5, 0x86B5}, + {0x86B6, 0x86B6}, {0x86B7, 0x86B7}, {0x86B8, 0x86B8}, {0x86B9, 0x86B9}, {0x86BA, 0x86BA}, {0x86BB, 0x86BB}, {0x86BC, 0x86BC}, + {0x86BD, 0x86BD}, {0x86BE, 0x86BE}, {0x86BF, 0x86BF}, {0x86C0, 0x86C0}, {0x86C1, 0x86C1}, {0x86C2, 0x86C2}, {0x86C3, 0x86C3}, + {0x86C4, 0x86C4}, {0x86C5, 0x86C5}, {0x86C6, 0x86C6}, {0x86C7, 0x86C7}, {0x86C8, 0x86C8}, {0x86C9, 0x86C9}, {0x86CA, 0x86CA}, + {0x86CB, 0x86CB}, {0x86CC, 0x86CC}, {0x86CD, 0x86CD}, {0x86CE, 0x86CE}, {0x86CF, 0x86CF}, {0x86D0, 0x86D0}, {0x86D1, 0x86D1}, + {0x86D2, 0x86D2}, {0x86D3, 0x86D3}, {0x86D4, 0x86D4}, {0x86D5, 0x86D5}, {0x86D6, 0x86D6}, {0x86D7, 0x86D7}, {0x86D8, 0x86D8}, + {0x86D9, 0x86D9}, {0x86DA, 0x86DA}, {0x86DB, 0x86DB}, {0x86DC, 0x86DC}, {0x86DD, 0x86DD}, {0x86DE, 0x86DE}, {0x86DF, 0x86DF}, + {0x86E0, 0x86E0}, {0x86E1, 0x86E1}, {0x86E2, 0x86E2}, {0x86E3, 0x86E3}, {0x86E4, 0x86E4}, {0x86E5, 0x86E5}, {0x86E6, 0x86E6}, + {0x86E7, 0x86E7}, {0x86E8, 0x86E8}, {0x86E9, 0x86E9}, {0x86EA, 0x86EA}, {0x86EB, 0x86EB}, {0x86EC, 0x86EC}, {0x86ED, 0x86ED}, + {0x86EE, 0x86EE}, {0x86EF, 0x86EF}, {0x86F0, 0x86F0}, {0x86F1, 0x86F1}, {0x86F2, 0x86F2}, {0x86F3, 0x86F3}, {0x86F4, 0x86F4}, + {0x86F5, 0x86F5}, {0x86F6, 0x86F6}, {0x86F7, 0x86F7}, {0x86F8, 0x86F8}, {0x86F9, 0x86F9}, {0x86FA, 0x86FA}, {0x86FB, 0x86FB}, + {0x86FC, 0x86FC}, {0x86FD, 0x86FD}, {0x86FE, 0x86FE}, {0x86FF, 0x86FF}, {0x8700, 0x8700}, {0x8701, 0x8701}, {0x8702, 0x8702}, + {0x8703, 0x8703}, {0x8704, 0x8704}, {0x8705, 0x8705}, {0x8706, 0x8706}, {0x8707, 0x8707}, {0x8708, 0x8708}, {0x8709, 0x8709}, + {0x870A, 0x870A}, {0x870B, 0x870B}, {0x870C, 0x870C}, {0x870D, 0x870D}, {0x870E, 0x870E}, {0x870F, 0x870F}, {0x8710, 0x8710}, + {0x8711, 0x8711}, {0x8712, 0x8712}, {0x8713, 0x8713}, {0x8714, 0x8714}, {0x8715, 0x8715}, {0x8716, 0x8716}, {0x8717, 0x8717}, + {0x8718, 0x8718}, {0x8719, 0x8719}, {0x871A, 0x871A}, {0x871B, 0x871B}, {0x871C, 0x871C}, {0x871D, 0x871D}, {0x871E, 0x871E}, + {0x871F, 0x871F}, {0x8720, 0x8720}, {0x8721, 0x8721}, {0x8722, 0x8722}, {0x8723, 0x8723}, {0x8724, 0x8724}, {0x8725, 0x8725}, + {0x8726, 0x8726}, {0x8727, 0x8727}, {0x8728, 0x8728}, {0x8729, 0x8729}, {0x872A, 0x872A}, {0x872B, 0x872B}, {0x872C, 0x872C}, + {0x872D, 0x872D}, {0x872E, 0x872E}, {0x872F, 0x872F}, {0x8730, 0x8730}, {0x8731, 0x8731}, {0x8732, 0x8732}, {0x8733, 0x8733}, + {0x8734, 0x8734}, {0x8735, 0x8735}, {0x8736, 0x8736}, {0x8737, 0x8737}, {0x8738, 0x8738}, {0x8739, 0x8739}, {0x873A, 0x873A}, + {0x873B, 0x873B}, {0x873C, 0x873C}, {0x873D, 0x873D}, {0x873E, 0x873E}, {0x873F, 0x873F}, {0x8740, 0x8740}, {0x8741, 0x8741}, + {0x8742, 0x8742}, {0x8743, 0x8743}, {0x8744, 0x8744}, {0x8745, 0x8745}, {0x8746, 0x8746}, {0x8747, 0x8747}, {0x8748, 0x8748}, + {0x8749, 0x8749}, {0x874A, 0x874A}, {0x874B, 0x874B}, {0x874C, 0x874C}, {0x874D, 0x874D}, {0x874E, 0x874E}, {0x874F, 0x874F}, + {0x8750, 0x8750}, {0x8751, 0x8751}, {0x8752, 0x8752}, {0x8753, 0x8753}, {0x8754, 0x8754}, {0x8755, 0x8755}, {0x8756, 0x8756}, + {0x8757, 0x8757}, {0x8758, 0x8758}, {0x8759, 0x8759}, {0x875A, 0x875A}, {0x875B, 0x875B}, {0x875C, 0x875C}, {0x875D, 0x875D}, + {0x875E, 0x875E}, {0x875F, 0x875F}, {0x8760, 0x8760}, {0x8761, 0x8761}, {0x8762, 0x8762}, {0x8763, 0x8763}, {0x8764, 0x8764}, + {0x8765, 0x8765}, {0x8766, 0x8766}, {0x8767, 0x8767}, {0x8768, 0x8768}, {0x8769, 0x8769}, {0x876A, 0x876A}, {0x876B, 0x876B}, + {0x876C, 0x876C}, {0x876D, 0x876D}, {0x876E, 0x876E}, {0x876F, 0x876F}, {0x8770, 0x8770}, {0x8771, 0x8771}, {0x8772, 0x8772}, + {0x8773, 0x8773}, {0x8774, 0x8774}, {0x8775, 0x8775}, {0x8776, 0x8776}, {0x8777, 0x8777}, {0x8778, 0x8778}, {0x8779, 0x8779}, + {0x877A, 0x877A}, {0x877B, 0x877B}, {0x877C, 0x877C}, {0x877D, 0x877D}, {0x877E, 0x877E}, {0x877F, 0x877F}, {0x8780, 0x8780}, + {0x8781, 0x8781}, {0x8782, 0x8782}, {0x8783, 0x8783}, {0x8784, 0x8784}, {0x8785, 0x8785}, {0x8786, 0x8786}, {0x8787, 0x8787}, + {0x8788, 0x8788}, {0x8789, 0x8789}, {0x878A, 0x878A}, {0x878B, 0x878B}, {0x878C, 0x878C}, {0x878D, 0x878D}, {0x878E, 0x878E}, + {0x878F, 0x878F}, {0x8790, 0x8790}, {0x8791, 0x8791}, {0x8792, 0x8792}, {0x8793, 0x8793}, {0x8794, 0x8794}, {0x8795, 0x8795}, + {0x8796, 0x8796}, {0x8797, 0x8797}, {0x8798, 0x8798}, {0x8799, 0x8799}, {0x879A, 0x879A}, {0x879B, 0x879B}, {0x879C, 0x879C}, + {0x879D, 0x879D}, {0x879E, 0x879E}, {0x879F, 0x879F}, {0x87A0, 0x87A0}, {0x87A1, 0x87A1}, {0x87A2, 0x87A2}, {0x87A3, 0x87A3}, + {0x87A4, 0x87A4}, {0x87A5, 0x87A5}, {0x87A6, 0x87A6}, {0x87A7, 0x87A7}, {0x87A8, 0x87A8}, {0x87A9, 0x87A9}, {0x87AA, 0x87AA}, + {0x87AB, 0x87AB}, {0x87AC, 0x87AC}, {0x87AD, 0x87AD}, {0x87AE, 0x87AE}, {0x87AF, 0x87AF}, {0x87B0, 0x87B0}, {0x87B1, 0x87B1}, + {0x87B2, 0x87B2}, {0x87B3, 0x87B3}, {0x87B4, 0x87B4}, {0x87B5, 0x87B5}, {0x87B6, 0x87B6}, {0x87B7, 0x87B7}, {0x87B8, 0x87B8}, + {0x87B9, 0x87B9}, {0x87BA, 0x87BA}, {0x87BB, 0x87BB}, {0x87BC, 0x87BC}, {0x87BD, 0x87BD}, {0x87BE, 0x87BE}, {0x87BF, 0x87BF}, + {0x87C0, 0x87C0}, {0x87C1, 0x87C1}, {0x87C2, 0x87C2}, {0x87C3, 0x87C3}, {0x87C4, 0x87C4}, {0x87C5, 0x87C5}, {0x87C6, 0x87C6}, + {0x87C7, 0x87C7}, {0x87C8, 0x87C8}, {0x87C9, 0x87C9}, {0x87CA, 0x87CA}, {0x87CB, 0x87CB}, {0x87CC, 0x87CC}, {0x87CD, 0x87CD}, + {0x87CE, 0x87CE}, {0x87CF, 0x87CF}, {0x87D0, 0x87D0}, {0x87D1, 0x87D1}, {0x87D2, 0x87D2}, {0x87D3, 0x87D3}, {0x87D4, 0x87D4}, + {0x87D5, 0x87D5}, {0x87D6, 0x87D6}, {0x87D7, 0x87D7}, {0x87D8, 0x87D8}, {0x87D9, 0x87D9}, {0x87DA, 0x87DA}, {0x87DB, 0x87DB}, + {0x87DC, 0x87DC}, {0x87DD, 0x87DD}, {0x87DE, 0x87DE}, {0x87DF, 0x87DF}, {0x87E0, 0x87E0}, {0x87E1, 0x87E1}, {0x87E2, 0x87E2}, + {0x87E3, 0x87E3}, {0x87E4, 0x87E4}, {0x87E5, 0x87E5}, {0x87E6, 0x87E6}, {0x87E7, 0x87E7}, {0x87E8, 0x87E8}, {0x87E9, 0x87E9}, + {0x87EA, 0x87EA}, {0x87EB, 0x87EB}, {0x87EC, 0x87EC}, {0x87ED, 0x87ED}, {0x87EE, 0x87EE}, {0x87EF, 0x87EF}, {0x87F0, 0x87F0}, + {0x87F1, 0x87F1}, {0x87F2, 0x87F2}, {0x87F3, 0x87F3}, {0x87F4, 0x87F4}, {0x87F5, 0x87F5}, {0x87F6, 0x87F6}, {0x87F7, 0x87F7}, + {0x87F8, 0x87F8}, {0x87F9, 0x87F9}, {0x87FA, 0x87FA}, {0x87FB, 0x87FB}, {0x87FC, 0x87FC}, {0x87FD, 0x87FD}, {0x87FE, 0x87FE}, + {0x87FF, 0x87FF}, {0x8800, 0x8800}, {0x8801, 0x8801}, {0x8802, 0x8802}, {0x8803, 0x8803}, {0x8804, 0x8804}, {0x8805, 0x8805}, + {0x8806, 0x8806}, {0x8807, 0x8807}, {0x8808, 0x8808}, {0x8809, 0x8809}, {0x880A, 0x880A}, {0x880B, 0x880B}, {0x880C, 0x880C}, + {0x880D, 0x880D}, {0x880E, 0x880E}, {0x880F, 0x880F}, {0x8810, 0x8810}, {0x8811, 0x8811}, {0x8812, 0x8812}, {0x8813, 0x8813}, + {0x8814, 0x8814}, {0x8815, 0x8815}, {0x8816, 0x8816}, {0x8817, 0x8817}, {0x8818, 0x8818}, {0x8819, 0x8819}, {0x881A, 0x881A}, + {0x881B, 0x881B}, {0x881C, 0x881C}, {0x881D, 0x881D}, {0x881E, 0x881E}, {0x881F, 0x881F}, {0x8820, 0x8820}, {0x8821, 0x8821}, + {0x8822, 0x8822}, {0x8823, 0x8823}, {0x8824, 0x8824}, {0x8825, 0x8825}, {0x8826, 0x8826}, {0x8827, 0x8827}, {0x8828, 0x8828}, + {0x8829, 0x8829}, {0x882A, 0x882A}, {0x882B, 0x882B}, {0x882C, 0x882C}, {0x882D, 0x882D}, {0x882E, 0x882E}, {0x882F, 0x882F}, + {0x8830, 0x8830}, {0x8831, 0x8831}, {0x8832, 0x8832}, {0x8833, 0x8833}, {0x8834, 0x8834}, {0x8835, 0x8835}, {0x8836, 0x8836}, + {0x8837, 0x8837}, {0x8838, 0x8838}, {0x8839, 0x8839}, {0x883A, 0x883A}, {0x883B, 0x883B}, {0x883C, 0x883C}, {0x883D, 0x883D}, + {0x883E, 0x883E}, {0x883F, 0x883F}, {0x8840, 0x8840}, {0x8841, 0x8841}, {0x8842, 0x8842}, {0x8843, 0x8843}, {0x8844, 0x8844}, + {0x8845, 0x8845}, {0x8846, 0x8846}, {0x8847, 0x8847}, {0x8848, 0x8848}, {0x8849, 0x8849}, {0x884A, 0x884A}, {0x884B, 0x884B}, + {0x884C, 0x884C}, {0x884D, 0x884D}, {0x884E, 0x884E}, {0x884F, 0x884F}, {0x8850, 0x8850}, {0x8851, 0x8851}, {0x8852, 0x8852}, + {0x8853, 0x8853}, {0x8854, 0x8854}, {0x8855, 0x8855}, {0x8856, 0x8856}, {0x8857, 0x8857}, {0x8858, 0x8858}, {0x8859, 0x8859}, + {0x885A, 0x885A}, {0x885B, 0x885B}, {0x885C, 0x885C}, {0x885D, 0x885D}, {0x885E, 0x885E}, {0x885F, 0x885F}, {0x8860, 0x8860}, + {0x8861, 0x8861}, {0x8862, 0x8862}, {0x8863, 0x8863}, {0x8864, 0x8864}, {0x8865, 0x8865}, {0x8866, 0x8866}, {0x8867, 0x8867}, + {0x8868, 0x8868}, {0x8869, 0x8869}, {0x886A, 0x886A}, {0x886B, 0x886B}, {0x886C, 0x886C}, {0x886D, 0x886D}, {0x886E, 0x886E}, + {0x886F, 0x886F}, {0x8870, 0x8870}, {0x8871, 0x8871}, {0x8872, 0x8872}, {0x8873, 0x8873}, {0x8874, 0x8874}, {0x8875, 0x8875}, + {0x8876, 0x8876}, {0x8877, 0x8877}, {0x8878, 0x8878}, {0x8879, 0x8879}, {0x887A, 0x887A}, {0x887B, 0x887B}, {0x887C, 0x887C}, + {0x887D, 0x887D}, {0x887E, 0x887E}, {0x887F, 0x887F}, {0x8880, 0x8880}, {0x8881, 0x8881}, {0x8882, 0x8882}, {0x8883, 0x8883}, + {0x8884, 0x8884}, {0x8885, 0x8885}, {0x8886, 0x8886}, {0x8887, 0x8887}, {0x8888, 0x8888}, {0x8889, 0x8889}, {0x888A, 0x888A}, + {0x888B, 0x888B}, {0x888C, 0x888C}, {0x888D, 0x888D}, {0x888E, 0x888E}, {0x888F, 0x888F}, {0x8890, 0x8890}, {0x8891, 0x8891}, + {0x8892, 0x8892}, {0x8893, 0x8893}, {0x8894, 0x8894}, {0x8895, 0x8895}, {0x8896, 0x8896}, {0x8897, 0x8897}, {0x8898, 0x8898}, + {0x8899, 0x8899}, {0x889A, 0x889A}, {0x889B, 0x889B}, {0x889C, 0x889C}, {0x889D, 0x889D}, {0x889E, 0x889E}, {0x889F, 0x889F}, + {0x88A0, 0x88A0}, {0x88A1, 0x88A1}, {0x88A2, 0x88A2}, {0x88A3, 0x88A3}, {0x88A4, 0x88A4}, {0x88A5, 0x88A5}, {0x88A6, 0x88A6}, + {0x88A7, 0x88A7}, {0x88A8, 0x88A8}, {0x88A9, 0x88A9}, {0x88AA, 0x88AA}, {0x88AB, 0x88AB}, {0x88AC, 0x88AC}, {0x88AD, 0x88AD}, + {0x88AE, 0x88AE}, {0x88AF, 0x88AF}, {0x88B0, 0x88B0}, {0x88B1, 0x88B1}, {0x88B2, 0x88B2}, {0x88B3, 0x88B3}, {0x88B4, 0x88B4}, + {0x88B5, 0x88B5}, {0x88B6, 0x88B6}, {0x88B7, 0x88B7}, {0x88B8, 0x88B8}, {0x88B9, 0x88B9}, {0x88BA, 0x88BA}, {0x88BB, 0x88BB}, + {0x88BC, 0x88BC}, {0x88BD, 0x88BD}, {0x88BE, 0x88BE}, {0x88BF, 0x88BF}, {0x88C0, 0x88C0}, {0x88C1, 0x88C1}, {0x88C2, 0x88C2}, + {0x88C3, 0x88C3}, {0x88C4, 0x88C4}, {0x88C5, 0x88C5}, {0x88C6, 0x88C6}, {0x88C7, 0x88C7}, {0x88C8, 0x88C8}, {0x88C9, 0x88C9}, + {0x88CA, 0x88CA}, {0x88CB, 0x88CB}, {0x88CC, 0x88CC}, {0x88CD, 0x88CD}, {0x88CE, 0x88CE}, {0x88CF, 0x88CF}, {0x88D0, 0x88D0}, + {0x88D1, 0x88D1}, {0x88D2, 0x88D2}, {0x88D3, 0x88D3}, {0x88D4, 0x88D4}, {0x88D5, 0x88D5}, {0x88D6, 0x88D6}, {0x88D7, 0x88D7}, + {0x88D8, 0x88D8}, {0x88D9, 0x88D9}, {0x88DA, 0x88DA}, {0x88DB, 0x88DB}, {0x88DC, 0x88DC}, {0x88DD, 0x88DD}, {0x88DE, 0x88DE}, + {0x88DF, 0x88DF}, {0x88E0, 0x88E0}, {0x88E1, 0x88E1}, {0x88E2, 0x88E2}, {0x88E3, 0x88E3}, {0x88E4, 0x88E4}, {0x88E5, 0x88E5}, + {0x88E6, 0x88E6}, {0x88E7, 0x88E7}, {0x88E8, 0x88E8}, {0x88E9, 0x88E9}, {0x88EA, 0x88EA}, {0x88EB, 0x88EB}, {0x88EC, 0x88EC}, + {0x88ED, 0x88ED}, {0x88EE, 0x88EE}, {0x88EF, 0x88EF}, {0x88F0, 0x88F0}, {0x88F1, 0x88F1}, {0x88F2, 0x88F2}, {0x88F3, 0x88F3}, + {0x88F4, 0x88F4}, {0x88F5, 0x88F5}, {0x88F6, 0x88F6}, {0x88F7, 0x88F7}, {0x88F8, 0x88F8}, {0x88F9, 0x88F9}, {0x88FA, 0x88FA}, + {0x88FB, 0x88FB}, {0x88FC, 0x88FC}, {0x88FD, 0x88FD}, {0x88FE, 0x88FE}, {0x88FF, 0x88FF}, {0x8900, 0x8900}, {0x8901, 0x8901}, + {0x8902, 0x8902}, {0x8903, 0x8903}, {0x8904, 0x8904}, {0x8905, 0x8905}, {0x8906, 0x8906}, {0x8907, 0x8907}, {0x8908, 0x8908}, + {0x8909, 0x8909}, {0x890A, 0x890A}, {0x890B, 0x890B}, {0x890C, 0x890C}, {0x890D, 0x890D}, {0x890E, 0x890E}, {0x890F, 0x890F}, + {0x8910, 0x8910}, {0x8911, 0x8911}, {0x8912, 0x8912}, {0x8913, 0x8913}, {0x8914, 0x8914}, {0x8915, 0x8915}, {0x8916, 0x8916}, + {0x8917, 0x8917}, {0x8918, 0x8918}, {0x8919, 0x8919}, {0x891A, 0x891A}, {0x891B, 0x891B}, {0x891C, 0x891C}, {0x891D, 0x891D}, + {0x891E, 0x891E}, {0x891F, 0x891F}, {0x8920, 0x8920}, {0x8921, 0x8921}, {0x8922, 0x8922}, {0x8923, 0x8923}, {0x8924, 0x8924}, + {0x8925, 0x8925}, {0x8926, 0x8926}, {0x8927, 0x8927}, {0x8928, 0x8928}, {0x8929, 0x8929}, {0x892A, 0x892A}, {0x892B, 0x892B}, + {0x892C, 0x892C}, {0x892D, 0x892D}, {0x892E, 0x892E}, {0x892F, 0x892F}, {0x8930, 0x8930}, {0x8931, 0x8931}, {0x8932, 0x8932}, + {0x8933, 0x8933}, {0x8934, 0x8934}, {0x8935, 0x8935}, {0x8936, 0x8936}, {0x8937, 0x8937}, {0x8938, 0x8938}, {0x8939, 0x8939}, + {0x893A, 0x893A}, {0x893B, 0x893B}, {0x893C, 0x893C}, {0x893D, 0x893D}, {0x893E, 0x893E}, {0x893F, 0x893F}, {0x8940, 0x8940}, + {0x8941, 0x8941}, {0x8942, 0x8942}, {0x8943, 0x8943}, {0x8944, 0x8944}, {0x8945, 0x8945}, {0x8946, 0x8946}, {0x8947, 0x8947}, + {0x8948, 0x8948}, {0x8949, 0x8949}, {0x894A, 0x894A}, {0x894B, 0x894B}, {0x894C, 0x894C}, {0x894D, 0x894D}, {0x894E, 0x894E}, + {0x894F, 0x894F}, {0x8950, 0x8950}, {0x8951, 0x8951}, {0x8952, 0x8952}, {0x8953, 0x8953}, {0x8954, 0x8954}, {0x8955, 0x8955}, + {0x8956, 0x8956}, {0x8957, 0x8957}, {0x8958, 0x8958}, {0x8959, 0x8959}, {0x895A, 0x895A}, {0x895B, 0x895B}, {0x895C, 0x895C}, + {0x895D, 0x895D}, {0x895E, 0x895E}, {0x895F, 0x895F}, {0x8960, 0x8960}, {0x8961, 0x8961}, {0x8962, 0x8962}, {0x8963, 0x8963}, + {0x8964, 0x8964}, {0x8965, 0x8965}, {0x8966, 0x8966}, {0x8967, 0x8967}, {0x8968, 0x8968}, {0x8969, 0x8969}, {0x896A, 0x896A}, + {0x896B, 0x896B}, {0x896C, 0x896C}, {0x896D, 0x896D}, {0x896E, 0x896E}, {0x896F, 0x896F}, {0x8970, 0x8970}, {0x8971, 0x8971}, + {0x8972, 0x8972}, {0x8973, 0x8973}, {0x8974, 0x8974}, {0x8975, 0x8975}, {0x8976, 0x8976}, {0x8977, 0x8977}, {0x8978, 0x8978}, + {0x8979, 0x8979}, {0x897A, 0x897A}, {0x897B, 0x897B}, {0x897C, 0x897C}, {0x897D, 0x897D}, {0x897E, 0x897E}, {0x897F, 0x897F}, + {0x8980, 0x8980}, {0x8981, 0x8981}, {0x8982, 0x8982}, {0x8983, 0x8983}, {0x8984, 0x8984}, {0x8985, 0x8985}, {0x8986, 0x8986}, + {0x8987, 0x8987}, {0x8988, 0x8988}, {0x8989, 0x8989}, {0x898A, 0x898A}, {0x898B, 0x898B}, {0x898C, 0x898C}, {0x898D, 0x898D}, + {0x898E, 0x898E}, {0x898F, 0x898F}, {0x8990, 0x8990}, {0x8991, 0x8991}, {0x8992, 0x8992}, {0x8993, 0x8993}, {0x8994, 0x8994}, + {0x8995, 0x8995}, {0x8996, 0x8996}, {0x8997, 0x8997}, {0x8998, 0x8998}, {0x8999, 0x8999}, {0x899A, 0x899A}, {0x899B, 0x899B}, + {0x899C, 0x899C}, {0x899D, 0x899D}, {0x899E, 0x899E}, {0x899F, 0x899F}, {0x89A0, 0x89A0}, {0x89A1, 0x89A1}, {0x89A2, 0x89A2}, + {0x89A3, 0x89A3}, {0x89A4, 0x89A4}, {0x89A5, 0x89A5}, {0x89A6, 0x89A6}, {0x89A7, 0x89A7}, {0x89A8, 0x89A8}, {0x89A9, 0x89A9}, + {0x89AA, 0x89AA}, {0x89AB, 0x89AB}, {0x89AC, 0x89AC}, {0x89AD, 0x89AD}, {0x89AE, 0x89AE}, {0x89AF, 0x89AF}, {0x89B0, 0x89B0}, + {0x89B1, 0x89B1}, {0x89B2, 0x89B2}, {0x89B3, 0x89B3}, {0x89B4, 0x89B4}, {0x89B5, 0x89B5}, {0x89B6, 0x89B6}, {0x89B7, 0x89B7}, + {0x89B8, 0x89B8}, {0x89B9, 0x89B9}, {0x89BA, 0x89BA}, {0x89BB, 0x89BB}, {0x89BC, 0x89BC}, {0x89BD, 0x89BD}, {0x89BE, 0x89BE}, + {0x89BF, 0x89BF}, {0x89C0, 0x89C0}, {0x89C1, 0x89C1}, {0x89C2, 0x89C2}, {0x89C3, 0x89C3}, {0x89C4, 0x89C4}, {0x89C5, 0x89C5}, + {0x89C6, 0x89C6}, {0x89C7, 0x89C7}, {0x89C8, 0x89C8}, {0x89C9, 0x89C9}, {0x89CA, 0x89CA}, {0x89CB, 0x89CB}, {0x89CC, 0x89CC}, + {0x89CD, 0x89CD}, {0x89CE, 0x89CE}, {0x89CF, 0x89CF}, {0x89D0, 0x89D0}, {0x89D1, 0x89D1}, {0x89D2, 0x89D2}, {0x89D3, 0x89D3}, + {0x89D4, 0x89D4}, {0x89D5, 0x89D5}, {0x89D6, 0x89D6}, {0x89D7, 0x89D7}, {0x89D8, 0x89D8}, {0x89D9, 0x89D9}, {0x89DA, 0x89DA}, + {0x89DB, 0x89DB}, {0x89DC, 0x89DC}, {0x89DD, 0x89DD}, {0x89DE, 0x89DE}, {0x89DF, 0x89DF}, {0x89E0, 0x89E0}, {0x89E1, 0x89E1}, + {0x89E2, 0x89E2}, {0x89E3, 0x89E3}, {0x89E4, 0x89E4}, {0x89E5, 0x89E5}, {0x89E6, 0x89E6}, {0x89E7, 0x89E7}, {0x89E8, 0x89E8}, + {0x89E9, 0x89E9}, {0x89EA, 0x89EA}, {0x89EB, 0x89EB}, {0x89EC, 0x89EC}, {0x89ED, 0x89ED}, {0x89EE, 0x89EE}, {0x89EF, 0x89EF}, + {0x89F0, 0x89F0}, {0x89F1, 0x89F1}, {0x89F2, 0x89F2}, {0x89F3, 0x89F3}, {0x89F4, 0x89F4}, {0x89F5, 0x89F5}, {0x89F6, 0x89F6}, + {0x89F7, 0x89F7}, {0x89F8, 0x89F8}, {0x89F9, 0x89F9}, {0x89FA, 0x89FA}, {0x89FB, 0x89FB}, {0x89FC, 0x89FC}, {0x89FD, 0x89FD}, + {0x89FE, 0x89FE}, {0x89FF, 0x89FF}, {0x8A00, 0x8A00}, {0x8A01, 0x8A01}, {0x8A02, 0x8A02}, {0x8A03, 0x8A03}, {0x8A04, 0x8A04}, + {0x8A05, 0x8A05}, {0x8A06, 0x8A06}, {0x8A07, 0x8A07}, {0x8A08, 0x8A08}, {0x8A09, 0x8A09}, {0x8A0A, 0x8A0A}, {0x8A0B, 0x8A0B}, + {0x8A0C, 0x8A0C}, {0x8A0D, 0x8A0D}, {0x8A0E, 0x8A0E}, {0x8A0F, 0x8A0F}, {0x8A10, 0x8A10}, {0x8A11, 0x8A11}, {0x8A12, 0x8A12}, + {0x8A13, 0x8A13}, {0x8A14, 0x8A14}, {0x8A15, 0x8A15}, {0x8A16, 0x8A16}, {0x8A17, 0x8A17}, {0x8A18, 0x8A18}, {0x8A19, 0x8A19}, + {0x8A1A, 0x8A1A}, {0x8A1B, 0x8A1B}, {0x8A1C, 0x8A1C}, {0x8A1D, 0x8A1D}, {0x8A1E, 0x8A1E}, {0x8A1F, 0x8A1F}, {0x8A20, 0x8A20}, + {0x8A21, 0x8A21}, {0x8A22, 0x8A22}, {0x8A23, 0x8A23}, {0x8A24, 0x8A24}, {0x8A25, 0x8A25}, {0x8A26, 0x8A26}, {0x8A27, 0x8A27}, + {0x8A28, 0x8A28}, {0x8A29, 0x8A29}, {0x8A2A, 0x8A2A}, {0x8A2B, 0x8A2B}, {0x8A2C, 0x8A2C}, {0x8A2D, 0x8A2D}, {0x8A2E, 0x8A2E}, + {0x8A2F, 0x8A2F}, {0x8A30, 0x8A30}, {0x8A31, 0x8A31}, {0x8A32, 0x8A32}, {0x8A33, 0x8A33}, {0x8A34, 0x8A34}, {0x8A35, 0x8A35}, + {0x8A36, 0x8A36}, {0x8A37, 0x8A37}, {0x8A38, 0x8A38}, {0x8A39, 0x8A39}, {0x8A3A, 0x8A3A}, {0x8A3B, 0x8A3B}, {0x8A3C, 0x8A3C}, + {0x8A3D, 0x8A3D}, {0x8A3E, 0x8A3E}, {0x8A3F, 0x8A3F}, {0x8A40, 0x8A40}, {0x8A41, 0x8A41}, {0x8A42, 0x8A42}, {0x8A43, 0x8A43}, + {0x8A44, 0x8A44}, {0x8A45, 0x8A45}, {0x8A46, 0x8A46}, {0x8A47, 0x8A47}, {0x8A48, 0x8A48}, {0x8A49, 0x8A49}, {0x8A4A, 0x8A4A}, + {0x8A4B, 0x8A4B}, {0x8A4C, 0x8A4C}, {0x8A4D, 0x8A4D}, {0x8A4E, 0x8A4E}, {0x8A4F, 0x8A4F}, {0x8A50, 0x8A50}, {0x8A51, 0x8A51}, + {0x8A52, 0x8A52}, {0x8A53, 0x8A53}, {0x8A54, 0x8A54}, {0x8A55, 0x8A55}, {0x8A56, 0x8A56}, {0x8A57, 0x8A57}, {0x8A58, 0x8A58}, + {0x8A59, 0x8A59}, {0x8A5A, 0x8A5A}, {0x8A5B, 0x8A5B}, {0x8A5C, 0x8A5C}, {0x8A5D, 0x8A5D}, {0x8A5E, 0x8A5E}, {0x8A5F, 0x8A5F}, + {0x8A60, 0x8A60}, {0x8A61, 0x8A61}, {0x8A62, 0x8A62}, {0x8A63, 0x8A63}, {0x8A64, 0x8A64}, {0x8A65, 0x8A65}, {0x8A66, 0x8A66}, + {0x8A67, 0x8A67}, {0x8A68, 0x8A68}, {0x8A69, 0x8A69}, {0x8A6A, 0x8A6A}, {0x8A6B, 0x8A6B}, {0x8A6C, 0x8A6C}, {0x8A6D, 0x8A6D}, + {0x8A6E, 0x8A6E}, {0x8A6F, 0x8A6F}, {0x8A70, 0x8A70}, {0x8A71, 0x8A71}, {0x8A72, 0x8A72}, {0x8A73, 0x8A73}, {0x8A74, 0x8A74}, + {0x8A75, 0x8A75}, {0x8A76, 0x8A76}, {0x8A77, 0x8A77}, {0x8A78, 0x8A78}, {0x8A79, 0x8A79}, {0x8A7A, 0x8A7A}, {0x8A7B, 0x8A7B}, + {0x8A7C, 0x8A7C}, {0x8A7D, 0x8A7D}, {0x8A7E, 0x8A7E}, {0x8A7F, 0x8A7F}, {0x8A80, 0x8A80}, {0x8A81, 0x8A81}, {0x8A82, 0x8A82}, + {0x8A83, 0x8A83}, {0x8A84, 0x8A84}, {0x8A85, 0x8A85}, {0x8A86, 0x8A86}, {0x8A87, 0x8A87}, {0x8A88, 0x8A88}, {0x8A89, 0x8A89}, + {0x8A8A, 0x8A8A}, {0x8A8B, 0x8A8B}, {0x8A8C, 0x8A8C}, {0x8A8D, 0x8A8D}, {0x8A8E, 0x8A8E}, {0x8A8F, 0x8A8F}, {0x8A90, 0x8A90}, + {0x8A91, 0x8A91}, {0x8A92, 0x8A92}, {0x8A93, 0x8A93}, {0x8A94, 0x8A94}, {0x8A95, 0x8A95}, {0x8A96, 0x8A96}, {0x8A97, 0x8A97}, + {0x8A98, 0x8A98}, {0x8A99, 0x8A99}, {0x8A9A, 0x8A9A}, {0x8A9B, 0x8A9B}, {0x8A9C, 0x8A9C}, {0x8A9D, 0x8A9D}, {0x8A9E, 0x8A9E}, + {0x8A9F, 0x8A9F}, {0x8AA0, 0x8AA0}, {0x8AA1, 0x8AA1}, {0x8AA2, 0x8AA2}, {0x8AA3, 0x8AA3}, {0x8AA4, 0x8AA4}, {0x8AA5, 0x8AA5}, + {0x8AA6, 0x8AA6}, {0x8AA7, 0x8AA7}, {0x8AA8, 0x8AA8}, {0x8AA9, 0x8AA9}, {0x8AAA, 0x8AAA}, {0x8AAB, 0x8AAB}, {0x8AAC, 0x8AAC}, + {0x8AAD, 0x8AAD}, {0x8AAE, 0x8AAE}, {0x8AAF, 0x8AAF}, {0x8AB0, 0x8AB0}, {0x8AB1, 0x8AB1}, {0x8AB2, 0x8AB2}, {0x8AB3, 0x8AB3}, + {0x8AB4, 0x8AB4}, {0x8AB5, 0x8AB5}, {0x8AB6, 0x8AB6}, {0x8AB7, 0x8AB7}, {0x8AB8, 0x8AB8}, {0x8AB9, 0x8AB9}, {0x8ABA, 0x8ABA}, + {0x8ABB, 0x8ABB}, {0x8ABC, 0x8ABC}, {0x8ABD, 0x8ABD}, {0x8ABE, 0x8ABE}, {0x8ABF, 0x8ABF}, {0x8AC0, 0x8AC0}, {0x8AC1, 0x8AC1}, + {0x8AC2, 0x8AC2}, {0x8AC3, 0x8AC3}, {0x8AC4, 0x8AC4}, {0x8AC5, 0x8AC5}, {0x8AC6, 0x8AC6}, {0x8AC7, 0x8AC7}, {0x8AC8, 0x8AC8}, + {0x8AC9, 0x8AC9}, {0x8ACA, 0x8ACA}, {0x8ACB, 0x8ACB}, {0x8ACC, 0x8ACC}, {0x8ACD, 0x8ACD}, {0x8ACE, 0x8ACE}, {0x8ACF, 0x8ACF}, + {0x8AD0, 0x8AD0}, {0x8AD1, 0x8AD1}, {0x8AD2, 0x8AD2}, {0x8AD3, 0x8AD3}, {0x8AD4, 0x8AD4}, {0x8AD5, 0x8AD5}, {0x8AD6, 0x8AD6}, + {0x8AD7, 0x8AD7}, {0x8AD8, 0x8AD8}, {0x8AD9, 0x8AD9}, {0x8ADA, 0x8ADA}, {0x8ADB, 0x8ADB}, {0x8ADC, 0x8ADC}, {0x8ADD, 0x8ADD}, + {0x8ADE, 0x8ADE}, {0x8ADF, 0x8ADF}, {0x8AE0, 0x8AE0}, {0x8AE1, 0x8AE1}, {0x8AE2, 0x8AE2}, {0x8AE3, 0x8AE3}, {0x8AE4, 0x8AE4}, + {0x8AE5, 0x8AE5}, {0x8AE6, 0x8AE6}, {0x8AE7, 0x8AE7}, {0x8AE8, 0x8AE8}, {0x8AE9, 0x8AE9}, {0x8AEA, 0x8AEA}, {0x8AEB, 0x8AEB}, + {0x8AEC, 0x8AEC}, {0x8AED, 0x8AED}, {0x8AEE, 0x8AEE}, {0x8AEF, 0x8AEF}, {0x8AF0, 0x8AF0}, {0x8AF1, 0x8AF1}, {0x8AF2, 0x8AF2}, + {0x8AF3, 0x8AF3}, {0x8AF4, 0x8AF4}, {0x8AF5, 0x8AF5}, {0x8AF6, 0x8AF6}, {0x8AF7, 0x8AF7}, {0x8AF8, 0x8AF8}, {0x8AF9, 0x8AF9}, + {0x8AFA, 0x8AFA}, {0x8AFB, 0x8AFB}, {0x8AFC, 0x8AFC}, {0x8AFD, 0x8AFD}, {0x8AFE, 0x8AFE}, {0x8AFF, 0x8AFF}, {0x8B00, 0x8B00}, + {0x8B01, 0x8B01}, {0x8B02, 0x8B02}, {0x8B03, 0x8B03}, {0x8B04, 0x8B04}, {0x8B05, 0x8B05}, {0x8B06, 0x8B06}, {0x8B07, 0x8B07}, + {0x8B08, 0x8B08}, {0x8B09, 0x8B09}, {0x8B0A, 0x8B0A}, {0x8B0B, 0x8B0B}, {0x8B0C, 0x8B0C}, {0x8B0D, 0x8B0D}, {0x8B0E, 0x8B0E}, + {0x8B0F, 0x8B0F}, {0x8B10, 0x8B10}, {0x8B11, 0x8B11}, {0x8B12, 0x8B12}, {0x8B13, 0x8B13}, {0x8B14, 0x8B14}, {0x8B15, 0x8B15}, + {0x8B16, 0x8B16}, {0x8B17, 0x8B17}, {0x8B18, 0x8B18}, {0x8B19, 0x8B19}, {0x8B1A, 0x8B1A}, {0x8B1B, 0x8B1B}, {0x8B1C, 0x8B1C}, + {0x8B1D, 0x8B1D}, {0x8B1E, 0x8B1E}, {0x8B1F, 0x8B1F}, {0x8B20, 0x8B20}, {0x8B21, 0x8B21}, {0x8B22, 0x8B22}, {0x8B23, 0x8B23}, + {0x8B24, 0x8B24}, {0x8B25, 0x8B25}, {0x8B26, 0x8B26}, {0x8B27, 0x8B27}, {0x8B28, 0x8B28}, {0x8B29, 0x8B29}, {0x8B2A, 0x8B2A}, + {0x8B2B, 0x8B2B}, {0x8B2C, 0x8B2C}, {0x8B2D, 0x8B2D}, {0x8B2E, 0x8B2E}, {0x8B2F, 0x8B2F}, {0x8B30, 0x8B30}, {0x8B31, 0x8B31}, + {0x8B32, 0x8B32}, {0x8B33, 0x8B33}, {0x8B34, 0x8B34}, {0x8B35, 0x8B35}, {0x8B36, 0x8B36}, {0x8B37, 0x8B37}, {0x8B38, 0x8B38}, + {0x8B39, 0x8B39}, {0x8B3A, 0x8B3A}, {0x8B3B, 0x8B3B}, {0x8B3C, 0x8B3C}, {0x8B3D, 0x8B3D}, {0x8B3E, 0x8B3E}, {0x8B3F, 0x8B3F}, + {0x8B40, 0x8B40}, {0x8B41, 0x8B41}, {0x8B42, 0x8B42}, {0x8B43, 0x8B43}, {0x8B44, 0x8B44}, {0x8B45, 0x8B45}, {0x8B46, 0x8B46}, + {0x8B47, 0x8B47}, {0x8B48, 0x8B48}, {0x8B49, 0x8B49}, {0x8B4A, 0x8B4A}, {0x8B4B, 0x8B4B}, {0x8B4C, 0x8B4C}, {0x8B4D, 0x8B4D}, + {0x8B4E, 0x8B4E}, {0x8B4F, 0x8B4F}, {0x8B50, 0x8B50}, {0x8B51, 0x8B51}, {0x8B52, 0x8B52}, {0x8B53, 0x8B53}, {0x8B54, 0x8B54}, + {0x8B55, 0x8B55}, {0x8B56, 0x8B56}, {0x8B57, 0x8B57}, {0x8B58, 0x8B58}, {0x8B59, 0x8B59}, {0x8B5A, 0x8B5A}, {0x8B5B, 0x8B5B}, + {0x8B5C, 0x8B5C}, {0x8B5D, 0x8B5D}, {0x8B5E, 0x8B5E}, {0x8B5F, 0x8B5F}, {0x8B60, 0x8B60}, {0x8B61, 0x8B61}, {0x8B62, 0x8B62}, + {0x8B63, 0x8B63}, {0x8B64, 0x8B64}, {0x8B65, 0x8B65}, {0x8B66, 0x8B66}, {0x8B67, 0x8B67}, {0x8B68, 0x8B68}, {0x8B69, 0x8B69}, + {0x8B6A, 0x8B6A}, {0x8B6B, 0x8B6B}, {0x8B6C, 0x8B6C}, {0x8B6D, 0x8B6D}, {0x8B6E, 0x8B6E}, {0x8B6F, 0x8B6F}, {0x8B70, 0x8B70}, + {0x8B71, 0x8B71}, {0x8B72, 0x8B72}, {0x8B73, 0x8B73}, {0x8B74, 0x8B74}, {0x8B75, 0x8B75}, {0x8B76, 0x8B76}, {0x8B77, 0x8B77}, + {0x8B78, 0x8B78}, {0x8B79, 0x8B79}, {0x8B7A, 0x8B7A}, {0x8B7B, 0x8B7B}, {0x8B7C, 0x8B7C}, {0x8B7D, 0x8B7D}, {0x8B7E, 0x8B7E}, + {0x8B7F, 0x8B7F}, {0x8B80, 0x8B80}, {0x8B81, 0x8B81}, {0x8B82, 0x8B82}, {0x8B83, 0x8B83}, {0x8B84, 0x8B84}, {0x8B85, 0x8B85}, + {0x8B86, 0x8B86}, {0x8B87, 0x8B87}, {0x8B88, 0x8B88}, {0x8B89, 0x8B89}, {0x8B8A, 0x8B8A}, {0x8B8B, 0x8B8B}, {0x8B8C, 0x8B8C}, + {0x8B8D, 0x8B8D}, {0x8B8E, 0x8B8E}, {0x8B8F, 0x8B8F}, {0x8B90, 0x8B90}, {0x8B91, 0x8B91}, {0x8B92, 0x8B92}, {0x8B93, 0x8B93}, + {0x8B94, 0x8B94}, {0x8B95, 0x8B95}, {0x8B96, 0x8B96}, {0x8B97, 0x8B97}, {0x8B98, 0x8B98}, {0x8B99, 0x8B99}, {0x8B9A, 0x8B9A}, + {0x8B9B, 0x8B9B}, {0x8B9C, 0x8B9C}, {0x8B9D, 0x8B9D}, {0x8B9E, 0x8B9E}, {0x8B9F, 0x8B9F}, {0x8BA0, 0x8BA0}, {0x8BA1, 0x8BA1}, + {0x8BA2, 0x8BA2}, {0x8BA3, 0x8BA3}, {0x8BA4, 0x8BA4}, {0x8BA5, 0x8BA5}, {0x8BA6, 0x8BA6}, {0x8BA7, 0x8BA7}, {0x8BA8, 0x8BA8}, + {0x8BA9, 0x8BA9}, {0x8BAA, 0x8BAA}, {0x8BAB, 0x8BAB}, {0x8BAC, 0x8BAC}, {0x8BAD, 0x8BAD}, {0x8BAE, 0x8BAE}, {0x8BAF, 0x8BAF}, + {0x8BB0, 0x8BB0}, {0x8BB1, 0x8BB1}, {0x8BB2, 0x8BB2}, {0x8BB3, 0x8BB3}, {0x8BB4, 0x8BB4}, {0x8BB5, 0x8BB5}, {0x8BB6, 0x8BB6}, + {0x8BB7, 0x8BB7}, {0x8BB8, 0x8BB8}, {0x8BB9, 0x8BB9}, {0x8BBA, 0x8BBA}, {0x8BBB, 0x8BBB}, {0x8BBC, 0x8BBC}, {0x8BBD, 0x8BBD}, + {0x8BBE, 0x8BBE}, {0x8BBF, 0x8BBF}, {0x8BC0, 0x8BC0}, {0x8BC1, 0x8BC1}, {0x8BC2, 0x8BC2}, {0x8BC3, 0x8BC3}, {0x8BC4, 0x8BC4}, + {0x8BC5, 0x8BC5}, {0x8BC6, 0x8BC6}, {0x8BC7, 0x8BC7}, {0x8BC8, 0x8BC8}, {0x8BC9, 0x8BC9}, {0x8BCA, 0x8BCA}, {0x8BCB, 0x8BCB}, + {0x8BCC, 0x8BCC}, {0x8BCD, 0x8BCD}, {0x8BCE, 0x8BCE}, {0x8BCF, 0x8BCF}, {0x8BD0, 0x8BD0}, {0x8BD1, 0x8BD1}, {0x8BD2, 0x8BD2}, + {0x8BD3, 0x8BD3}, {0x8BD4, 0x8BD4}, {0x8BD5, 0x8BD5}, {0x8BD6, 0x8BD6}, {0x8BD7, 0x8BD7}, {0x8BD8, 0x8BD8}, {0x8BD9, 0x8BD9}, + {0x8BDA, 0x8BDA}, {0x8BDB, 0x8BDB}, {0x8BDC, 0x8BDC}, {0x8BDD, 0x8BDD}, {0x8BDE, 0x8BDE}, {0x8BDF, 0x8BDF}, {0x8BE0, 0x8BE0}, + {0x8BE1, 0x8BE1}, {0x8BE2, 0x8BE2}, {0x8BE3, 0x8BE3}, {0x8BE4, 0x8BE4}, {0x8BE5, 0x8BE5}, {0x8BE6, 0x8BE6}, {0x8BE7, 0x8BE7}, + {0x8BE8, 0x8BE8}, {0x8BE9, 0x8BE9}, {0x8BEA, 0x8BEA}, {0x8BEB, 0x8BEB}, {0x8BEC, 0x8BEC}, {0x8BED, 0x8BED}, {0x8BEE, 0x8BEE}, + {0x8BEF, 0x8BEF}, {0x8BF0, 0x8BF0}, {0x8BF1, 0x8BF1}, {0x8BF2, 0x8BF2}, {0x8BF3, 0x8BF3}, {0x8BF4, 0x8BF4}, {0x8BF5, 0x8BF5}, + {0x8BF6, 0x8BF6}, {0x8BF7, 0x8BF7}, {0x8BF8, 0x8BF8}, {0x8BF9, 0x8BF9}, {0x8BFA, 0x8BFA}, {0x8BFB, 0x8BFB}, {0x8BFC, 0x8BFC}, + {0x8BFD, 0x8BFD}, {0x8BFE, 0x8BFE}, {0x8BFF, 0x8BFF}, {0x8C00, 0x8C00}, {0x8C01, 0x8C01}, {0x8C02, 0x8C02}, {0x8C03, 0x8C03}, + {0x8C04, 0x8C04}, {0x8C05, 0x8C05}, {0x8C06, 0x8C06}, {0x8C07, 0x8C07}, {0x8C08, 0x8C08}, {0x8C09, 0x8C09}, {0x8C0A, 0x8C0A}, + {0x8C0B, 0x8C0B}, {0x8C0C, 0x8C0C}, {0x8C0D, 0x8C0D}, {0x8C0E, 0x8C0E}, {0x8C0F, 0x8C0F}, {0x8C10, 0x8C10}, {0x8C11, 0x8C11}, + {0x8C12, 0x8C12}, {0x8C13, 0x8C13}, {0x8C14, 0x8C14}, {0x8C15, 0x8C15}, {0x8C16, 0x8C16}, {0x8C17, 0x8C17}, {0x8C18, 0x8C18}, + {0x8C19, 0x8C19}, {0x8C1A, 0x8C1A}, {0x8C1B, 0x8C1B}, {0x8C1C, 0x8C1C}, {0x8C1D, 0x8C1D}, {0x8C1E, 0x8C1E}, {0x8C1F, 0x8C1F}, + {0x8C20, 0x8C20}, {0x8C21, 0x8C21}, {0x8C22, 0x8C22}, {0x8C23, 0x8C23}, {0x8C24, 0x8C24}, {0x8C25, 0x8C25}, {0x8C26, 0x8C26}, + {0x8C27, 0x8C27}, {0x8C28, 0x8C28}, {0x8C29, 0x8C29}, {0x8C2A, 0x8C2A}, {0x8C2B, 0x8C2B}, {0x8C2C, 0x8C2C}, {0x8C2D, 0x8C2D}, + {0x8C2E, 0x8C2E}, {0x8C2F, 0x8C2F}, {0x8C30, 0x8C30}, {0x8C31, 0x8C31}, {0x8C32, 0x8C32}, {0x8C33, 0x8C33}, {0x8C34, 0x8C34}, + {0x8C35, 0x8C35}, {0x8C36, 0x8C36}, {0x8C37, 0x8C37}, {0x8C38, 0x8C38}, {0x8C39, 0x8C39}, {0x8C3A, 0x8C3A}, {0x8C3B, 0x8C3B}, + {0x8C3C, 0x8C3C}, {0x8C3D, 0x8C3D}, {0x8C3E, 0x8C3E}, {0x8C3F, 0x8C3F}, {0x8C40, 0x8C40}, {0x8C41, 0x8C41}, {0x8C42, 0x8C42}, + {0x8C43, 0x8C43}, {0x8C44, 0x8C44}, {0x8C45, 0x8C45}, {0x8C46, 0x8C46}, {0x8C47, 0x8C47}, {0x8C48, 0x8C48}, {0x8C49, 0x8C49}, + {0x8C4A, 0x8C4A}, {0x8C4B, 0x8C4B}, {0x8C4C, 0x8C4C}, {0x8C4D, 0x8C4D}, {0x8C4E, 0x8C4E}, {0x8C4F, 0x8C4F}, {0x8C50, 0x8C50}, + {0x8C51, 0x8C51}, {0x8C52, 0x8C52}, {0x8C53, 0x8C53}, {0x8C54, 0x8C54}, {0x8C55, 0x8C55}, {0x8C56, 0x8C56}, {0x8C57, 0x8C57}, + {0x8C58, 0x8C58}, {0x8C59, 0x8C59}, {0x8C5A, 0x8C5A}, {0x8C5B, 0x8C5B}, {0x8C5C, 0x8C5C}, {0x8C5D, 0x8C5D}, {0x8C5E, 0x8C5E}, + {0x8C5F, 0x8C5F}, {0x8C60, 0x8C60}, {0x8C61, 0x8C61}, {0x8C62, 0x8C62}, {0x8C63, 0x8C63}, {0x8C64, 0x8C64}, {0x8C65, 0x8C65}, + {0x8C66, 0x8C66}, {0x8C67, 0x8C67}, {0x8C68, 0x8C68}, {0x8C69, 0x8C69}, {0x8C6A, 0x8C6A}, {0x8C6B, 0x8C6B}, {0x8C6C, 0x8C6C}, + {0x8C6D, 0x8C6D}, {0x8C6E, 0x8C6E}, {0x8C6F, 0x8C6F}, {0x8C70, 0x8C70}, {0x8C71, 0x8C71}, {0x8C72, 0x8C72}, {0x8C73, 0x8C73}, + {0x8C74, 0x8C74}, {0x8C75, 0x8C75}, {0x8C76, 0x8C76}, {0x8C77, 0x8C77}, {0x8C78, 0x8C78}, {0x8C79, 0x8C79}, {0x8C7A, 0x8C7A}, + {0x8C7B, 0x8C7B}, {0x8C7C, 0x8C7C}, {0x8C7D, 0x8C7D}, {0x8C7E, 0x8C7E}, {0x8C7F, 0x8C7F}, {0x8C80, 0x8C80}, {0x8C81, 0x8C81}, + {0x8C82, 0x8C82}, {0x8C83, 0x8C83}, {0x8C84, 0x8C84}, {0x8C85, 0x8C85}, {0x8C86, 0x8C86}, {0x8C87, 0x8C87}, {0x8C88, 0x8C88}, + {0x8C89, 0x8C89}, {0x8C8A, 0x8C8A}, {0x8C8B, 0x8C8B}, {0x8C8C, 0x8C8C}, {0x8C8D, 0x8C8D}, {0x8C8E, 0x8C8E}, {0x8C8F, 0x8C8F}, + {0x8C90, 0x8C90}, {0x8C91, 0x8C91}, {0x8C92, 0x8C92}, {0x8C93, 0x8C93}, {0x8C94, 0x8C94}, {0x8C95, 0x8C95}, {0x8C96, 0x8C96}, + {0x8C97, 0x8C97}, {0x8C98, 0x8C98}, {0x8C99, 0x8C99}, {0x8C9A, 0x8C9A}, {0x8C9B, 0x8C9B}, {0x8C9C, 0x8C9C}, {0x8C9D, 0x8C9D}, + {0x8C9E, 0x8C9E}, {0x8C9F, 0x8C9F}, {0x8CA0, 0x8CA0}, {0x8CA1, 0x8CA1}, {0x8CA2, 0x8CA2}, {0x8CA3, 0x8CA3}, {0x8CA4, 0x8CA4}, + {0x8CA5, 0x8CA5}, {0x8CA6, 0x8CA6}, {0x8CA7, 0x8CA7}, {0x8CA8, 0x8CA8}, {0x8CA9, 0x8CA9}, {0x8CAA, 0x8CAA}, {0x8CAB, 0x8CAB}, + {0x8CAC, 0x8CAC}, {0x8CAD, 0x8CAD}, {0x8CAE, 0x8CAE}, {0x8CAF, 0x8CAF}, {0x8CB0, 0x8CB0}, {0x8CB1, 0x8CB1}, {0x8CB2, 0x8CB2}, + {0x8CB3, 0x8CB3}, {0x8CB4, 0x8CB4}, {0x8CB5, 0x8CB5}, {0x8CB6, 0x8CB6}, {0x8CB7, 0x8CB7}, {0x8CB8, 0x8CB8}, {0x8CB9, 0x8CB9}, + {0x8CBA, 0x8CBA}, {0x8CBB, 0x8CBB}, {0x8CBC, 0x8CBC}, {0x8CBD, 0x8CBD}, {0x8CBE, 0x8CBE}, {0x8CBF, 0x8CBF}, {0x8CC0, 0x8CC0}, + {0x8CC1, 0x8CC1}, {0x8CC2, 0x8CC2}, {0x8CC3, 0x8CC3}, {0x8CC4, 0x8CC4}, {0x8CC5, 0x8CC5}, {0x8CC6, 0x8CC6}, {0x8CC7, 0x8CC7}, + {0x8CC8, 0x8CC8}, {0x8CC9, 0x8CC9}, {0x8CCA, 0x8CCA}, {0x8CCB, 0x8CCB}, {0x8CCC, 0x8CCC}, {0x8CCD, 0x8CCD}, {0x8CCE, 0x8CCE}, + {0x8CCF, 0x8CCF}, {0x8CD0, 0x8CD0}, {0x8CD1, 0x8CD1}, {0x8CD2, 0x8CD2}, {0x8CD3, 0x8CD3}, {0x8CD4, 0x8CD4}, {0x8CD5, 0x8CD5}, + {0x8CD6, 0x8CD6}, {0x8CD7, 0x8CD7}, {0x8CD8, 0x8CD8}, {0x8CD9, 0x8CD9}, {0x8CDA, 0x8CDA}, {0x8CDB, 0x8CDB}, {0x8CDC, 0x8CDC}, + {0x8CDD, 0x8CDD}, {0x8CDE, 0x8CDE}, {0x8CDF, 0x8CDF}, {0x8CE0, 0x8CE0}, {0x8CE1, 0x8CE1}, {0x8CE2, 0x8CE2}, {0x8CE3, 0x8CE3}, + {0x8CE4, 0x8CE4}, {0x8CE5, 0x8CE5}, {0x8CE6, 0x8CE6}, {0x8CE7, 0x8CE7}, {0x8CE8, 0x8CE8}, {0x8CE9, 0x8CE9}, {0x8CEA, 0x8CEA}, + {0x8CEB, 0x8CEB}, {0x8CEC, 0x8CEC}, {0x8CED, 0x8CED}, {0x8CEE, 0x8CEE}, {0x8CEF, 0x8CEF}, {0x8CF0, 0x8CF0}, {0x8CF1, 0x8CF1}, + {0x8CF2, 0x8CF2}, {0x8CF3, 0x8CF3}, {0x8CF4, 0x8CF4}, {0x8CF5, 0x8CF5}, {0x8CF6, 0x8CF6}, {0x8CF7, 0x8CF7}, {0x8CF8, 0x8CF8}, + {0x8CF9, 0x8CF9}, {0x8CFA, 0x8CFA}, {0x8CFB, 0x8CFB}, {0x8CFC, 0x8CFC}, {0x8CFD, 0x8CFD}, {0x8CFE, 0x8CFE}, {0x8CFF, 0x8CFF}, + {0x8D00, 0x8D00}, {0x8D01, 0x8D01}, {0x8D02, 0x8D02}, {0x8D03, 0x8D03}, {0x8D04, 0x8D04}, {0x8D05, 0x8D05}, {0x8D06, 0x8D06}, + {0x8D07, 0x8D07}, {0x8D08, 0x8D08}, {0x8D09, 0x8D09}, {0x8D0A, 0x8D0A}, {0x8D0B, 0x8D0B}, {0x8D0C, 0x8D0C}, {0x8D0D, 0x8D0D}, + {0x8D0E, 0x8D0E}, {0x8D0F, 0x8D0F}, {0x8D10, 0x8D10}, {0x8D11, 0x8D11}, {0x8D12, 0x8D12}, {0x8D13, 0x8D13}, {0x8D14, 0x8D14}, + {0x8D15, 0x8D15}, {0x8D16, 0x8D16}, {0x8D17, 0x8D17}, {0x8D18, 0x8D18}, {0x8D19, 0x8D19}, {0x8D1A, 0x8D1A}, {0x8D1B, 0x8D1B}, + {0x8D1C, 0x8D1C}, {0x8D1D, 0x8D1D}, {0x8D1E, 0x8D1E}, {0x8D1F, 0x8D1F}, {0x8D20, 0x8D20}, {0x8D21, 0x8D21}, {0x8D22, 0x8D22}, + {0x8D23, 0x8D23}, {0x8D24, 0x8D24}, {0x8D25, 0x8D25}, {0x8D26, 0x8D26}, {0x8D27, 0x8D27}, {0x8D28, 0x8D28}, {0x8D29, 0x8D29}, + {0x8D2A, 0x8D2A}, {0x8D2B, 0x8D2B}, {0x8D2C, 0x8D2C}, {0x8D2D, 0x8D2D}, {0x8D2E, 0x8D2E}, {0x8D2F, 0x8D2F}, {0x8D30, 0x8D30}, + {0x8D31, 0x8D31}, {0x8D32, 0x8D32}, {0x8D33, 0x8D33}, {0x8D34, 0x8D34}, {0x8D35, 0x8D35}, {0x8D36, 0x8D36}, {0x8D37, 0x8D37}, + {0x8D38, 0x8D38}, {0x8D39, 0x8D39}, {0x8D3A, 0x8D3A}, {0x8D3B, 0x8D3B}, {0x8D3C, 0x8D3C}, {0x8D3D, 0x8D3D}, {0x8D3E, 0x8D3E}, + {0x8D3F, 0x8D3F}, {0x8D40, 0x8D40}, {0x8D41, 0x8D41}, {0x8D42, 0x8D42}, {0x8D43, 0x8D43}, {0x8D44, 0x8D44}, {0x8D45, 0x8D45}, + {0x8D46, 0x8D46}, {0x8D47, 0x8D47}, {0x8D48, 0x8D48}, {0x8D49, 0x8D49}, {0x8D4A, 0x8D4A}, {0x8D4B, 0x8D4B}, {0x8D4C, 0x8D4C}, + {0x8D4D, 0x8D4D}, {0x8D4E, 0x8D4E}, {0x8D4F, 0x8D4F}, {0x8D50, 0x8D50}, {0x8D51, 0x8D51}, {0x8D52, 0x8D52}, {0x8D53, 0x8D53}, + {0x8D54, 0x8D54}, {0x8D55, 0x8D55}, {0x8D56, 0x8D56}, {0x8D57, 0x8D57}, {0x8D58, 0x8D58}, {0x8D59, 0x8D59}, {0x8D5A, 0x8D5A}, + {0x8D5B, 0x8D5B}, {0x8D5C, 0x8D5C}, {0x8D5D, 0x8D5D}, {0x8D5E, 0x8D5E}, {0x8D5F, 0x8D5F}, {0x8D60, 0x8D60}, {0x8D61, 0x8D61}, + {0x8D62, 0x8D62}, {0x8D63, 0x8D63}, {0x8D64, 0x8D64}, {0x8D65, 0x8D65}, {0x8D66, 0x8D66}, {0x8D67, 0x8D67}, {0x8D68, 0x8D68}, + {0x8D69, 0x8D69}, {0x8D6A, 0x8D6A}, {0x8D6B, 0x8D6B}, {0x8D6C, 0x8D6C}, {0x8D6D, 0x8D6D}, {0x8D6E, 0x8D6E}, {0x8D6F, 0x8D6F}, + {0x8D70, 0x8D70}, {0x8D71, 0x8D71}, {0x8D72, 0x8D72}, {0x8D73, 0x8D73}, {0x8D74, 0x8D74}, {0x8D75, 0x8D75}, {0x8D76, 0x8D76}, + {0x8D77, 0x8D77}, {0x8D78, 0x8D78}, {0x8D79, 0x8D79}, {0x8D7A, 0x8D7A}, {0x8D7B, 0x8D7B}, {0x8D7C, 0x8D7C}, {0x8D7D, 0x8D7D}, + {0x8D7E, 0x8D7E}, {0x8D7F, 0x8D7F}, {0x8D80, 0x8D80}, {0x8D81, 0x8D81}, {0x8D82, 0x8D82}, {0x8D83, 0x8D83}, {0x8D84, 0x8D84}, + {0x8D85, 0x8D85}, {0x8D86, 0x8D86}, {0x8D87, 0x8D87}, {0x8D88, 0x8D88}, {0x8D89, 0x8D89}, {0x8D8A, 0x8D8A}, {0x8D8B, 0x8D8B}, + {0x8D8C, 0x8D8C}, {0x8D8D, 0x8D8D}, {0x8D8E, 0x8D8E}, {0x8D8F, 0x8D8F}, {0x8D90, 0x8D90}, {0x8D91, 0x8D91}, {0x8D92, 0x8D92}, + {0x8D93, 0x8D93}, {0x8D94, 0x8D94}, {0x8D95, 0x8D95}, {0x8D96, 0x8D96}, {0x8D97, 0x8D97}, {0x8D98, 0x8D98}, {0x8D99, 0x8D99}, + {0x8D9A, 0x8D9A}, {0x8D9B, 0x8D9B}, {0x8D9C, 0x8D9C}, {0x8D9D, 0x8D9D}, {0x8D9E, 0x8D9E}, {0x8D9F, 0x8D9F}, {0x8DA0, 0x8DA0}, + {0x8DA1, 0x8DA1}, {0x8DA2, 0x8DA2}, {0x8DA3, 0x8DA3}, {0x8DA4, 0x8DA4}, {0x8DA5, 0x8DA5}, {0x8DA6, 0x8DA6}, {0x8DA7, 0x8DA7}, + {0x8DA8, 0x8DA8}, {0x8DA9, 0x8DA9}, {0x8DAA, 0x8DAA}, {0x8DAB, 0x8DAB}, {0x8DAC, 0x8DAC}, {0x8DAD, 0x8DAD}, {0x8DAE, 0x8DAE}, + {0x8DAF, 0x8DAF}, {0x8DB0, 0x8DB0}, {0x8DB1, 0x8DB1}, {0x8DB2, 0x8DB2}, {0x8DB3, 0x8DB3}, {0x8DB4, 0x8DB4}, {0x8DB5, 0x8DB5}, + {0x8DB6, 0x8DB6}, {0x8DB7, 0x8DB7}, {0x8DB8, 0x8DB8}, {0x8DB9, 0x8DB9}, {0x8DBA, 0x8DBA}, {0x8DBB, 0x8DBB}, {0x8DBC, 0x8DBC}, + {0x8DBD, 0x8DBD}, {0x8DBE, 0x8DBE}, {0x8DBF, 0x8DBF}, {0x8DC0, 0x8DC0}, {0x8DC1, 0x8DC1}, {0x8DC2, 0x8DC2}, {0x8DC3, 0x8DC3}, + {0x8DC4, 0x8DC4}, {0x8DC5, 0x8DC5}, {0x8DC6, 0x8DC6}, {0x8DC7, 0x8DC7}, {0x8DC8, 0x8DC8}, {0x8DC9, 0x8DC9}, {0x8DCA, 0x8DCA}, + {0x8DCB, 0x8DCB}, {0x8DCC, 0x8DCC}, {0x8DCD, 0x8DCD}, {0x8DCE, 0x8DCE}, {0x8DCF, 0x8DCF}, {0x8DD0, 0x8DD0}, {0x8DD1, 0x8DD1}, + {0x8DD2, 0x8DD2}, {0x8DD3, 0x8DD3}, {0x8DD4, 0x8DD4}, {0x8DD5, 0x8DD5}, {0x8DD6, 0x8DD6}, {0x8DD7, 0x8DD7}, {0x8DD8, 0x8DD8}, + {0x8DD9, 0x8DD9}, {0x8DDA, 0x8DDA}, {0x8DDB, 0x8DDB}, {0x8DDC, 0x8DDC}, {0x8DDD, 0x8DDD}, {0x8DDE, 0x8DDE}, {0x8DDF, 0x8DDF}, + {0x8DE0, 0x8DE0}, {0x8DE1, 0x8DE1}, {0x8DE2, 0x8DE2}, {0x8DE3, 0x8DE3}, {0x8DE4, 0x8DE4}, {0x8DE5, 0x8DE5}, {0x8DE6, 0x8DE6}, + {0x8DE7, 0x8DE7}, {0x8DE8, 0x8DE8}, {0x8DE9, 0x8DE9}, {0x8DEA, 0x8DEA}, {0x8DEB, 0x8DEB}, {0x8DEC, 0x8DEC}, {0x8DED, 0x8DED}, + {0x8DEE, 0x8DEE}, {0x8DEF, 0x8DEF}, {0x8DF0, 0x8DF0}, {0x8DF1, 0x8DF1}, {0x8DF2, 0x8DF2}, {0x8DF3, 0x8DF3}, {0x8DF4, 0x8DF4}, + {0x8DF5, 0x8DF5}, {0x8DF6, 0x8DF6}, {0x8DF7, 0x8DF7}, {0x8DF8, 0x8DF8}, {0x8DF9, 0x8DF9}, {0x8DFA, 0x8DFA}, {0x8DFB, 0x8DFB}, + {0x8DFC, 0x8DFC}, {0x8DFD, 0x8DFD}, {0x8DFE, 0x8DFE}, {0x8DFF, 0x8DFF}, {0x8E00, 0x8E00}, {0x8E01, 0x8E01}, {0x8E02, 0x8E02}, + {0x8E03, 0x8E03}, {0x8E04, 0x8E04}, {0x8E05, 0x8E05}, {0x8E06, 0x8E06}, {0x8E07, 0x8E07}, {0x8E08, 0x8E08}, {0x8E09, 0x8E09}, + {0x8E0A, 0x8E0A}, {0x8E0B, 0x8E0B}, {0x8E0C, 0x8E0C}, {0x8E0D, 0x8E0D}, {0x8E0E, 0x8E0E}, {0x8E0F, 0x8E0F}, {0x8E10, 0x8E10}, + {0x8E11, 0x8E11}, {0x8E12, 0x8E12}, {0x8E13, 0x8E13}, {0x8E14, 0x8E14}, {0x8E15, 0x8E15}, {0x8E16, 0x8E16}, {0x8E17, 0x8E17}, + {0x8E18, 0x8E18}, {0x8E19, 0x8E19}, {0x8E1A, 0x8E1A}, {0x8E1B, 0x8E1B}, {0x8E1C, 0x8E1C}, {0x8E1D, 0x8E1D}, {0x8E1E, 0x8E1E}, + {0x8E1F, 0x8E1F}, {0x8E20, 0x8E20}, {0x8E21, 0x8E21}, {0x8E22, 0x8E22}, {0x8E23, 0x8E23}, {0x8E24, 0x8E24}, {0x8E25, 0x8E25}, + {0x8E26, 0x8E26}, {0x8E27, 0x8E27}, {0x8E28, 0x8E28}, {0x8E29, 0x8E29}, {0x8E2A, 0x8E2A}, {0x8E2B, 0x8E2B}, {0x8E2C, 0x8E2C}, + {0x8E2D, 0x8E2D}, {0x8E2E, 0x8E2E}, {0x8E2F, 0x8E2F}, {0x8E30, 0x8E30}, {0x8E31, 0x8E31}, {0x8E32, 0x8E32}, {0x8E33, 0x8E33}, + {0x8E34, 0x8E34}, {0x8E35, 0x8E35}, {0x8E36, 0x8E36}, {0x8E37, 0x8E37}, {0x8E38, 0x8E38}, {0x8E39, 0x8E39}, {0x8E3A, 0x8E3A}, + {0x8E3B, 0x8E3B}, {0x8E3C, 0x8E3C}, {0x8E3D, 0x8E3D}, {0x8E3E, 0x8E3E}, {0x8E3F, 0x8E3F}, {0x8E40, 0x8E40}, {0x8E41, 0x8E41}, + {0x8E42, 0x8E42}, {0x8E43, 0x8E43}, {0x8E44, 0x8E44}, {0x8E45, 0x8E45}, {0x8E46, 0x8E46}, {0x8E47, 0x8E47}, {0x8E48, 0x8E48}, + {0x8E49, 0x8E49}, {0x8E4A, 0x8E4A}, {0x8E4B, 0x8E4B}, {0x8E4C, 0x8E4C}, {0x8E4D, 0x8E4D}, {0x8E4E, 0x8E4E}, {0x8E4F, 0x8E4F}, + {0x8E50, 0x8E50}, {0x8E51, 0x8E51}, {0x8E52, 0x8E52}, {0x8E53, 0x8E53}, {0x8E54, 0x8E54}, {0x8E55, 0x8E55}, {0x8E56, 0x8E56}, + {0x8E57, 0x8E57}, {0x8E58, 0x8E58}, {0x8E59, 0x8E59}, {0x8E5A, 0x8E5A}, {0x8E5B, 0x8E5B}, {0x8E5C, 0x8E5C}, {0x8E5D, 0x8E5D}, + {0x8E5E, 0x8E5E}, {0x8E5F, 0x8E5F}, {0x8E60, 0x8E60}, {0x8E61, 0x8E61}, {0x8E62, 0x8E62}, {0x8E63, 0x8E63}, {0x8E64, 0x8E64}, + {0x8E65, 0x8E65}, {0x8E66, 0x8E66}, {0x8E67, 0x8E67}, {0x8E68, 0x8E68}, {0x8E69, 0x8E69}, {0x8E6A, 0x8E6A}, {0x8E6B, 0x8E6B}, + {0x8E6C, 0x8E6C}, {0x8E6D, 0x8E6D}, {0x8E6E, 0x8E6E}, {0x8E6F, 0x8E6F}, {0x8E70, 0x8E70}, {0x8E71, 0x8E71}, {0x8E72, 0x8E72}, + {0x8E73, 0x8E73}, {0x8E74, 0x8E74}, {0x8E75, 0x8E75}, {0x8E76, 0x8E76}, {0x8E77, 0x8E77}, {0x8E78, 0x8E78}, {0x8E79, 0x8E79}, + {0x8E7A, 0x8E7A}, {0x8E7B, 0x8E7B}, {0x8E7C, 0x8E7C}, {0x8E7D, 0x8E7D}, {0x8E7E, 0x8E7E}, {0x8E7F, 0x8E7F}, {0x8E80, 0x8E80}, + {0x8E81, 0x8E81}, {0x8E82, 0x8E82}, {0x8E83, 0x8E83}, {0x8E84, 0x8E84}, {0x8E85, 0x8E85}, {0x8E86, 0x8E86}, {0x8E87, 0x8E87}, + {0x8E88, 0x8E88}, {0x8E89, 0x8E89}, {0x8E8A, 0x8E8A}, {0x8E8B, 0x8E8B}, {0x8E8C, 0x8E8C}, {0x8E8D, 0x8E8D}, {0x8E8E, 0x8E8E}, + {0x8E8F, 0x8E8F}, {0x8E90, 0x8E90}, {0x8E91, 0x8E91}, {0x8E92, 0x8E92}, {0x8E93, 0x8E93}, {0x8E94, 0x8E94}, {0x8E95, 0x8E95}, + {0x8E96, 0x8E96}, {0x8E97, 0x8E97}, {0x8E98, 0x8E98}, {0x8E99, 0x8E99}, {0x8E9A, 0x8E9A}, {0x8E9B, 0x8E9B}, {0x8E9C, 0x8E9C}, + {0x8E9D, 0x8E9D}, {0x8E9E, 0x8E9E}, {0x8E9F, 0x8E9F}, {0x8EA0, 0x8EA0}, {0x8EA1, 0x8EA1}, {0x8EA2, 0x8EA2}, {0x8EA3, 0x8EA3}, + {0x8EA4, 0x8EA4}, {0x8EA5, 0x8EA5}, {0x8EA6, 0x8EA6}, {0x8EA7, 0x8EA7}, {0x8EA8, 0x8EA8}, {0x8EA9, 0x8EA9}, {0x8EAA, 0x8EAA}, + {0x8EAB, 0x8EAB}, {0x8EAC, 0x8EAC}, {0x8EAD, 0x8EAD}, {0x8EAE, 0x8EAE}, {0x8EAF, 0x8EAF}, {0x8EB0, 0x8EB0}, {0x8EB1, 0x8EB1}, + {0x8EB2, 0x8EB2}, {0x8EB3, 0x8EB3}, {0x8EB4, 0x8EB4}, {0x8EB5, 0x8EB5}, {0x8EB6, 0x8EB6}, {0x8EB7, 0x8EB7}, {0x8EB8, 0x8EB8}, + {0x8EB9, 0x8EB9}, {0x8EBA, 0x8EBA}, {0x8EBB, 0x8EBB}, {0x8EBC, 0x8EBC}, {0x8EBD, 0x8EBD}, {0x8EBE, 0x8EBE}, {0x8EBF, 0x8EBF}, + {0x8EC0, 0x8EC0}, {0x8EC1, 0x8EC1}, {0x8EC2, 0x8EC2}, {0x8EC3, 0x8EC3}, {0x8EC4, 0x8EC4}, {0x8EC5, 0x8EC5}, {0x8EC6, 0x8EC6}, + {0x8EC7, 0x8EC7}, {0x8EC8, 0x8EC8}, {0x8EC9, 0x8EC9}, {0x8ECA, 0x8ECA}, {0x8ECB, 0x8ECB}, {0x8ECC, 0x8ECC}, {0x8ECD, 0x8ECD}, + {0x8ECE, 0x8ECE}, {0x8ECF, 0x8ECF}, {0x8ED0, 0x8ED0}, {0x8ED1, 0x8ED1}, {0x8ED2, 0x8ED2}, {0x8ED3, 0x8ED3}, {0x8ED4, 0x8ED4}, + {0x8ED5, 0x8ED5}, {0x8ED6, 0x8ED6}, {0x8ED7, 0x8ED7}, {0x8ED8, 0x8ED8}, {0x8ED9, 0x8ED9}, {0x8EDA, 0x8EDA}, {0x8EDB, 0x8EDB}, + {0x8EDC, 0x8EDC}, {0x8EDD, 0x8EDD}, {0x8EDE, 0x8EDE}, {0x8EDF, 0x8EDF}, {0x8EE0, 0x8EE0}, {0x8EE1, 0x8EE1}, {0x8EE2, 0x8EE2}, + {0x8EE3, 0x8EE3}, {0x8EE4, 0x8EE4}, {0x8EE5, 0x8EE5}, {0x8EE6, 0x8EE6}, {0x8EE7, 0x8EE7}, {0x8EE8, 0x8EE8}, {0x8EE9, 0x8EE9}, + {0x8EEA, 0x8EEA}, {0x8EEB, 0x8EEB}, {0x8EEC, 0x8EEC}, {0x8EED, 0x8EED}, {0x8EEE, 0x8EEE}, {0x8EEF, 0x8EEF}, {0x8EF0, 0x8EF0}, + {0x8EF1, 0x8EF1}, {0x8EF2, 0x8EF2}, {0x8EF3, 0x8EF3}, {0x8EF4, 0x8EF4}, {0x8EF5, 0x8EF5}, {0x8EF6, 0x8EF6}, {0x8EF7, 0x8EF7}, + {0x8EF8, 0x8EF8}, {0x8EF9, 0x8EF9}, {0x8EFA, 0x8EFA}, {0x8EFB, 0x8EFB}, {0x8EFC, 0x8EFC}, {0x8EFD, 0x8EFD}, {0x8EFE, 0x8EFE}, + {0x8EFF, 0x8EFF}, {0x8F00, 0x8F00}, {0x8F01, 0x8F01}, {0x8F02, 0x8F02}, {0x8F03, 0x8F03}, {0x8F04, 0x8F04}, {0x8F05, 0x8F05}, + {0x8F06, 0x8F06}, {0x8F07, 0x8F07}, {0x8F08, 0x8F08}, {0x8F09, 0x8F09}, {0x8F0A, 0x8F0A}, {0x8F0B, 0x8F0B}, {0x8F0C, 0x8F0C}, + {0x8F0D, 0x8F0D}, {0x8F0E, 0x8F0E}, {0x8F0F, 0x8F0F}, {0x8F10, 0x8F10}, {0x8F11, 0x8F11}, {0x8F12, 0x8F12}, {0x8F13, 0x8F13}, + {0x8F14, 0x8F14}, {0x8F15, 0x8F15}, {0x8F16, 0x8F16}, {0x8F17, 0x8F17}, {0x8F18, 0x8F18}, {0x8F19, 0x8F19}, {0x8F1A, 0x8F1A}, + {0x8F1B, 0x8F1B}, {0x8F1C, 0x8F1C}, {0x8F1D, 0x8F1D}, {0x8F1E, 0x8F1E}, {0x8F1F, 0x8F1F}, {0x8F20, 0x8F20}, {0x8F21, 0x8F21}, + {0x8F22, 0x8F22}, {0x8F23, 0x8F23}, {0x8F24, 0x8F24}, {0x8F25, 0x8F25}, {0x8F26, 0x8F26}, {0x8F27, 0x8F27}, {0x8F28, 0x8F28}, + {0x8F29, 0x8F29}, {0x8F2A, 0x8F2A}, {0x8F2B, 0x8F2B}, {0x8F2C, 0x8F2C}, {0x8F2D, 0x8F2D}, {0x8F2E, 0x8F2E}, {0x8F2F, 0x8F2F}, + {0x8F30, 0x8F30}, {0x8F31, 0x8F31}, {0x8F32, 0x8F32}, {0x8F33, 0x8F33}, {0x8F34, 0x8F34}, {0x8F35, 0x8F35}, {0x8F36, 0x8F36}, + {0x8F37, 0x8F37}, {0x8F38, 0x8F38}, {0x8F39, 0x8F39}, {0x8F3A, 0x8F3A}, {0x8F3B, 0x8F3B}, {0x8F3C, 0x8F3C}, {0x8F3D, 0x8F3D}, + {0x8F3E, 0x8F3E}, {0x8F3F, 0x8F3F}, {0x8F40, 0x8F40}, {0x8F41, 0x8F41}, {0x8F42, 0x8F42}, {0x8F43, 0x8F43}, {0x8F44, 0x8F44}, + {0x8F45, 0x8F45}, {0x8F46, 0x8F46}, {0x8F47, 0x8F47}, {0x8F48, 0x8F48}, {0x8F49, 0x8F49}, {0x8F4A, 0x8F4A}, {0x8F4B, 0x8F4B}, + {0x8F4C, 0x8F4C}, {0x8F4D, 0x8F4D}, {0x8F4E, 0x8F4E}, {0x8F4F, 0x8F4F}, {0x8F50, 0x8F50}, {0x8F51, 0x8F51}, {0x8F52, 0x8F52}, + {0x8F53, 0x8F53}, {0x8F54, 0x8F54}, {0x8F55, 0x8F55}, {0x8F56, 0x8F56}, {0x8F57, 0x8F57}, {0x8F58, 0x8F58}, {0x8F59, 0x8F59}, + {0x8F5A, 0x8F5A}, {0x8F5B, 0x8F5B}, {0x8F5C, 0x8F5C}, {0x8F5D, 0x8F5D}, {0x8F5E, 0x8F5E}, {0x8F5F, 0x8F5F}, {0x8F60, 0x8F60}, + {0x8F61, 0x8F61}, {0x8F62, 0x8F62}, {0x8F63, 0x8F63}, {0x8F64, 0x8F64}, {0x8F65, 0x8F65}, {0x8F66, 0x8F66}, {0x8F67, 0x8F67}, + {0x8F68, 0x8F68}, {0x8F69, 0x8F69}, {0x8F6A, 0x8F6A}, {0x8F6B, 0x8F6B}, {0x8F6C, 0x8F6C}, {0x8F6D, 0x8F6D}, {0x8F6E, 0x8F6E}, + {0x8F6F, 0x8F6F}, {0x8F70, 0x8F70}, {0x8F71, 0x8F71}, {0x8F72, 0x8F72}, {0x8F73, 0x8F73}, {0x8F74, 0x8F74}, {0x8F75, 0x8F75}, + {0x8F76, 0x8F76}, {0x8F77, 0x8F77}, {0x8F78, 0x8F78}, {0x8F79, 0x8F79}, {0x8F7A, 0x8F7A}, {0x8F7B, 0x8F7B}, {0x8F7C, 0x8F7C}, + {0x8F7D, 0x8F7D}, {0x8F7E, 0x8F7E}, {0x8F7F, 0x8F7F}, {0x8F80, 0x8F80}, {0x8F81, 0x8F81}, {0x8F82, 0x8F82}, {0x8F83, 0x8F83}, + {0x8F84, 0x8F84}, {0x8F85, 0x8F85}, {0x8F86, 0x8F86}, {0x8F87, 0x8F87}, {0x8F88, 0x8F88}, {0x8F89, 0x8F89}, {0x8F8A, 0x8F8A}, + {0x8F8B, 0x8F8B}, {0x8F8C, 0x8F8C}, {0x8F8D, 0x8F8D}, {0x8F8E, 0x8F8E}, {0x8F8F, 0x8F8F}, {0x8F90, 0x8F90}, {0x8F91, 0x8F91}, + {0x8F92, 0x8F92}, {0x8F93, 0x8F93}, {0x8F94, 0x8F94}, {0x8F95, 0x8F95}, {0x8F96, 0x8F96}, {0x8F97, 0x8F97}, {0x8F98, 0x8F98}, + {0x8F99, 0x8F99}, {0x8F9A, 0x8F9A}, {0x8F9B, 0x8F9B}, {0x8F9C, 0x8F9C}, {0x8F9D, 0x8F9D}, {0x8F9E, 0x8F9E}, {0x8F9F, 0x8F9F}, + {0x8FA0, 0x8FA0}, {0x8FA1, 0x8FA1}, {0x8FA2, 0x8FA2}, {0x8FA3, 0x8FA3}, {0x8FA4, 0x8FA4}, {0x8FA5, 0x8FA5}, {0x8FA6, 0x8FA6}, + {0x8FA7, 0x8FA7}, {0x8FA8, 0x8FA8}, {0x8FA9, 0x8FA9}, {0x8FAA, 0x8FAA}, {0x8FAB, 0x8FAB}, {0x8FAC, 0x8FAC}, {0x8FAD, 0x8FAD}, + {0x8FAE, 0x8FAE}, {0x8FAF, 0x8FAF}, {0x8FB0, 0x8FB0}, {0x8FB1, 0x8FB1}, {0x8FB2, 0x8FB2}, {0x8FB3, 0x8FB3}, {0x8FB4, 0x8FB4}, + {0x8FB5, 0x8FB5}, {0x8FB6, 0x8FB6}, {0x8FB7, 0x8FB7}, {0x8FB8, 0x8FB8}, {0x8FB9, 0x8FB9}, {0x8FBA, 0x8FBA}, {0x8FBB, 0x8FBB}, + {0x8FBC, 0x8FBC}, {0x8FBD, 0x8FBD}, {0x8FBE, 0x8FBE}, {0x8FBF, 0x8FBF}, {0x8FC0, 0x8FC0}, {0x8FC1, 0x8FC1}, {0x8FC2, 0x8FC2}, + {0x8FC3, 0x8FC3}, {0x8FC4, 0x8FC4}, {0x8FC5, 0x8FC5}, {0x8FC6, 0x8FC6}, {0x8FC7, 0x8FC7}, {0x8FC8, 0x8FC8}, {0x8FC9, 0x8FC9}, + {0x8FCA, 0x8FCA}, {0x8FCB, 0x8FCB}, {0x8FCC, 0x8FCC}, {0x8FCD, 0x8FCD}, {0x8FCE, 0x8FCE}, {0x8FCF, 0x8FCF}, {0x8FD0, 0x8FD0}, + {0x8FD1, 0x8FD1}, {0x8FD2, 0x8FD2}, {0x8FD3, 0x8FD3}, {0x8FD4, 0x8FD4}, {0x8FD5, 0x8FD5}, {0x8FD6, 0x8FD6}, {0x8FD7, 0x8FD7}, + {0x8FD8, 0x8FD8}, {0x8FD9, 0x8FD9}, {0x8FDA, 0x8FDA}, {0x8FDB, 0x8FDB}, {0x8FDC, 0x8FDC}, {0x8FDD, 0x8FDD}, {0x8FDE, 0x8FDE}, + {0x8FDF, 0x8FDF}, {0x8FE0, 0x8FE0}, {0x8FE1, 0x8FE1}, {0x8FE2, 0x8FE2}, {0x8FE3, 0x8FE3}, {0x8FE4, 0x8FE4}, {0x8FE5, 0x8FE5}, + {0x8FE6, 0x8FE6}, {0x8FE7, 0x8FE7}, {0x8FE8, 0x8FE8}, {0x8FE9, 0x8FE9}, {0x8FEA, 0x8FEA}, {0x8FEB, 0x8FEB}, {0x8FEC, 0x8FEC}, + {0x8FED, 0x8FED}, {0x8FEE, 0x8FEE}, {0x8FEF, 0x8FEF}, {0x8FF0, 0x8FF0}, {0x8FF1, 0x8FF1}, {0x8FF2, 0x8FF2}, {0x8FF3, 0x8FF3}, + {0x8FF4, 0x8FF4}, {0x8FF5, 0x8FF5}, {0x8FF6, 0x8FF6}, {0x8FF7, 0x8FF7}, {0x8FF8, 0x8FF8}, {0x8FF9, 0x8FF9}, {0x8FFA, 0x8FFA}, + {0x8FFB, 0x8FFB}, {0x8FFC, 0x8FFC}, {0x8FFD, 0x8FFD}, {0x8FFE, 0x8FFE}, {0x8FFF, 0x8FFF}, {0x9000, 0x9000}, {0x9001, 0x9001}, + {0x9002, 0x9002}, {0x9003, 0x9003}, {0x9004, 0x9004}, {0x9005, 0x9005}, {0x9006, 0x9006}, {0x9007, 0x9007}, {0x9008, 0x9008}, + {0x9009, 0x9009}, {0x900A, 0x900A}, {0x900B, 0x900B}, {0x900C, 0x900C}, {0x900D, 0x900D}, {0x900E, 0x900E}, {0x900F, 0x900F}, + {0x9010, 0x9010}, {0x9011, 0x9011}, {0x9012, 0x9012}, {0x9013, 0x9013}, {0x9014, 0x9014}, {0x9015, 0x9015}, {0x9016, 0x9016}, + {0x9017, 0x9017}, {0x9018, 0x9018}, {0x9019, 0x9019}, {0x901A, 0x901A}, {0x901B, 0x901B}, {0x901C, 0x901C}, {0x901D, 0x901D}, + {0x901E, 0x901E}, {0x901F, 0x901F}, {0x9020, 0x9020}, {0x9021, 0x9021}, {0x9022, 0x9022}, {0x9023, 0x9023}, {0x9024, 0x9024}, + {0x9025, 0x9025}, {0x9026, 0x9026}, {0x9027, 0x9027}, {0x9028, 0x9028}, {0x9029, 0x9029}, {0x902A, 0x902A}, {0x902B, 0x902B}, + {0x902C, 0x902C}, {0x902D, 0x902D}, {0x902E, 0x902E}, {0x902F, 0x902F}, {0x9030, 0x9030}, {0x9031, 0x9031}, {0x9032, 0x9032}, + {0x9033, 0x9033}, {0x9034, 0x9034}, {0x9035, 0x9035}, {0x9036, 0x9036}, {0x9037, 0x9037}, {0x9038, 0x9038}, {0x9039, 0x9039}, + {0x903A, 0x903A}, {0x903B, 0x903B}, {0x903C, 0x903C}, {0x903D, 0x903D}, {0x903E, 0x903E}, {0x903F, 0x903F}, {0x9040, 0x9040}, + {0x9041, 0x9041}, {0x9042, 0x9042}, {0x9043, 0x9043}, {0x9044, 0x9044}, {0x9045, 0x9045}, {0x9046, 0x9046}, {0x9047, 0x9047}, + {0x9048, 0x9048}, {0x9049, 0x9049}, {0x904A, 0x904A}, {0x904B, 0x904B}, {0x904C, 0x904C}, {0x904D, 0x904D}, {0x904E, 0x904E}, + {0x904F, 0x904F}, {0x9050, 0x9050}, {0x9051, 0x9051}, {0x9052, 0x9052}, {0x9053, 0x9053}, {0x9054, 0x9054}, {0x9055, 0x9055}, + {0x9056, 0x9056}, {0x9057, 0x9057}, {0x9058, 0x9058}, {0x9059, 0x9059}, {0x905A, 0x905A}, {0x905B, 0x905B}, {0x905C, 0x905C}, + {0x905D, 0x905D}, {0x905E, 0x905E}, {0x905F, 0x905F}, {0x9060, 0x9060}, {0x9061, 0x9061}, {0x9062, 0x9062}, {0x9063, 0x9063}, + {0x9064, 0x9064}, {0x9065, 0x9065}, {0x9066, 0x9066}, {0x9067, 0x9067}, {0x9068, 0x9068}, {0x9069, 0x9069}, {0x906A, 0x906A}, + {0x906B, 0x906B}, {0x906C, 0x906C}, {0x906D, 0x906D}, {0x906E, 0x906E}, {0x906F, 0x906F}, {0x9070, 0x9070}, {0x9071, 0x9071}, + {0x9072, 0x9072}, {0x9073, 0x9073}, {0x9074, 0x9074}, {0x9075, 0x9075}, {0x9076, 0x9076}, {0x9077, 0x9077}, {0x9078, 0x9078}, + {0x9079, 0x9079}, {0x907A, 0x907A}, {0x907B, 0x907B}, {0x907C, 0x907C}, {0x907D, 0x907D}, {0x907E, 0x907E}, {0x907F, 0x907F}, + {0x9080, 0x9080}, {0x9081, 0x9081}, {0x9082, 0x9082}, {0x9083, 0x9083}, {0x9084, 0x9084}, {0x9085, 0x9085}, {0x9086, 0x9086}, + {0x9087, 0x9087}, {0x9088, 0x9088}, {0x9089, 0x9089}, {0x908A, 0x908A}, {0x908B, 0x908B}, {0x908C, 0x908C}, {0x908D, 0x908D}, + {0x908E, 0x908E}, {0x908F, 0x908F}, {0x9090, 0x9090}, {0x9091, 0x9091}, {0x9092, 0x9092}, {0x9093, 0x9093}, {0x9094, 0x9094}, + {0x9095, 0x9095}, {0x9096, 0x9096}, {0x9097, 0x9097}, {0x9098, 0x9098}, {0x9099, 0x9099}, {0x909A, 0x909A}, {0x909B, 0x909B}, + {0x909C, 0x909C}, {0x909D, 0x909D}, {0x909E, 0x909E}, {0x909F, 0x909F}, {0x90A0, 0x90A0}, {0x90A1, 0x90A1}, {0x90A2, 0x90A2}, + {0x90A3, 0x90A3}, {0x90A4, 0x90A4}, {0x90A5, 0x90A5}, {0x90A6, 0x90A6}, {0x90A7, 0x90A7}, {0x90A8, 0x90A8}, {0x90A9, 0x90A9}, + {0x90AA, 0x90AA}, {0x90AB, 0x90AB}, {0x90AC, 0x90AC}, {0x90AD, 0x90AD}, {0x90AE, 0x90AE}, {0x90AF, 0x90AF}, {0x90B0, 0x90B0}, + {0x90B1, 0x90B1}, {0x90B2, 0x90B2}, {0x90B3, 0x90B3}, {0x90B4, 0x90B4}, {0x90B5, 0x90B5}, {0x90B6, 0x90B6}, {0x90B7, 0x90B7}, + {0x90B8, 0x90B8}, {0x90B9, 0x90B9}, {0x90BA, 0x90BA}, {0x90BB, 0x90BB}, {0x90BC, 0x90BC}, {0x90BD, 0x90BD}, {0x90BE, 0x90BE}, + {0x90BF, 0x90BF}, {0x90C0, 0x90C0}, {0x90C1, 0x90C1}, {0x90C2, 0x90C2}, {0x90C3, 0x90C3}, {0x90C4, 0x90C4}, {0x90C5, 0x90C5}, + {0x90C6, 0x90C6}, {0x90C7, 0x90C7}, {0x90C8, 0x90C8}, {0x90C9, 0x90C9}, {0x90CA, 0x90CA}, {0x90CB, 0x90CB}, {0x90CC, 0x90CC}, + {0x90CD, 0x90CD}, {0x90CE, 0x90CE}, {0x90CF, 0x90CF}, {0x90D0, 0x90D0}, {0x90D1, 0x90D1}, {0x90D2, 0x90D2}, {0x90D3, 0x90D3}, + {0x90D4, 0x90D4}, {0x90D5, 0x90D5}, {0x90D6, 0x90D6}, {0x90D7, 0x90D7}, {0x90D8, 0x90D8}, {0x90D9, 0x90D9}, {0x90DA, 0x90DA}, + {0x90DB, 0x90DB}, {0x90DC, 0x90DC}, {0x90DD, 0x90DD}, {0x90DE, 0x90DE}, {0x90DF, 0x90DF}, {0x90E0, 0x90E0}, {0x90E1, 0x90E1}, + {0x90E2, 0x90E2}, {0x90E3, 0x90E3}, {0x90E4, 0x90E4}, {0x90E5, 0x90E5}, {0x90E6, 0x90E6}, {0x90E7, 0x90E7}, {0x90E8, 0x90E8}, + {0x90E9, 0x90E9}, {0x90EA, 0x90EA}, {0x90EB, 0x90EB}, {0x90EC, 0x90EC}, {0x90ED, 0x90ED}, {0x90EE, 0x90EE}, {0x90EF, 0x90EF}, + {0x90F0, 0x90F0}, {0x90F1, 0x90F1}, {0x90F2, 0x90F2}, {0x90F3, 0x90F3}, {0x90F4, 0x90F4}, {0x90F5, 0x90F5}, {0x90F6, 0x90F6}, + {0x90F7, 0x90F7}, {0x90F8, 0x90F8}, {0x90F9, 0x90F9}, {0x90FA, 0x90FA}, {0x90FB, 0x90FB}, {0x90FC, 0x90FC}, {0x90FD, 0x90FD}, + {0x90FE, 0x90FE}, {0x90FF, 0x90FF}, {0x9100, 0x9100}, {0x9101, 0x9101}, {0x9102, 0x9102}, {0x9103, 0x9103}, {0x9104, 0x9104}, + {0x9105, 0x9105}, {0x9106, 0x9106}, {0x9107, 0x9107}, {0x9108, 0x9108}, {0x9109, 0x9109}, {0x910A, 0x910A}, {0x910B, 0x910B}, + {0x910C, 0x910C}, {0x910D, 0x910D}, {0x910E, 0x910E}, {0x910F, 0x910F}, {0x9110, 0x9110}, {0x9111, 0x9111}, {0x9112, 0x9112}, + {0x9113, 0x9113}, {0x9114, 0x9114}, {0x9115, 0x9115}, {0x9116, 0x9116}, {0x9117, 0x9117}, {0x9118, 0x9118}, {0x9119, 0x9119}, + {0x911A, 0x911A}, {0x911B, 0x911B}, {0x911C, 0x911C}, {0x911D, 0x911D}, {0x911E, 0x911E}, {0x911F, 0x911F}, {0x9120, 0x9120}, + {0x9121, 0x9121}, {0x9122, 0x9122}, {0x9123, 0x9123}, {0x9124, 0x9124}, {0x9125, 0x9125}, {0x9126, 0x9126}, {0x9127, 0x9127}, + {0x9128, 0x9128}, {0x9129, 0x9129}, {0x912A, 0x912A}, {0x912B, 0x912B}, {0x912C, 0x912C}, {0x912D, 0x912D}, {0x912E, 0x912E}, + {0x912F, 0x912F}, {0x9130, 0x9130}, {0x9131, 0x9131}, {0x9132, 0x9132}, {0x9133, 0x9133}, {0x9134, 0x9134}, {0x9135, 0x9135}, + {0x9136, 0x9136}, {0x9137, 0x9137}, {0x9138, 0x9138}, {0x9139, 0x9139}, {0x913A, 0x913A}, {0x913B, 0x913B}, {0x913C, 0x913C}, + {0x913D, 0x913D}, {0x913E, 0x913E}, {0x913F, 0x913F}, {0x9140, 0x9140}, {0x9141, 0x9141}, {0x9142, 0x9142}, {0x9143, 0x9143}, + {0x9144, 0x9144}, {0x9145, 0x9145}, {0x9146, 0x9146}, {0x9147, 0x9147}, {0x9148, 0x9148}, {0x9149, 0x9149}, {0x914A, 0x914A}, + {0x914B, 0x914B}, {0x914C, 0x914C}, {0x914D, 0x914D}, {0x914E, 0x914E}, {0x914F, 0x914F}, {0x9150, 0x9150}, {0x9151, 0x9151}, + {0x9152, 0x9152}, {0x9153, 0x9153}, {0x9154, 0x9154}, {0x9155, 0x9155}, {0x9156, 0x9156}, {0x9157, 0x9157}, {0x9158, 0x9158}, + {0x9159, 0x9159}, {0x915A, 0x915A}, {0x915B, 0x915B}, {0x915C, 0x915C}, {0x915D, 0x915D}, {0x915E, 0x915E}, {0x915F, 0x915F}, + {0x9160, 0x9160}, {0x9161, 0x9161}, {0x9162, 0x9162}, {0x9163, 0x9163}, {0x9164, 0x9164}, {0x9165, 0x9165}, {0x9166, 0x9166}, + {0x9167, 0x9167}, {0x9168, 0x9168}, {0x9169, 0x9169}, {0x916A, 0x916A}, {0x916B, 0x916B}, {0x916C, 0x916C}, {0x916D, 0x916D}, + {0x916E, 0x916E}, {0x916F, 0x916F}, {0x9170, 0x9170}, {0x9171, 0x9171}, {0x9172, 0x9172}, {0x9173, 0x9173}, {0x9174, 0x9174}, + {0x9175, 0x9175}, {0x9176, 0x9176}, {0x9177, 0x9177}, {0x9178, 0x9178}, {0x9179, 0x9179}, {0x917A, 0x917A}, {0x917B, 0x917B}, + {0x917C, 0x917C}, {0x917D, 0x917D}, {0x917E, 0x917E}, {0x917F, 0x917F}, {0x9180, 0x9180}, {0x9181, 0x9181}, {0x9182, 0x9182}, + {0x9183, 0x9183}, {0x9184, 0x9184}, {0x9185, 0x9185}, {0x9186, 0x9186}, {0x9187, 0x9187}, {0x9188, 0x9188}, {0x9189, 0x9189}, + {0x918A, 0x918A}, {0x918B, 0x918B}, {0x918C, 0x918C}, {0x918D, 0x918D}, {0x918E, 0x918E}, {0x918F, 0x918F}, {0x9190, 0x9190}, + {0x9191, 0x9191}, {0x9192, 0x9192}, {0x9193, 0x9193}, {0x9194, 0x9194}, {0x9195, 0x9195}, {0x9196, 0x9196}, {0x9197, 0x9197}, + {0x9198, 0x9198}, {0x9199, 0x9199}, {0x919A, 0x919A}, {0x919B, 0x919B}, {0x919C, 0x919C}, {0x919D, 0x919D}, {0x919E, 0x919E}, + {0x919F, 0x919F}, {0x91A0, 0x91A0}, {0x91A1, 0x91A1}, {0x91A2, 0x91A2}, {0x91A3, 0x91A3}, {0x91A4, 0x91A4}, {0x91A5, 0x91A5}, + {0x91A6, 0x91A6}, {0x91A7, 0x91A7}, {0x91A8, 0x91A8}, {0x91A9, 0x91A9}, {0x91AA, 0x91AA}, {0x91AB, 0x91AB}, {0x91AC, 0x91AC}, + {0x91AD, 0x91AD}, {0x91AE, 0x91AE}, {0x91AF, 0x91AF}, {0x91B0, 0x91B0}, {0x91B1, 0x91B1}, {0x91B2, 0x91B2}, {0x91B3, 0x91B3}, + {0x91B4, 0x91B4}, {0x91B5, 0x91B5}, {0x91B6, 0x91B6}, {0x91B7, 0x91B7}, {0x91B8, 0x91B8}, {0x91B9, 0x91B9}, {0x91BA, 0x91BA}, + {0x91BB, 0x91BB}, {0x91BC, 0x91BC}, {0x91BD, 0x91BD}, {0x91BE, 0x91BE}, {0x91BF, 0x91BF}, {0x91C0, 0x91C0}, {0x91C1, 0x91C1}, + {0x91C2, 0x91C2}, {0x91C3, 0x91C3}, {0x91C4, 0x91C4}, {0x91C5, 0x91C5}, {0x91C6, 0x91C6}, {0x91C7, 0x91C7}, {0x91C8, 0x91C8}, + {0x91C9, 0x91C9}, {0x91CA, 0x91CA}, {0x91CB, 0x91CB}, {0x91CC, 0x91CC}, {0x91CD, 0x91CD}, {0x91CE, 0x91CE}, {0x91CF, 0x91CF}, + {0x91D0, 0x91D0}, {0x91D1, 0x91D1}, {0x91D2, 0x91D2}, {0x91D3, 0x91D3}, {0x91D4, 0x91D4}, {0x91D5, 0x91D5}, {0x91D6, 0x91D6}, + {0x91D7, 0x91D7}, {0x91D8, 0x91D8}, {0x91D9, 0x91D9}, {0x91DA, 0x91DA}, {0x91DB, 0x91DB}, {0x91DC, 0x91DC}, {0x91DD, 0x91DD}, + {0x91DE, 0x91DE}, {0x91DF, 0x91DF}, {0x91E0, 0x91E0}, {0x91E1, 0x91E1}, {0x91E2, 0x91E2}, {0x91E3, 0x91E3}, {0x91E4, 0x91E4}, + {0x91E5, 0x91E5}, {0x91E6, 0x91E6}, {0x91E7, 0x91E7}, {0x91E8, 0x91E8}, {0x91E9, 0x91E9}, {0x91EA, 0x91EA}, {0x91EB, 0x91EB}, + {0x91EC, 0x91EC}, {0x91ED, 0x91ED}, {0x91EE, 0x91EE}, {0x91EF, 0x91EF}, {0x91F0, 0x91F0}, {0x91F1, 0x91F1}, {0x91F2, 0x91F2}, + {0x91F3, 0x91F3}, {0x91F4, 0x91F4}, {0x91F5, 0x91F5}, {0x91F6, 0x91F6}, {0x91F7, 0x91F7}, {0x91F8, 0x91F8}, {0x91F9, 0x91F9}, + {0x91FA, 0x91FA}, {0x91FB, 0x91FB}, {0x91FC, 0x91FC}, {0x91FD, 0x91FD}, {0x91FE, 0x91FE}, {0x91FF, 0x91FF}, {0x9200, 0x9200}, + {0x9201, 0x9201}, {0x9202, 0x9202}, {0x9203, 0x9203}, {0x9204, 0x9204}, {0x9205, 0x9205}, {0x9206, 0x9206}, {0x9207, 0x9207}, + {0x9208, 0x9208}, {0x9209, 0x9209}, {0x920A, 0x920A}, {0x920B, 0x920B}, {0x920C, 0x920C}, {0x920D, 0x920D}, {0x920E, 0x920E}, + {0x920F, 0x920F}, {0x9210, 0x9210}, {0x9211, 0x9211}, {0x9212, 0x9212}, {0x9213, 0x9213}, {0x9214, 0x9214}, {0x9215, 0x9215}, + {0x9216, 0x9216}, {0x9217, 0x9217}, {0x9218, 0x9218}, {0x9219, 0x9219}, {0x921A, 0x921A}, {0x921B, 0x921B}, {0x921C, 0x921C}, + {0x921D, 0x921D}, {0x921E, 0x921E}, {0x921F, 0x921F}, {0x9220, 0x9220}, {0x9221, 0x9221}, {0x9222, 0x9222}, {0x9223, 0x9223}, + {0x9224, 0x9224}, {0x9225, 0x9225}, {0x9226, 0x9226}, {0x9227, 0x9227}, {0x9228, 0x9228}, {0x9229, 0x9229}, {0x922A, 0x922A}, + {0x922B, 0x922B}, {0x922C, 0x922C}, {0x922D, 0x922D}, {0x922E, 0x922E}, {0x922F, 0x922F}, {0x9230, 0x9230}, {0x9231, 0x9231}, + {0x9232, 0x9232}, {0x9233, 0x9233}, {0x9234, 0x9234}, {0x9235, 0x9235}, {0x9236, 0x9236}, {0x9237, 0x9237}, {0x9238, 0x9238}, + {0x9239, 0x9239}, {0x923A, 0x923A}, {0x923B, 0x923B}, {0x923C, 0x923C}, {0x923D, 0x923D}, {0x923E, 0x923E}, {0x923F, 0x923F}, + {0x9240, 0x9240}, {0x9241, 0x9241}, {0x9242, 0x9242}, {0x9243, 0x9243}, {0x9244, 0x9244}, {0x9245, 0x9245}, {0x9246, 0x9246}, + {0x9247, 0x9247}, {0x9248, 0x9248}, {0x9249, 0x9249}, {0x924A, 0x924A}, {0x924B, 0x924B}, {0x924C, 0x924C}, {0x924D, 0x924D}, + {0x924E, 0x924E}, {0x924F, 0x924F}, {0x9250, 0x9250}, {0x9251, 0x9251}, {0x9252, 0x9252}, {0x9253, 0x9253}, {0x9254, 0x9254}, + {0x9255, 0x9255}, {0x9256, 0x9256}, {0x9257, 0x9257}, {0x9258, 0x9258}, {0x9259, 0x9259}, {0x925A, 0x925A}, {0x925B, 0x925B}, + {0x925C, 0x925C}, {0x925D, 0x925D}, {0x925E, 0x925E}, {0x925F, 0x925F}, {0x9260, 0x9260}, {0x9261, 0x9261}, {0x9262, 0x9262}, + {0x9263, 0x9263}, {0x9264, 0x9264}, {0x9265, 0x9265}, {0x9266, 0x9266}, {0x9267, 0x9267}, {0x9268, 0x9268}, {0x9269, 0x9269}, + {0x926A, 0x926A}, {0x926B, 0x926B}, {0x926C, 0x926C}, {0x926D, 0x926D}, {0x926E, 0x926E}, {0x926F, 0x926F}, {0x9270, 0x9270}, + {0x9271, 0x9271}, {0x9272, 0x9272}, {0x9273, 0x9273}, {0x9274, 0x9274}, {0x9275, 0x9275}, {0x9276, 0x9276}, {0x9277, 0x9277}, + {0x9278, 0x9278}, {0x9279, 0x9279}, {0x927A, 0x927A}, {0x927B, 0x927B}, {0x927C, 0x927C}, {0x927D, 0x927D}, {0x927E, 0x927E}, + {0x927F, 0x927F}, {0x9280, 0x9280}, {0x9281, 0x9281}, {0x9282, 0x9282}, {0x9283, 0x9283}, {0x9284, 0x9284}, {0x9285, 0x9285}, + {0x9286, 0x9286}, {0x9287, 0x9287}, {0x9288, 0x9288}, {0x9289, 0x9289}, {0x928A, 0x928A}, {0x928B, 0x928B}, {0x928C, 0x928C}, + {0x928D, 0x928D}, {0x928E, 0x928E}, {0x928F, 0x928F}, {0x9290, 0x9290}, {0x9291, 0x9291}, {0x9292, 0x9292}, {0x9293, 0x9293}, + {0x9294, 0x9294}, {0x9295, 0x9295}, {0x9296, 0x9296}, {0x9297, 0x9297}, {0x9298, 0x9298}, {0x9299, 0x9299}, {0x929A, 0x929A}, + {0x929B, 0x929B}, {0x929C, 0x929C}, {0x929D, 0x929D}, {0x929E, 0x929E}, {0x929F, 0x929F}, {0x92A0, 0x92A0}, {0x92A1, 0x92A1}, + {0x92A2, 0x92A2}, {0x92A3, 0x92A3}, {0x92A4, 0x92A4}, {0x92A5, 0x92A5}, {0x92A6, 0x92A6}, {0x92A7, 0x92A7}, {0x92A8, 0x92A8}, + {0x92A9, 0x92A9}, {0x92AA, 0x92AA}, {0x92AB, 0x92AB}, {0x92AC, 0x92AC}, {0x92AD, 0x92AD}, {0x92AE, 0x92AE}, {0x92AF, 0x92AF}, + {0x92B0, 0x92B0}, {0x92B1, 0x92B1}, {0x92B2, 0x92B2}, {0x92B3, 0x92B3}, {0x92B4, 0x92B4}, {0x92B5, 0x92B5}, {0x92B6, 0x92B6}, + {0x92B7, 0x92B7}, {0x92B8, 0x92B8}, {0x92B9, 0x92B9}, {0x92BA, 0x92BA}, {0x92BB, 0x92BB}, {0x92BC, 0x92BC}, {0x92BD, 0x92BD}, + {0x92BE, 0x92BE}, {0x92BF, 0x92BF}, {0x92C0, 0x92C0}, {0x92C1, 0x92C1}, {0x92C2, 0x92C2}, {0x92C3, 0x92C3}, {0x92C4, 0x92C4}, + {0x92C5, 0x92C5}, {0x92C6, 0x92C6}, {0x92C7, 0x92C7}, {0x92C8, 0x92C8}, {0x92C9, 0x92C9}, {0x92CA, 0x92CA}, {0x92CB, 0x92CB}, + {0x92CC, 0x92CC}, {0x92CD, 0x92CD}, {0x92CE, 0x92CE}, {0x92CF, 0x92CF}, {0x92D0, 0x92D0}, {0x92D1, 0x92D1}, {0x92D2, 0x92D2}, + {0x92D3, 0x92D3}, {0x92D4, 0x92D4}, {0x92D5, 0x92D5}, {0x92D6, 0x92D6}, {0x92D7, 0x92D7}, {0x92D8, 0x92D8}, {0x92D9, 0x92D9}, + {0x92DA, 0x92DA}, {0x92DB, 0x92DB}, {0x92DC, 0x92DC}, {0x92DD, 0x92DD}, {0x92DE, 0x92DE}, {0x92DF, 0x92DF}, {0x92E0, 0x92E0}, + {0x92E1, 0x92E1}, {0x92E2, 0x92E2}, {0x92E3, 0x92E3}, {0x92E4, 0x92E4}, {0x92E5, 0x92E5}, {0x92E6, 0x92E6}, {0x92E7, 0x92E7}, + {0x92E8, 0x92E8}, {0x92E9, 0x92E9}, {0x92EA, 0x92EA}, {0x92EB, 0x92EB}, {0x92EC, 0x92EC}, {0x92ED, 0x92ED}, {0x92EE, 0x92EE}, + {0x92EF, 0x92EF}, {0x92F0, 0x92F0}, {0x92F1, 0x92F1}, {0x92F2, 0x92F2}, {0x92F3, 0x92F3}, {0x92F4, 0x92F4}, {0x92F5, 0x92F5}, + {0x92F6, 0x92F6}, {0x92F7, 0x92F7}, {0x92F8, 0x92F8}, {0x92F9, 0x92F9}, {0x92FA, 0x92FA}, {0x92FB, 0x92FB}, {0x92FC, 0x92FC}, + {0x92FD, 0x92FD}, {0x92FE, 0x92FE}, {0x92FF, 0x92FF}, {0x9300, 0x9300}, {0x9301, 0x9301}, {0x9302, 0x9302}, {0x9303, 0x9303}, + {0x9304, 0x9304}, {0x9305, 0x9305}, {0x9306, 0x9306}, {0x9307, 0x9307}, {0x9308, 0x9308}, {0x9309, 0x9309}, {0x930A, 0x930A}, + {0x930B, 0x930B}, {0x930C, 0x930C}, {0x930D, 0x930D}, {0x930E, 0x930E}, {0x930F, 0x930F}, {0x9310, 0x9310}, {0x9311, 0x9311}, + {0x9312, 0x9312}, {0x9313, 0x9313}, {0x9314, 0x9314}, {0x9315, 0x9315}, {0x9316, 0x9316}, {0x9317, 0x9317}, {0x9318, 0x9318}, + {0x9319, 0x9319}, {0x931A, 0x931A}, {0x931B, 0x931B}, {0x931C, 0x931C}, {0x931D, 0x931D}, {0x931E, 0x931E}, {0x931F, 0x931F}, + {0x9320, 0x9320}, {0x9321, 0x9321}, {0x9322, 0x9322}, {0x9323, 0x9323}, {0x9324, 0x9324}, {0x9325, 0x9325}, {0x9326, 0x9326}, + {0x9327, 0x9327}, {0x9328, 0x9328}, {0x9329, 0x9329}, {0x932A, 0x932A}, {0x932B, 0x932B}, {0x932C, 0x932C}, {0x932D, 0x932D}, + {0x932E, 0x932E}, {0x932F, 0x932F}, {0x9330, 0x9330}, {0x9331, 0x9331}, {0x9332, 0x9332}, {0x9333, 0x9333}, {0x9334, 0x9334}, + {0x9335, 0x9335}, {0x9336, 0x9336}, {0x9337, 0x9337}, {0x9338, 0x9338}, {0x9339, 0x9339}, {0x933A, 0x933A}, {0x933B, 0x933B}, + {0x933C, 0x933C}, {0x933D, 0x933D}, {0x933E, 0x933E}, {0x933F, 0x933F}, {0x9340, 0x9340}, {0x9341, 0x9341}, {0x9342, 0x9342}, + {0x9343, 0x9343}, {0x9344, 0x9344}, {0x9345, 0x9345}, {0x9346, 0x9346}, {0x9347, 0x9347}, {0x9348, 0x9348}, {0x9349, 0x9349}, + {0x934A, 0x934A}, {0x934B, 0x934B}, {0x934C, 0x934C}, {0x934D, 0x934D}, {0x934E, 0x934E}, {0x934F, 0x934F}, {0x9350, 0x9350}, + {0x9351, 0x9351}, {0x9352, 0x9352}, {0x9353, 0x9353}, {0x9354, 0x9354}, {0x9355, 0x9355}, {0x9356, 0x9356}, {0x9357, 0x9357}, + {0x9358, 0x9358}, {0x9359, 0x9359}, {0x935A, 0x935A}, {0x935B, 0x935B}, {0x935C, 0x935C}, {0x935D, 0x935D}, {0x935E, 0x935E}, + {0x935F, 0x935F}, {0x9360, 0x9360}, {0x9361, 0x9361}, {0x9362, 0x9362}, {0x9363, 0x9363}, {0x9364, 0x9364}, {0x9365, 0x9365}, + {0x9366, 0x9366}, {0x9367, 0x9367}, {0x9368, 0x9368}, {0x9369, 0x9369}, {0x936A, 0x936A}, {0x936B, 0x936B}, {0x936C, 0x936C}, + {0x936D, 0x936D}, {0x936E, 0x936E}, {0x936F, 0x936F}, {0x9370, 0x9370}, {0x9371, 0x9371}, {0x9372, 0x9372}, {0x9373, 0x9373}, + {0x9374, 0x9374}, {0x9375, 0x9375}, {0x9376, 0x9376}, {0x9377, 0x9377}, {0x9378, 0x9378}, {0x9379, 0x9379}, {0x937A, 0x937A}, + {0x937B, 0x937B}, {0x937C, 0x937C}, {0x937D, 0x937D}, {0x937E, 0x937E}, {0x937F, 0x937F}, {0x9380, 0x9380}, {0x9381, 0x9381}, + {0x9382, 0x9382}, {0x9383, 0x9383}, {0x9384, 0x9384}, {0x9385, 0x9385}, {0x9386, 0x9386}, {0x9387, 0x9387}, {0x9388, 0x9388}, + {0x9389, 0x9389}, {0x938A, 0x938A}, {0x938B, 0x938B}, {0x938C, 0x938C}, {0x938D, 0x938D}, {0x938E, 0x938E}, {0x938F, 0x938F}, + {0x9390, 0x9390}, {0x9391, 0x9391}, {0x9392, 0x9392}, {0x9393, 0x9393}, {0x9394, 0x9394}, {0x9395, 0x9395}, {0x9396, 0x9396}, + {0x9397, 0x9397}, {0x9398, 0x9398}, {0x9399, 0x9399}, {0x939A, 0x939A}, {0x939B, 0x939B}, {0x939C, 0x939C}, {0x939D, 0x939D}, + {0x939E, 0x939E}, {0x939F, 0x939F}, {0x93A0, 0x93A0}, {0x93A1, 0x93A1}, {0x93A2, 0x93A2}, {0x93A3, 0x93A3}, {0x93A4, 0x93A4}, + {0x93A5, 0x93A5}, {0x93A6, 0x93A6}, {0x93A7, 0x93A7}, {0x93A8, 0x93A8}, {0x93A9, 0x93A9}, {0x93AA, 0x93AA}, {0x93AB, 0x93AB}, + {0x93AC, 0x93AC}, {0x93AD, 0x93AD}, {0x93AE, 0x93AE}, {0x93AF, 0x93AF}, {0x93B0, 0x93B0}, {0x93B1, 0x93B1}, {0x93B2, 0x93B2}, + {0x93B3, 0x93B3}, {0x93B4, 0x93B4}, {0x93B5, 0x93B5}, {0x93B6, 0x93B6}, {0x93B7, 0x93B7}, {0x93B8, 0x93B8}, {0x93B9, 0x93B9}, + {0x93BA, 0x93BA}, {0x93BB, 0x93BB}, {0x93BC, 0x93BC}, {0x93BD, 0x93BD}, {0x93BE, 0x93BE}, {0x93BF, 0x93BF}, {0x93C0, 0x93C0}, + {0x93C1, 0x93C1}, {0x93C2, 0x93C2}, {0x93C3, 0x93C3}, {0x93C4, 0x93C4}, {0x93C5, 0x93C5}, {0x93C6, 0x93C6}, {0x93C7, 0x93C7}, + {0x93C8, 0x93C8}, {0x93C9, 0x93C9}, {0x93CA, 0x93CA}, {0x93CB, 0x93CB}, {0x93CC, 0x93CC}, {0x93CD, 0x93CD}, {0x93CE, 0x93CE}, + {0x93CF, 0x93CF}, {0x93D0, 0x93D0}, {0x93D1, 0x93D1}, {0x93D2, 0x93D2}, {0x93D3, 0x93D3}, {0x93D4, 0x93D4}, {0x93D5, 0x93D5}, + {0x93D6, 0x93D6}, {0x93D7, 0x93D7}, {0x93D8, 0x93D8}, {0x93D9, 0x93D9}, {0x93DA, 0x93DA}, {0x93DB, 0x93DB}, {0x93DC, 0x93DC}, + {0x93DD, 0x93DD}, {0x93DE, 0x93DE}, {0x93DF, 0x93DF}, {0x93E0, 0x93E0}, {0x93E1, 0x93E1}, {0x93E2, 0x93E2}, {0x93E3, 0x93E3}, + {0x93E4, 0x93E4}, {0x93E5, 0x93E5}, {0x93E6, 0x93E6}, {0x93E7, 0x93E7}, {0x93E8, 0x93E8}, {0x93E9, 0x93E9}, {0x93EA, 0x93EA}, + {0x93EB, 0x93EB}, {0x93EC, 0x93EC}, {0x93ED, 0x93ED}, {0x93EE, 0x93EE}, {0x93EF, 0x93EF}, {0x93F0, 0x93F0}, {0x93F1, 0x93F1}, + {0x93F2, 0x93F2}, {0x93F3, 0x93F3}, {0x93F4, 0x93F4}, {0x93F5, 0x93F5}, {0x93F6, 0x93F6}, {0x93F7, 0x93F7}, {0x93F8, 0x93F8}, + {0x93F9, 0x93F9}, {0x93FA, 0x93FA}, {0x93FB, 0x93FB}, {0x93FC, 0x93FC}, {0x93FD, 0x93FD}, {0x93FE, 0x93FE}, {0x93FF, 0x93FF}, + {0x9400, 0x9400}, {0x9401, 0x9401}, {0x9402, 0x9402}, {0x9403, 0x9403}, {0x9404, 0x9404}, {0x9405, 0x9405}, {0x9406, 0x9406}, + {0x9407, 0x9407}, {0x9408, 0x9408}, {0x9409, 0x9409}, {0x940A, 0x940A}, {0x940B, 0x940B}, {0x940C, 0x940C}, {0x940D, 0x940D}, + {0x940E, 0x940E}, {0x940F, 0x940F}, {0x9410, 0x9410}, {0x9411, 0x9411}, {0x9412, 0x9412}, {0x9413, 0x9413}, {0x9414, 0x9414}, + {0x9415, 0x9415}, {0x9416, 0x9416}, {0x9417, 0x9417}, {0x9418, 0x9418}, {0x9419, 0x9419}, {0x941A, 0x941A}, {0x941B, 0x941B}, + {0x941C, 0x941C}, {0x941D, 0x941D}, {0x941E, 0x941E}, {0x941F, 0x941F}, {0x9420, 0x9420}, {0x9421, 0x9421}, {0x9422, 0x9422}, + {0x9423, 0x9423}, {0x9424, 0x9424}, {0x9425, 0x9425}, {0x9426, 0x9426}, {0x9427, 0x9427}, {0x9428, 0x9428}, {0x9429, 0x9429}, + {0x942A, 0x942A}, {0x942B, 0x942B}, {0x942C, 0x942C}, {0x942D, 0x942D}, {0x942E, 0x942E}, {0x942F, 0x942F}, {0x9430, 0x9430}, + {0x9431, 0x9431}, {0x9432, 0x9432}, {0x9433, 0x9433}, {0x9434, 0x9434}, {0x9435, 0x9435}, {0x9436, 0x9436}, {0x9437, 0x9437}, + {0x9438, 0x9438}, {0x9439, 0x9439}, {0x943A, 0x943A}, {0x943B, 0x943B}, {0x943C, 0x943C}, {0x943D, 0x943D}, {0x943E, 0x943E}, + {0x943F, 0x943F}, {0x9440, 0x9440}, {0x9441, 0x9441}, {0x9442, 0x9442}, {0x9443, 0x9443}, {0x9444, 0x9444}, {0x9445, 0x9445}, + {0x9446, 0x9446}, {0x9447, 0x9447}, {0x9448, 0x9448}, {0x9449, 0x9449}, {0x944A, 0x944A}, {0x944B, 0x944B}, {0x944C, 0x944C}, + {0x944D, 0x944D}, {0x944E, 0x944E}, {0x944F, 0x944F}, {0x9450, 0x9450}, {0x9451, 0x9451}, {0x9452, 0x9452}, {0x9453, 0x9453}, + {0x9454, 0x9454}, {0x9455, 0x9455}, {0x9456, 0x9456}, {0x9457, 0x9457}, {0x9458, 0x9458}, {0x9459, 0x9459}, {0x945A, 0x945A}, + {0x945B, 0x945B}, {0x945C, 0x945C}, {0x945D, 0x945D}, {0x945E, 0x945E}, {0x945F, 0x945F}, {0x9460, 0x9460}, {0x9461, 0x9461}, + {0x9462, 0x9462}, {0x9463, 0x9463}, {0x9464, 0x9464}, {0x9465, 0x9465}, {0x9466, 0x9466}, {0x9467, 0x9467}, {0x9468, 0x9468}, + {0x9469, 0x9469}, {0x946A, 0x946A}, {0x946B, 0x946B}, {0x946C, 0x946C}, {0x946D, 0x946D}, {0x946E, 0x946E}, {0x946F, 0x946F}, + {0x9470, 0x9470}, {0x9471, 0x9471}, {0x9472, 0x9472}, {0x9473, 0x9473}, {0x9474, 0x9474}, {0x9475, 0x9475}, {0x9476, 0x9476}, + {0x9477, 0x9477}, {0x9478, 0x9478}, {0x9479, 0x9479}, {0x947A, 0x947A}, {0x947B, 0x947B}, {0x947C, 0x947C}, {0x947D, 0x947D}, + {0x947E, 0x947E}, {0x947F, 0x947F}, {0x9480, 0x9480}, {0x9481, 0x9481}, {0x9482, 0x9482}, {0x9483, 0x9483}, {0x9484, 0x9484}, + {0x9485, 0x9485}, {0x9486, 0x9486}, {0x9487, 0x9487}, {0x9488, 0x9488}, {0x9489, 0x9489}, {0x948A, 0x948A}, {0x948B, 0x948B}, + {0x948C, 0x948C}, {0x948D, 0x948D}, {0x948E, 0x948E}, {0x948F, 0x948F}, {0x9490, 0x9490}, {0x9491, 0x9491}, {0x9492, 0x9492}, + {0x9493, 0x9493}, {0x9494, 0x9494}, {0x9495, 0x9495}, {0x9496, 0x9496}, {0x9497, 0x9497}, {0x9498, 0x9498}, {0x9499, 0x9499}, + {0x949A, 0x949A}, {0x949B, 0x949B}, {0x949C, 0x949C}, {0x949D, 0x949D}, {0x949E, 0x949E}, {0x949F, 0x949F}, {0x94A0, 0x94A0}, + {0x94A1, 0x94A1}, {0x94A2, 0x94A2}, {0x94A3, 0x94A3}, {0x94A4, 0x94A4}, {0x94A5, 0x94A5}, {0x94A6, 0x94A6}, {0x94A7, 0x94A7}, + {0x94A8, 0x94A8}, {0x94A9, 0x94A9}, {0x94AA, 0x94AA}, {0x94AB, 0x94AB}, {0x94AC, 0x94AC}, {0x94AD, 0x94AD}, {0x94AE, 0x94AE}, + {0x94AF, 0x94AF}, {0x94B0, 0x94B0}, {0x94B1, 0x94B1}, {0x94B2, 0x94B2}, {0x94B3, 0x94B3}, {0x94B4, 0x94B4}, {0x94B5, 0x94B5}, + {0x94B6, 0x94B6}, {0x94B7, 0x94B7}, {0x94B8, 0x94B8}, {0x94B9, 0x94B9}, {0x94BA, 0x94BA}, {0x94BB, 0x94BB}, {0x94BC, 0x94BC}, + {0x94BD, 0x94BD}, {0x94BE, 0x94BE}, {0x94BF, 0x94BF}, {0x94C0, 0x94C0}, {0x94C1, 0x94C1}, {0x94C2, 0x94C2}, {0x94C3, 0x94C3}, + {0x94C4, 0x94C4}, {0x94C5, 0x94C5}, {0x94C6, 0x94C6}, {0x94C7, 0x94C7}, {0x94C8, 0x94C8}, {0x94C9, 0x94C9}, {0x94CA, 0x94CA}, + {0x94CB, 0x94CB}, {0x94CC, 0x94CC}, {0x94CD, 0x94CD}, {0x94CE, 0x94CE}, {0x94CF, 0x94CF}, {0x94D0, 0x94D0}, {0x94D1, 0x94D1}, + {0x94D2, 0x94D2}, {0x94D3, 0x94D3}, {0x94D4, 0x94D4}, {0x94D5, 0x94D5}, {0x94D6, 0x94D6}, {0x94D7, 0x94D7}, {0x94D8, 0x94D8}, + {0x94D9, 0x94D9}, {0x94DA, 0x94DA}, {0x94DB, 0x94DB}, {0x94DC, 0x94DC}, {0x94DD, 0x94DD}, {0x94DE, 0x94DE}, {0x94DF, 0x94DF}, + {0x94E0, 0x94E0}, {0x94E1, 0x94E1}, {0x94E2, 0x94E2}, {0x94E3, 0x94E3}, {0x94E4, 0x94E4}, {0x94E5, 0x94E5}, {0x94E6, 0x94E6}, + {0x94E7, 0x94E7}, {0x94E8, 0x94E8}, {0x94E9, 0x94E9}, {0x94EA, 0x94EA}, {0x94EB, 0x94EB}, {0x94EC, 0x94EC}, {0x94ED, 0x94ED}, + {0x94EE, 0x94EE}, {0x94EF, 0x94EF}, {0x94F0, 0x94F0}, {0x94F1, 0x94F1}, {0x94F2, 0x94F2}, {0x94F3, 0x94F3}, {0x94F4, 0x94F4}, + {0x94F5, 0x94F5}, {0x94F6, 0x94F6}, {0x94F7, 0x94F7}, {0x94F8, 0x94F8}, {0x94F9, 0x94F9}, {0x94FA, 0x94FA}, {0x94FB, 0x94FB}, + {0x94FC, 0x94FC}, {0x94FD, 0x94FD}, {0x94FE, 0x94FE}, {0x94FF, 0x94FF}, {0x9500, 0x9500}, {0x9501, 0x9501}, {0x9502, 0x9502}, + {0x9503, 0x9503}, {0x9504, 0x9504}, {0x9505, 0x9505}, {0x9506, 0x9506}, {0x9507, 0x9507}, {0x9508, 0x9508}, {0x9509, 0x9509}, + {0x950A, 0x950A}, {0x950B, 0x950B}, {0x950C, 0x950C}, {0x950D, 0x950D}, {0x950E, 0x950E}, {0x950F, 0x950F}, {0x9510, 0x9510}, + {0x9511, 0x9511}, {0x9512, 0x9512}, {0x9513, 0x9513}, {0x9514, 0x9514}, {0x9515, 0x9515}, {0x9516, 0x9516}, {0x9517, 0x9517}, + {0x9518, 0x9518}, {0x9519, 0x9519}, {0x951A, 0x951A}, {0x951B, 0x951B}, {0x951C, 0x951C}, {0x951D, 0x951D}, {0x951E, 0x951E}, + {0x951F, 0x951F}, {0x9520, 0x9520}, {0x9521, 0x9521}, {0x9522, 0x9522}, {0x9523, 0x9523}, {0x9524, 0x9524}, {0x9525, 0x9525}, + {0x9526, 0x9526}, {0x9527, 0x9527}, {0x9528, 0x9528}, {0x9529, 0x9529}, {0x952A, 0x952A}, {0x952B, 0x952B}, {0x952C, 0x952C}, + {0x952D, 0x952D}, {0x952E, 0x952E}, {0x952F, 0x952F}, {0x9530, 0x9530}, {0x9531, 0x9531}, {0x9532, 0x9532}, {0x9533, 0x9533}, + {0x9534, 0x9534}, {0x9535, 0x9535}, {0x9536, 0x9536}, {0x9537, 0x9537}, {0x9538, 0x9538}, {0x9539, 0x9539}, {0x953A, 0x953A}, + {0x953B, 0x953B}, {0x953C, 0x953C}, {0x953D, 0x953D}, {0x953E, 0x953E}, {0x953F, 0x953F}, {0x9540, 0x9540}, {0x9541, 0x9541}, + {0x9542, 0x9542}, {0x9543, 0x9543}, {0x9544, 0x9544}, {0x9545, 0x9545}, {0x9546, 0x9546}, {0x9547, 0x9547}, {0x9548, 0x9548}, + {0x9549, 0x9549}, {0x954A, 0x954A}, {0x954B, 0x954B}, {0x954C, 0x954C}, {0x954D, 0x954D}, {0x954E, 0x954E}, {0x954F, 0x954F}, + {0x9550, 0x9550}, {0x9551, 0x9551}, {0x9552, 0x9552}, {0x9553, 0x9553}, {0x9554, 0x9554}, {0x9555, 0x9555}, {0x9556, 0x9556}, + {0x9557, 0x9557}, {0x9558, 0x9558}, {0x9559, 0x9559}, {0x955A, 0x955A}, {0x955B, 0x955B}, {0x955C, 0x955C}, {0x955D, 0x955D}, + {0x955E, 0x955E}, {0x955F, 0x955F}, {0x9560, 0x9560}, {0x9561, 0x9561}, {0x9562, 0x9562}, {0x9563, 0x9563}, {0x9564, 0x9564}, + {0x9565, 0x9565}, {0x9566, 0x9566}, {0x9567, 0x9567}, {0x9568, 0x9568}, {0x9569, 0x9569}, {0x956A, 0x956A}, {0x956B, 0x956B}, + {0x956C, 0x956C}, {0x956D, 0x956D}, {0x956E, 0x956E}, {0x956F, 0x956F}, {0x9570, 0x9570}, {0x9571, 0x9571}, {0x9572, 0x9572}, + {0x9573, 0x9573}, {0x9574, 0x9574}, {0x9575, 0x9575}, {0x9576, 0x9576}, {0x9577, 0x9577}, {0x9578, 0x9578}, {0x9579, 0x9579}, + {0x957A, 0x957A}, {0x957B, 0x957B}, {0x957C, 0x957C}, {0x957D, 0x957D}, {0x957E, 0x957E}, {0x957F, 0x957F}, {0x9580, 0x9580}, + {0x9581, 0x9581}, {0x9582, 0x9582}, {0x9583, 0x9583}, {0x9584, 0x9584}, {0x9585, 0x9585}, {0x9586, 0x9586}, {0x9587, 0x9587}, + {0x9588, 0x9588}, {0x9589, 0x9589}, {0x958A, 0x958A}, {0x958B, 0x958B}, {0x958C, 0x958C}, {0x958D, 0x958D}, {0x958E, 0x958E}, + {0x958F, 0x958F}, {0x9590, 0x9590}, {0x9591, 0x9591}, {0x9592, 0x9592}, {0x9593, 0x9593}, {0x9594, 0x9594}, {0x9595, 0x9595}, + {0x9596, 0x9596}, {0x9597, 0x9597}, {0x9598, 0x9598}, {0x9599, 0x9599}, {0x959A, 0x959A}, {0x959B, 0x959B}, {0x959C, 0x959C}, + {0x959D, 0x959D}, {0x959E, 0x959E}, {0x959F, 0x959F}, {0x95A0, 0x95A0}, {0x95A1, 0x95A1}, {0x95A2, 0x95A2}, {0x95A3, 0x95A3}, + {0x95A4, 0x95A4}, {0x95A5, 0x95A5}, {0x95A6, 0x95A6}, {0x95A7, 0x95A7}, {0x95A8, 0x95A8}, {0x95A9, 0x95A9}, {0x95AA, 0x95AA}, + {0x95AB, 0x95AB}, {0x95AC, 0x95AC}, {0x95AD, 0x95AD}, {0x95AE, 0x95AE}, {0x95AF, 0x95AF}, {0x95B0, 0x95B0}, {0x95B1, 0x95B1}, + {0x95B2, 0x95B2}, {0x95B3, 0x95B3}, {0x95B4, 0x95B4}, {0x95B5, 0x95B5}, {0x95B6, 0x95B6}, {0x95B7, 0x95B7}, {0x95B8, 0x95B8}, + {0x95B9, 0x95B9}, {0x95BA, 0x95BA}, {0x95BB, 0x95BB}, {0x95BC, 0x95BC}, {0x95BD, 0x95BD}, {0x95BE, 0x95BE}, {0x95BF, 0x95BF}, + {0x95C0, 0x95C0}, {0x95C1, 0x95C1}, {0x95C2, 0x95C2}, {0x95C3, 0x95C3}, {0x95C4, 0x95C4}, {0x95C5, 0x95C5}, {0x95C6, 0x95C6}, + {0x95C7, 0x95C7}, {0x95C8, 0x95C8}, {0x95C9, 0x95C9}, {0x95CA, 0x95CA}, {0x95CB, 0x95CB}, {0x95CC, 0x95CC}, {0x95CD, 0x95CD}, + {0x95CE, 0x95CE}, {0x95CF, 0x95CF}, {0x95D0, 0x95D0}, {0x95D1, 0x95D1}, {0x95D2, 0x95D2}, {0x95D3, 0x95D3}, {0x95D4, 0x95D4}, + {0x95D5, 0x95D5}, {0x95D6, 0x95D6}, {0x95D7, 0x95D7}, {0x95D8, 0x95D8}, {0x95D9, 0x95D9}, {0x95DA, 0x95DA}, {0x95DB, 0x95DB}, + {0x95DC, 0x95DC}, {0x95DD, 0x95DD}, {0x95DE, 0x95DE}, {0x95DF, 0x95DF}, {0x95E0, 0x95E0}, {0x95E1, 0x95E1}, {0x95E2, 0x95E2}, + {0x95E3, 0x95E3}, {0x95E4, 0x95E4}, {0x95E5, 0x95E5}, {0x95E6, 0x95E6}, {0x95E7, 0x95E7}, {0x95E8, 0x95E8}, {0x95E9, 0x95E9}, + {0x95EA, 0x95EA}, {0x95EB, 0x95EB}, {0x95EC, 0x95EC}, {0x95ED, 0x95ED}, {0x95EE, 0x95EE}, {0x95EF, 0x95EF}, {0x95F0, 0x95F0}, + {0x95F1, 0x95F1}, {0x95F2, 0x95F2}, {0x95F3, 0x95F3}, {0x95F4, 0x95F4}, {0x95F5, 0x95F5}, {0x95F6, 0x95F6}, {0x95F7, 0x95F7}, + {0x95F8, 0x95F8}, {0x95F9, 0x95F9}, {0x95FA, 0x95FA}, {0x95FB, 0x95FB}, {0x95FC, 0x95FC}, {0x95FD, 0x95FD}, {0x95FE, 0x95FE}, + {0x95FF, 0x95FF}, {0x9600, 0x9600}, {0x9601, 0x9601}, {0x9602, 0x9602}, {0x9603, 0x9603}, {0x9604, 0x9604}, {0x9605, 0x9605}, + {0x9606, 0x9606}, {0x9607, 0x9607}, {0x9608, 0x9608}, {0x9609, 0x9609}, {0x960A, 0x960A}, {0x960B, 0x960B}, {0x960C, 0x960C}, + {0x960D, 0x960D}, {0x960E, 0x960E}, {0x960F, 0x960F}, {0x9610, 0x9610}, {0x9611, 0x9611}, {0x9612, 0x9612}, {0x9613, 0x9613}, + {0x9614, 0x9614}, {0x9615, 0x9615}, {0x9616, 0x9616}, {0x9617, 0x9617}, {0x9618, 0x9618}, {0x9619, 0x9619}, {0x961A, 0x961A}, + {0x961B, 0x961B}, {0x961C, 0x961C}, {0x961D, 0x961D}, {0x961E, 0x961E}, {0x961F, 0x961F}, {0x9620, 0x9620}, {0x9621, 0x9621}, + {0x9622, 0x9622}, {0x9623, 0x9623}, {0x9624, 0x9624}, {0x9625, 0x9625}, {0x9626, 0x9626}, {0x9627, 0x9627}, {0x9628, 0x9628}, + {0x9629, 0x9629}, {0x962A, 0x962A}, {0x962B, 0x962B}, {0x962C, 0x962C}, {0x962D, 0x962D}, {0x962E, 0x962E}, {0x962F, 0x962F}, + {0x9630, 0x9630}, {0x9631, 0x9631}, {0x9632, 0x9632}, {0x9633, 0x9633}, {0x9634, 0x9634}, {0x9635, 0x9635}, {0x9636, 0x9636}, + {0x9637, 0x9637}, {0x9638, 0x9638}, {0x9639, 0x9639}, {0x963A, 0x963A}, {0x963B, 0x963B}, {0x963C, 0x963C}, {0x963D, 0x963D}, + {0x963E, 0x963E}, {0x963F, 0x963F}, {0x9640, 0x9640}, {0x9641, 0x9641}, {0x9642, 0x9642}, {0x9643, 0x9643}, {0x9644, 0x9644}, + {0x9645, 0x9645}, {0x9646, 0x9646}, {0x9647, 0x9647}, {0x9648, 0x9648}, {0x9649, 0x9649}, {0x964A, 0x964A}, {0x964B, 0x964B}, + {0x964C, 0x964C}, {0x964D, 0x964D}, {0x964E, 0x964E}, {0x964F, 0x964F}, {0x9650, 0x9650}, {0x9651, 0x9651}, {0x9652, 0x9652}, + {0x9653, 0x9653}, {0x9654, 0x9654}, {0x9655, 0x9655}, {0x9656, 0x9656}, {0x9657, 0x9657}, {0x9658, 0x9658}, {0x9659, 0x9659}, + {0x965A, 0x965A}, {0x965B, 0x965B}, {0x965C, 0x965C}, {0x965D, 0x965D}, {0x965E, 0x965E}, {0x965F, 0x965F}, {0x9660, 0x9660}, + {0x9661, 0x9661}, {0x9662, 0x9662}, {0x9663, 0x9663}, {0x9664, 0x9664}, {0x9665, 0x9665}, {0x9666, 0x9666}, {0x9667, 0x9667}, + {0x9668, 0x9668}, {0x9669, 0x9669}, {0x966A, 0x966A}, {0x966B, 0x966B}, {0x966C, 0x966C}, {0x966D, 0x966D}, {0x966E, 0x966E}, + {0x966F, 0x966F}, {0x9670, 0x9670}, {0x9671, 0x9671}, {0x9672, 0x9672}, {0x9673, 0x9673}, {0x9674, 0x9674}, {0x9675, 0x9675}, + {0x9676, 0x9676}, {0x9677, 0x9677}, {0x9678, 0x9678}, {0x9679, 0x9679}, {0x967A, 0x967A}, {0x967B, 0x967B}, {0x967C, 0x967C}, + {0x967D, 0x967D}, {0x967E, 0x967E}, {0x967F, 0x967F}, {0x9680, 0x9680}, {0x9681, 0x9681}, {0x9682, 0x9682}, {0x9683, 0x9683}, + {0x9684, 0x9684}, {0x9685, 0x9685}, {0x9686, 0x9686}, {0x9687, 0x9687}, {0x9688, 0x9688}, {0x9689, 0x9689}, {0x968A, 0x968A}, + {0x968B, 0x968B}, {0x968C, 0x968C}, {0x968D, 0x968D}, {0x968E, 0x968E}, {0x968F, 0x968F}, {0x9690, 0x9690}, {0x9691, 0x9691}, + {0x9692, 0x9692}, {0x9693, 0x9693}, {0x9694, 0x9694}, {0x9695, 0x9695}, {0x9696, 0x9696}, {0x9697, 0x9697}, {0x9698, 0x9698}, + {0x9699, 0x9699}, {0x969A, 0x969A}, {0x969B, 0x969B}, {0x969C, 0x969C}, {0x969D, 0x969D}, {0x969E, 0x969E}, {0x969F, 0x969F}, + {0x96A0, 0x96A0}, {0x96A1, 0x96A1}, {0x96A2, 0x96A2}, {0x96A3, 0x96A3}, {0x96A4, 0x96A4}, {0x96A5, 0x96A5}, {0x96A6, 0x96A6}, + {0x96A7, 0x96A7}, {0x96A8, 0x96A8}, {0x96A9, 0x96A9}, {0x96AA, 0x96AA}, {0x96AB, 0x96AB}, {0x96AC, 0x96AC}, {0x96AD, 0x96AD}, + {0x96AE, 0x96AE}, {0x96AF, 0x96AF}, {0x96B0, 0x96B0}, {0x96B1, 0x96B1}, {0x96B2, 0x96B2}, {0x96B3, 0x96B3}, {0x96B4, 0x96B4}, + {0x96B5, 0x96B5}, {0x96B6, 0x96B6}, {0x96B7, 0x96B7}, {0x96B8, 0x96B8}, {0x96B9, 0x96B9}, {0x96BA, 0x96BA}, {0x96BB, 0x96BB}, + {0x96BC, 0x96BC}, {0x96BD, 0x96BD}, {0x96BE, 0x96BE}, {0x96BF, 0x96BF}, {0x96C0, 0x96C0}, {0x96C1, 0x96C1}, {0x96C2, 0x96C2}, + {0x96C3, 0x96C3}, {0x96C4, 0x96C4}, {0x96C5, 0x96C5}, {0x96C6, 0x96C6}, {0x96C7, 0x96C7}, {0x96C8, 0x96C8}, {0x96C9, 0x96C9}, + {0x96CA, 0x96CA}, {0x96CB, 0x96CB}, {0x96CC, 0x96CC}, {0x96CD, 0x96CD}, {0x96CE, 0x96CE}, {0x96CF, 0x96CF}, {0x96D0, 0x96D0}, + {0x96D1, 0x96D1}, {0x96D2, 0x96D2}, {0x96D3, 0x96D3}, {0x96D4, 0x96D4}, {0x96D5, 0x96D5}, {0x96D6, 0x96D6}, {0x96D7, 0x96D7}, + {0x96D8, 0x96D8}, {0x96D9, 0x96D9}, {0x96DA, 0x96DA}, {0x96DB, 0x96DB}, {0x96DC, 0x96DC}, {0x96DD, 0x96DD}, {0x96DE, 0x96DE}, + {0x96DF, 0x96DF}, {0x96E0, 0x96E0}, {0x96E1, 0x96E1}, {0x96E2, 0x96E2}, {0x96E3, 0x96E3}, {0x96E4, 0x96E4}, {0x96E5, 0x96E5}, + {0x96E6, 0x96E6}, {0x96E7, 0x96E7}, {0x96E8, 0x96E8}, {0x96E9, 0x96E9}, {0x96EA, 0x96EA}, {0x96EB, 0x96EB}, {0x96EC, 0x96EC}, + {0x96ED, 0x96ED}, {0x96EE, 0x96EE}, {0x96EF, 0x96EF}, {0x96F0, 0x96F0}, {0x96F1, 0x96F1}, {0x96F2, 0x96F2}, {0x96F3, 0x96F3}, + {0x96F4, 0x96F4}, {0x96F5, 0x96F5}, {0x96F6, 0x96F6}, {0x96F7, 0x96F7}, {0x96F8, 0x96F8}, {0x96F9, 0x96F9}, {0x96FA, 0x96FA}, + {0x96FB, 0x96FB}, {0x96FC, 0x96FC}, {0x96FD, 0x96FD}, {0x96FE, 0x96FE}, {0x96FF, 0x96FF}, {0x9700, 0x9700}, {0x9701, 0x9701}, + {0x9702, 0x9702}, {0x9703, 0x9703}, {0x9704, 0x9704}, {0x9705, 0x9705}, {0x9706, 0x9706}, {0x9707, 0x9707}, {0x9708, 0x9708}, + {0x9709, 0x9709}, {0x970A, 0x970A}, {0x970B, 0x970B}, {0x970C, 0x970C}, {0x970D, 0x970D}, {0x970E, 0x970E}, {0x970F, 0x970F}, + {0x9710, 0x9710}, {0x9711, 0x9711}, {0x9712, 0x9712}, {0x9713, 0x9713}, {0x9714, 0x9714}, {0x9715, 0x9715}, {0x9716, 0x9716}, + {0x9717, 0x9717}, {0x9718, 0x9718}, {0x9719, 0x9719}, {0x971A, 0x971A}, {0x971B, 0x971B}, {0x971C, 0x971C}, {0x971D, 0x971D}, + {0x971E, 0x971E}, {0x971F, 0x971F}, {0x9720, 0x9720}, {0x9721, 0x9721}, {0x9722, 0x9722}, {0x9723, 0x9723}, {0x9724, 0x9724}, + {0x9725, 0x9725}, {0x9726, 0x9726}, {0x9727, 0x9727}, {0x9728, 0x9728}, {0x9729, 0x9729}, {0x972A, 0x972A}, {0x972B, 0x972B}, + {0x972C, 0x972C}, {0x972D, 0x972D}, {0x972E, 0x972E}, {0x972F, 0x972F}, {0x9730, 0x9730}, {0x9731, 0x9731}, {0x9732, 0x9732}, + {0x9733, 0x9733}, {0x9734, 0x9734}, {0x9735, 0x9735}, {0x9736, 0x9736}, {0x9737, 0x9737}, {0x9738, 0x9738}, {0x9739, 0x9739}, + {0x973A, 0x973A}, {0x973B, 0x973B}, {0x973C, 0x973C}, {0x973D, 0x973D}, {0x973E, 0x973E}, {0x973F, 0x973F}, {0x9740, 0x9740}, + {0x9741, 0x9741}, {0x9742, 0x9742}, {0x9743, 0x9743}, {0x9744, 0x9744}, {0x9745, 0x9745}, {0x9746, 0x9746}, {0x9747, 0x9747}, + {0x9748, 0x9748}, {0x9749, 0x9749}, {0x974A, 0x974A}, {0x974B, 0x974B}, {0x974C, 0x974C}, {0x974D, 0x974D}, {0x974E, 0x974E}, + {0x974F, 0x974F}, {0x9750, 0x9750}, {0x9751, 0x9751}, {0x9752, 0x9752}, {0x9753, 0x9753}, {0x9754, 0x9754}, {0x9755, 0x9755}, + {0x9756, 0x9756}, {0x9757, 0x9757}, {0x9758, 0x9758}, {0x9759, 0x9759}, {0x975A, 0x975A}, {0x975B, 0x975B}, {0x975C, 0x975C}, + {0x975D, 0x975D}, {0x975E, 0x975E}, {0x975F, 0x975F}, {0x9760, 0x9760}, {0x9761, 0x9761}, {0x9762, 0x9762}, {0x9763, 0x9763}, + {0x9764, 0x9764}, {0x9765, 0x9765}, {0x9766, 0x9766}, {0x9767, 0x9767}, {0x9768, 0x9768}, {0x9769, 0x9769}, {0x976A, 0x976A}, + {0x976B, 0x976B}, {0x976C, 0x976C}, {0x976D, 0x976D}, {0x976E, 0x976E}, {0x976F, 0x976F}, {0x9770, 0x9770}, {0x9771, 0x9771}, + {0x9772, 0x9772}, {0x9773, 0x9773}, {0x9774, 0x9774}, {0x9775, 0x9775}, {0x9776, 0x9776}, {0x9777, 0x9777}, {0x9778, 0x9778}, + {0x9779, 0x9779}, {0x977A, 0x977A}, {0x977B, 0x977B}, {0x977C, 0x977C}, {0x977D, 0x977D}, {0x977E, 0x977E}, {0x977F, 0x977F}, + {0x9780, 0x9780}, {0x9781, 0x9781}, {0x9782, 0x9782}, {0x9783, 0x9783}, {0x9784, 0x9784}, {0x9785, 0x9785}, {0x9786, 0x9786}, + {0x9787, 0x9787}, {0x9788, 0x9788}, {0x9789, 0x9789}, {0x978A, 0x978A}, {0x978B, 0x978B}, {0x978C, 0x978C}, {0x978D, 0x978D}, + {0x978E, 0x978E}, {0x978F, 0x978F}, {0x9790, 0x9790}, {0x9791, 0x9791}, {0x9792, 0x9792}, {0x9793, 0x9793}, {0x9794, 0x9794}, + {0x9795, 0x9795}, {0x9796, 0x9796}, {0x9797, 0x9797}, {0x9798, 0x9798}, {0x9799, 0x9799}, {0x979A, 0x979A}, {0x979B, 0x979B}, + {0x979C, 0x979C}, {0x979D, 0x979D}, {0x979E, 0x979E}, {0x979F, 0x979F}, {0x97A0, 0x97A0}, {0x97A1, 0x97A1}, {0x97A2, 0x97A2}, + {0x97A3, 0x97A3}, {0x97A4, 0x97A4}, {0x97A5, 0x97A5}, {0x97A6, 0x97A6}, {0x97A7, 0x97A7}, {0x97A8, 0x97A8}, {0x97A9, 0x97A9}, + {0x97AA, 0x97AA}, {0x97AB, 0x97AB}, {0x97AC, 0x97AC}, {0x97AD, 0x97AD}, {0x97AE, 0x97AE}, {0x97AF, 0x97AF}, {0x97B0, 0x97B0}, + {0x97B1, 0x97B1}, {0x97B2, 0x97B2}, {0x97B3, 0x97B3}, {0x97B4, 0x97B4}, {0x97B5, 0x97B5}, {0x97B6, 0x97B6}, {0x97B7, 0x97B7}, + {0x97B8, 0x97B8}, {0x97B9, 0x97B9}, {0x97BA, 0x97BA}, {0x97BB, 0x97BB}, {0x97BC, 0x97BC}, {0x97BD, 0x97BD}, {0x97BE, 0x97BE}, + {0x97BF, 0x97BF}, {0x97C0, 0x97C0}, {0x97C1, 0x97C1}, {0x97C2, 0x97C2}, {0x97C3, 0x97C3}, {0x97C4, 0x97C4}, {0x97C5, 0x97C5}, + {0x97C6, 0x97C6}, {0x97C7, 0x97C7}, {0x97C8, 0x97C8}, {0x97C9, 0x97C9}, {0x97CA, 0x97CA}, {0x97CB, 0x97CB}, {0x97CC, 0x97CC}, + {0x97CD, 0x97CD}, {0x97CE, 0x97CE}, {0x97CF, 0x97CF}, {0x97D0, 0x97D0}, {0x97D1, 0x97D1}, {0x97D2, 0x97D2}, {0x97D3, 0x97D3}, + {0x97D4, 0x97D4}, {0x97D5, 0x97D5}, {0x97D6, 0x97D6}, {0x97D7, 0x97D7}, {0x97D8, 0x97D8}, {0x97D9, 0x97D9}, {0x97DA, 0x97DA}, + {0x97DB, 0x97DB}, {0x97DC, 0x97DC}, {0x97DD, 0x97DD}, {0x97DE, 0x97DE}, {0x97DF, 0x97DF}, {0x97E0, 0x97E0}, {0x97E1, 0x97E1}, + {0x97E2, 0x97E2}, {0x97E3, 0x97E3}, {0x97E4, 0x97E4}, {0x97E5, 0x97E5}, {0x97E6, 0x97E6}, {0x97E7, 0x97E7}, {0x97E8, 0x97E8}, + {0x97E9, 0x97E9}, {0x97EA, 0x97EA}, {0x97EB, 0x97EB}, {0x97EC, 0x97EC}, {0x97ED, 0x97ED}, {0x97EE, 0x97EE}, {0x97EF, 0x97EF}, + {0x97F0, 0x97F0}, {0x97F1, 0x97F1}, {0x97F2, 0x97F2}, {0x97F3, 0x97F3}, {0x97F4, 0x97F4}, {0x97F5, 0x97F5}, {0x97F6, 0x97F6}, + {0x97F7, 0x97F7}, {0x97F8, 0x97F8}, {0x97F9, 0x97F9}, {0x97FA, 0x97FA}, {0x97FB, 0x97FB}, {0x97FC, 0x97FC}, {0x97FD, 0x97FD}, + {0x97FE, 0x97FE}, {0x97FF, 0x97FF}, {0x9800, 0x9800}, {0x9801, 0x9801}, {0x9802, 0x9802}, {0x9803, 0x9803}, {0x9804, 0x9804}, + {0x9805, 0x9805}, {0x9806, 0x9806}, {0x9807, 0x9807}, {0x9808, 0x9808}, {0x9809, 0x9809}, {0x980A, 0x980A}, {0x980B, 0x980B}, + {0x980C, 0x980C}, {0x980D, 0x980D}, {0x980E, 0x980E}, {0x980F, 0x980F}, {0x9810, 0x9810}, {0x9811, 0x9811}, {0x9812, 0x9812}, + {0x9813, 0x9813}, {0x9814, 0x9814}, {0x9815, 0x9815}, {0x9816, 0x9816}, {0x9817, 0x9817}, {0x9818, 0x9818}, {0x9819, 0x9819}, + {0x981A, 0x981A}, {0x981B, 0x981B}, {0x981C, 0x981C}, {0x981D, 0x981D}, {0x981E, 0x981E}, {0x981F, 0x981F}, {0x9820, 0x9820}, + {0x9821, 0x9821}, {0x9822, 0x9822}, {0x9823, 0x9823}, {0x9824, 0x9824}, {0x9825, 0x9825}, {0x9826, 0x9826}, {0x9827, 0x9827}, + {0x9828, 0x9828}, {0x9829, 0x9829}, {0x982A, 0x982A}, {0x982B, 0x982B}, {0x982C, 0x982C}, {0x982D, 0x982D}, {0x982E, 0x982E}, + {0x982F, 0x982F}, {0x9830, 0x9830}, {0x9831, 0x9831}, {0x9832, 0x9832}, {0x9833, 0x9833}, {0x9834, 0x9834}, {0x9835, 0x9835}, + {0x9836, 0x9836}, {0x9837, 0x9837}, {0x9838, 0x9838}, {0x9839, 0x9839}, {0x983A, 0x983A}, {0x983B, 0x983B}, {0x983C, 0x983C}, + {0x983D, 0x983D}, {0x983E, 0x983E}, {0x983F, 0x983F}, {0x9840, 0x9840}, {0x9841, 0x9841}, {0x9842, 0x9842}, {0x9843, 0x9843}, + {0x9844, 0x9844}, {0x9845, 0x9845}, {0x9846, 0x9846}, {0x9847, 0x9847}, {0x9848, 0x9848}, {0x9849, 0x9849}, {0x984A, 0x984A}, + {0x984B, 0x984B}, {0x984C, 0x984C}, {0x984D, 0x984D}, {0x984E, 0x984E}, {0x984F, 0x984F}, {0x9850, 0x9850}, {0x9851, 0x9851}, + {0x9852, 0x9852}, {0x9853, 0x9853}, {0x9854, 0x9854}, {0x9855, 0x9855}, {0x9856, 0x9856}, {0x9857, 0x9857}, {0x9858, 0x9858}, + {0x9859, 0x9859}, {0x985A, 0x985A}, {0x985B, 0x985B}, {0x985C, 0x985C}, {0x985D, 0x985D}, {0x985E, 0x985E}, {0x985F, 0x985F}, + {0x9860, 0x9860}, {0x9861, 0x9861}, {0x9862, 0x9862}, {0x9863, 0x9863}, {0x9864, 0x9864}, {0x9865, 0x9865}, {0x9866, 0x9866}, + {0x9867, 0x9867}, {0x9868, 0x9868}, {0x9869, 0x9869}, {0x986A, 0x986A}, {0x986B, 0x986B}, {0x986C, 0x986C}, {0x986D, 0x986D}, + {0x986E, 0x986E}, {0x986F, 0x986F}, {0x9870, 0x9870}, {0x9871, 0x9871}, {0x9872, 0x9872}, {0x9873, 0x9873}, {0x9874, 0x9874}, + {0x9875, 0x9875}, {0x9876, 0x9876}, {0x9877, 0x9877}, {0x9878, 0x9878}, {0x9879, 0x9879}, {0x987A, 0x987A}, {0x987B, 0x987B}, + {0x987C, 0x987C}, {0x987D, 0x987D}, {0x987E, 0x987E}, {0x987F, 0x987F}, {0x9880, 0x9880}, {0x9881, 0x9881}, {0x9882, 0x9882}, + {0x9883, 0x9883}, {0x9884, 0x9884}, {0x9885, 0x9885}, {0x9886, 0x9886}, {0x9887, 0x9887}, {0x9888, 0x9888}, {0x9889, 0x9889}, + {0x988A, 0x988A}, {0x988B, 0x988B}, {0x988C, 0x988C}, {0x988D, 0x988D}, {0x988E, 0x988E}, {0x988F, 0x988F}, {0x9890, 0x9890}, + {0x9891, 0x9891}, {0x9892, 0x9892}, {0x9893, 0x9893}, {0x9894, 0x9894}, {0x9895, 0x9895}, {0x9896, 0x9896}, {0x9897, 0x9897}, + {0x9898, 0x9898}, {0x9899, 0x9899}, {0x989A, 0x989A}, {0x989B, 0x989B}, {0x989C, 0x989C}, {0x989D, 0x989D}, {0x989E, 0x989E}, + {0x989F, 0x989F}, {0x98A0, 0x98A0}, {0x98A1, 0x98A1}, {0x98A2, 0x98A2}, {0x98A3, 0x98A3}, {0x98A4, 0x98A4}, {0x98A5, 0x98A5}, + {0x98A6, 0x98A6}, {0x98A7, 0x98A7}, {0x98A8, 0x98A8}, {0x98A9, 0x98A9}, {0x98AA, 0x98AA}, {0x98AB, 0x98AB}, {0x98AC, 0x98AC}, + {0x98AD, 0x98AD}, {0x98AE, 0x98AE}, {0x98AF, 0x98AF}, {0x98B0, 0x98B0}, {0x98B1, 0x98B1}, {0x98B2, 0x98B2}, {0x98B3, 0x98B3}, + {0x98B4, 0x98B4}, {0x98B5, 0x98B5}, {0x98B6, 0x98B6}, {0x98B7, 0x98B7}, {0x98B8, 0x98B8}, {0x98B9, 0x98B9}, {0x98BA, 0x98BA}, + {0x98BB, 0x98BB}, {0x98BC, 0x98BC}, {0x98BD, 0x98BD}, {0x98BE, 0x98BE}, {0x98BF, 0x98BF}, {0x98C0, 0x98C0}, {0x98C1, 0x98C1}, + {0x98C2, 0x98C2}, {0x98C3, 0x98C3}, {0x98C4, 0x98C4}, {0x98C5, 0x98C5}, {0x98C6, 0x98C6}, {0x98C7, 0x98C7}, {0x98C8, 0x98C8}, + {0x98C9, 0x98C9}, {0x98CA, 0x98CA}, {0x98CB, 0x98CB}, {0x98CC, 0x98CC}, {0x98CD, 0x98CD}, {0x98CE, 0x98CE}, {0x98CF, 0x98CF}, + {0x98D0, 0x98D0}, {0x98D1, 0x98D1}, {0x98D2, 0x98D2}, {0x98D3, 0x98D3}, {0x98D4, 0x98D4}, {0x98D5, 0x98D5}, {0x98D6, 0x98D6}, + {0x98D7, 0x98D7}, {0x98D8, 0x98D8}, {0x98D9, 0x98D9}, {0x98DA, 0x98DA}, {0x98DB, 0x98DB}, {0x98DC, 0x98DC}, {0x98DD, 0x98DD}, + {0x98DE, 0x98DE}, {0x98DF, 0x98DF}, {0x98E0, 0x98E0}, {0x98E1, 0x98E1}, {0x98E2, 0x98E2}, {0x98E3, 0x98E3}, {0x98E4, 0x98E4}, + {0x98E5, 0x98E5}, {0x98E6, 0x98E6}, {0x98E7, 0x98E7}, {0x98E8, 0x98E8}, {0x98E9, 0x98E9}, {0x98EA, 0x98EA}, {0x98EB, 0x98EB}, + {0x98EC, 0x98EC}, {0x98ED, 0x98ED}, {0x98EE, 0x98EE}, {0x98EF, 0x98EF}, {0x98F0, 0x98F0}, {0x98F1, 0x98F1}, {0x98F2, 0x98F2}, + {0x98F3, 0x98F3}, {0x98F4, 0x98F4}, {0x98F5, 0x98F5}, {0x98F6, 0x98F6}, {0x98F7, 0x98F7}, {0x98F8, 0x98F8}, {0x98F9, 0x98F9}, + {0x98FA, 0x98FA}, {0x98FB, 0x98FB}, {0x98FC, 0x98FC}, {0x98FD, 0x98FD}, {0x98FE, 0x98FE}, {0x98FF, 0x98FF}, {0x9900, 0x9900}, + {0x9901, 0x9901}, {0x9902, 0x9902}, {0x9903, 0x9903}, {0x9904, 0x9904}, {0x9905, 0x9905}, {0x9906, 0x9906}, {0x9907, 0x9907}, + {0x9908, 0x9908}, {0x9909, 0x9909}, {0x990A, 0x990A}, {0x990B, 0x990B}, {0x990C, 0x990C}, {0x990D, 0x990D}, {0x990E, 0x990E}, + {0x990F, 0x990F}, {0x9910, 0x9910}, {0x9911, 0x9911}, {0x9912, 0x9912}, {0x9913, 0x9913}, {0x9914, 0x9914}, {0x9915, 0x9915}, + {0x9916, 0x9916}, {0x9917, 0x9917}, {0x9918, 0x9918}, {0x9919, 0x9919}, {0x991A, 0x991A}, {0x991B, 0x991B}, {0x991C, 0x991C}, + {0x991D, 0x991D}, {0x991E, 0x991E}, {0x991F, 0x991F}, {0x9920, 0x9920}, {0x9921, 0x9921}, {0x9922, 0x9922}, {0x9923, 0x9923}, + {0x9924, 0x9924}, {0x9925, 0x9925}, {0x9926, 0x9926}, {0x9927, 0x9927}, {0x9928, 0x9928}, {0x9929, 0x9929}, {0x992A, 0x992A}, + {0x992B, 0x992B}, {0x992C, 0x992C}, {0x992D, 0x992D}, {0x992E, 0x992E}, {0x992F, 0x992F}, {0x9930, 0x9930}, {0x9931, 0x9931}, + {0x9932, 0x9932}, {0x9933, 0x9933}, {0x9934, 0x9934}, {0x9935, 0x9935}, {0x9936, 0x9936}, {0x9937, 0x9937}, {0x9938, 0x9938}, + {0x9939, 0x9939}, {0x993A, 0x993A}, {0x993B, 0x993B}, {0x993C, 0x993C}, {0x993D, 0x993D}, {0x993E, 0x993E}, {0x993F, 0x993F}, + {0x9940, 0x9940}, {0x9941, 0x9941}, {0x9942, 0x9942}, {0x9943, 0x9943}, {0x9944, 0x9944}, {0x9945, 0x9945}, {0x9946, 0x9946}, + {0x9947, 0x9947}, {0x9948, 0x9948}, {0x9949, 0x9949}, {0x994A, 0x994A}, {0x994B, 0x994B}, {0x994C, 0x994C}, {0x994D, 0x994D}, + {0x994E, 0x994E}, {0x994F, 0x994F}, {0x9950, 0x9950}, {0x9951, 0x9951}, {0x9952, 0x9952}, {0x9953, 0x9953}, {0x9954, 0x9954}, + {0x9955, 0x9955}, {0x9956, 0x9956}, {0x9957, 0x9957}, {0x9958, 0x9958}, {0x9959, 0x9959}, {0x995A, 0x995A}, {0x995B, 0x995B}, + {0x995C, 0x995C}, {0x995D, 0x995D}, {0x995E, 0x995E}, {0x995F, 0x995F}, {0x9960, 0x9960}, {0x9961, 0x9961}, {0x9962, 0x9962}, + {0x9963, 0x9963}, {0x9964, 0x9964}, {0x9965, 0x9965}, {0x9966, 0x9966}, {0x9967, 0x9967}, {0x9968, 0x9968}, {0x9969, 0x9969}, + {0x996A, 0x996A}, {0x996B, 0x996B}, {0x996C, 0x996C}, {0x996D, 0x996D}, {0x996E, 0x996E}, {0x996F, 0x996F}, {0x9970, 0x9970}, + {0x9971, 0x9971}, {0x9972, 0x9972}, {0x9973, 0x9973}, {0x9974, 0x9974}, {0x9975, 0x9975}, {0x9976, 0x9976}, {0x9977, 0x9977}, + {0x9978, 0x9978}, {0x9979, 0x9979}, {0x997A, 0x997A}, {0x997B, 0x997B}, {0x997C, 0x997C}, {0x997D, 0x997D}, {0x997E, 0x997E}, + {0x997F, 0x997F}, {0x9980, 0x9980}, {0x9981, 0x9981}, {0x9982, 0x9982}, {0x9983, 0x9983}, {0x9984, 0x9984}, {0x9985, 0x9985}, + {0x9986, 0x9986}, {0x9987, 0x9987}, {0x9988, 0x9988}, {0x9989, 0x9989}, {0x998A, 0x998A}, {0x998B, 0x998B}, {0x998C, 0x998C}, + {0x998D, 0x998D}, {0x998E, 0x998E}, {0x998F, 0x998F}, {0x9990, 0x9990}, {0x9991, 0x9991}, {0x9992, 0x9992}, {0x9993, 0x9993}, + {0x9994, 0x9994}, {0x9995, 0x9995}, {0x9996, 0x9996}, {0x9997, 0x9997}, {0x9998, 0x9998}, {0x9999, 0x9999}, {0x999A, 0x999A}, + {0x999B, 0x999B}, {0x999C, 0x999C}, {0x999D, 0x999D}, {0x999E, 0x999E}, {0x999F, 0x999F}, {0x99A0, 0x99A0}, {0x99A1, 0x99A1}, + {0x99A2, 0x99A2}, {0x99A3, 0x99A3}, {0x99A4, 0x99A4}, {0x99A5, 0x99A5}, {0x99A6, 0x99A6}, {0x99A7, 0x99A7}, {0x99A8, 0x99A8}, + {0x99A9, 0x99A9}, {0x99AA, 0x99AA}, {0x99AB, 0x99AB}, {0x99AC, 0x99AC}, {0x99AD, 0x99AD}, {0x99AE, 0x99AE}, {0x99AF, 0x99AF}, + {0x99B0, 0x99B0}, {0x99B1, 0x99B1}, {0x99B2, 0x99B2}, {0x99B3, 0x99B3}, {0x99B4, 0x99B4}, {0x99B5, 0x99B5}, {0x99B6, 0x99B6}, + {0x99B7, 0x99B7}, {0x99B8, 0x99B8}, {0x99B9, 0x99B9}, {0x99BA, 0x99BA}, {0x99BB, 0x99BB}, {0x99BC, 0x99BC}, {0x99BD, 0x99BD}, + {0x99BE, 0x99BE}, {0x99BF, 0x99BF}, {0x99C0, 0x99C0}, {0x99C1, 0x99C1}, {0x99C2, 0x99C2}, {0x99C3, 0x99C3}, {0x99C4, 0x99C4}, + {0x99C5, 0x99C5}, {0x99C6, 0x99C6}, {0x99C7, 0x99C7}, {0x99C8, 0x99C8}, {0x99C9, 0x99C9}, {0x99CA, 0x99CA}, {0x99CB, 0x99CB}, + {0x99CC, 0x99CC}, {0x99CD, 0x99CD}, {0x99CE, 0x99CE}, {0x99CF, 0x99CF}, {0x99D0, 0x99D0}, {0x99D1, 0x99D1}, {0x99D2, 0x99D2}, + {0x99D3, 0x99D3}, {0x99D4, 0x99D4}, {0x99D5, 0x99D5}, {0x99D6, 0x99D6}, {0x99D7, 0x99D7}, {0x99D8, 0x99D8}, {0x99D9, 0x99D9}, + {0x99DA, 0x99DA}, {0x99DB, 0x99DB}, {0x99DC, 0x99DC}, {0x99DD, 0x99DD}, {0x99DE, 0x99DE}, {0x99DF, 0x99DF}, {0x99E0, 0x99E0}, + {0x99E1, 0x99E1}, {0x99E2, 0x99E2}, {0x99E3, 0x99E3}, {0x99E4, 0x99E4}, {0x99E5, 0x99E5}, {0x99E6, 0x99E6}, {0x99E7, 0x99E7}, + {0x99E8, 0x99E8}, {0x99E9, 0x99E9}, {0x99EA, 0x99EA}, {0x99EB, 0x99EB}, {0x99EC, 0x99EC}, {0x99ED, 0x99ED}, {0x99EE, 0x99EE}, + {0x99EF, 0x99EF}, {0x99F0, 0x99F0}, {0x99F1, 0x99F1}, {0x99F2, 0x99F2}, {0x99F3, 0x99F3}, {0x99F4, 0x99F4}, {0x99F5, 0x99F5}, + {0x99F6, 0x99F6}, {0x99F7, 0x99F7}, {0x99F8, 0x99F8}, {0x99F9, 0x99F9}, {0x99FA, 0x99FA}, {0x99FB, 0x99FB}, {0x99FC, 0x99FC}, + {0x99FD, 0x99FD}, {0x99FE, 0x99FE}, {0x99FF, 0x99FF}, {0x9A00, 0x9A00}, {0x9A01, 0x9A01}, {0x9A02, 0x9A02}, {0x9A03, 0x9A03}, + {0x9A04, 0x9A04}, {0x9A05, 0x9A05}, {0x9A06, 0x9A06}, {0x9A07, 0x9A07}, {0x9A08, 0x9A08}, {0x9A09, 0x9A09}, {0x9A0A, 0x9A0A}, + {0x9A0B, 0x9A0B}, {0x9A0C, 0x9A0C}, {0x9A0D, 0x9A0D}, {0x9A0E, 0x9A0E}, {0x9A0F, 0x9A0F}, {0x9A10, 0x9A10}, {0x9A11, 0x9A11}, + {0x9A12, 0x9A12}, {0x9A13, 0x9A13}, {0x9A14, 0x9A14}, {0x9A15, 0x9A15}, {0x9A16, 0x9A16}, {0x9A17, 0x9A17}, {0x9A18, 0x9A18}, + {0x9A19, 0x9A19}, {0x9A1A, 0x9A1A}, {0x9A1B, 0x9A1B}, {0x9A1C, 0x9A1C}, {0x9A1D, 0x9A1D}, {0x9A1E, 0x9A1E}, {0x9A1F, 0x9A1F}, + {0x9A20, 0x9A20}, {0x9A21, 0x9A21}, {0x9A22, 0x9A22}, {0x9A23, 0x9A23}, {0x9A24, 0x9A24}, {0x9A25, 0x9A25}, {0x9A26, 0x9A26}, + {0x9A27, 0x9A27}, {0x9A28, 0x9A28}, {0x9A29, 0x9A29}, {0x9A2A, 0x9A2A}, {0x9A2B, 0x9A2B}, {0x9A2C, 0x9A2C}, {0x9A2D, 0x9A2D}, + {0x9A2E, 0x9A2E}, {0x9A2F, 0x9A2F}, {0x9A30, 0x9A30}, {0x9A31, 0x9A31}, {0x9A32, 0x9A32}, {0x9A33, 0x9A33}, {0x9A34, 0x9A34}, + {0x9A35, 0x9A35}, {0x9A36, 0x9A36}, {0x9A37, 0x9A37}, {0x9A38, 0x9A38}, {0x9A39, 0x9A39}, {0x9A3A, 0x9A3A}, {0x9A3B, 0x9A3B}, + {0x9A3C, 0x9A3C}, {0x9A3D, 0x9A3D}, {0x9A3E, 0x9A3E}, {0x9A3F, 0x9A3F}, {0x9A40, 0x9A40}, {0x9A41, 0x9A41}, {0x9A42, 0x9A42}, + {0x9A43, 0x9A43}, {0x9A44, 0x9A44}, {0x9A45, 0x9A45}, {0x9A46, 0x9A46}, {0x9A47, 0x9A47}, {0x9A48, 0x9A48}, {0x9A49, 0x9A49}, + {0x9A4A, 0x9A4A}, {0x9A4B, 0x9A4B}, {0x9A4C, 0x9A4C}, {0x9A4D, 0x9A4D}, {0x9A4E, 0x9A4E}, {0x9A4F, 0x9A4F}, {0x9A50, 0x9A50}, + {0x9A51, 0x9A51}, {0x9A52, 0x9A52}, {0x9A53, 0x9A53}, {0x9A54, 0x9A54}, {0x9A55, 0x9A55}, {0x9A56, 0x9A56}, {0x9A57, 0x9A57}, + {0x9A58, 0x9A58}, {0x9A59, 0x9A59}, {0x9A5A, 0x9A5A}, {0x9A5B, 0x9A5B}, {0x9A5C, 0x9A5C}, {0x9A5D, 0x9A5D}, {0x9A5E, 0x9A5E}, + {0x9A5F, 0x9A5F}, {0x9A60, 0x9A60}, {0x9A61, 0x9A61}, {0x9A62, 0x9A62}, {0x9A63, 0x9A63}, {0x9A64, 0x9A64}, {0x9A65, 0x9A65}, + {0x9A66, 0x9A66}, {0x9A67, 0x9A67}, {0x9A68, 0x9A68}, {0x9A69, 0x9A69}, {0x9A6A, 0x9A6A}, {0x9A6B, 0x9A6B}, {0x9A6C, 0x9A6C}, + {0x9A6D, 0x9A6D}, {0x9A6E, 0x9A6E}, {0x9A6F, 0x9A6F}, {0x9A70, 0x9A70}, {0x9A71, 0x9A71}, {0x9A72, 0x9A72}, {0x9A73, 0x9A73}, + {0x9A74, 0x9A74}, {0x9A75, 0x9A75}, {0x9A76, 0x9A76}, {0x9A77, 0x9A77}, {0x9A78, 0x9A78}, {0x9A79, 0x9A79}, {0x9A7A, 0x9A7A}, + {0x9A7B, 0x9A7B}, {0x9A7C, 0x9A7C}, {0x9A7D, 0x9A7D}, {0x9A7E, 0x9A7E}, {0x9A7F, 0x9A7F}, {0x9A80, 0x9A80}, {0x9A81, 0x9A81}, + {0x9A82, 0x9A82}, {0x9A83, 0x9A83}, {0x9A84, 0x9A84}, {0x9A85, 0x9A85}, {0x9A86, 0x9A86}, {0x9A87, 0x9A87}, {0x9A88, 0x9A88}, + {0x9A89, 0x9A89}, {0x9A8A, 0x9A8A}, {0x9A8B, 0x9A8B}, {0x9A8C, 0x9A8C}, {0x9A8D, 0x9A8D}, {0x9A8E, 0x9A8E}, {0x9A8F, 0x9A8F}, + {0x9A90, 0x9A90}, {0x9A91, 0x9A91}, {0x9A92, 0x9A92}, {0x9A93, 0x9A93}, {0x9A94, 0x9A94}, {0x9A95, 0x9A95}, {0x9A96, 0x9A96}, + {0x9A97, 0x9A97}, {0x9A98, 0x9A98}, {0x9A99, 0x9A99}, {0x9A9A, 0x9A9A}, {0x9A9B, 0x9A9B}, {0x9A9C, 0x9A9C}, {0x9A9D, 0x9A9D}, + {0x9A9E, 0x9A9E}, {0x9A9F, 0x9A9F}, {0x9AA0, 0x9AA0}, {0x9AA1, 0x9AA1}, {0x9AA2, 0x9AA2}, {0x9AA3, 0x9AA3}, {0x9AA4, 0x9AA4}, + {0x9AA5, 0x9AA5}, {0x9AA6, 0x9AA6}, {0x9AA7, 0x9AA7}, {0x9AA8, 0x9AA8}, {0x9AA9, 0x9AA9}, {0x9AAA, 0x9AAA}, {0x9AAB, 0x9AAB}, + {0x9AAC, 0x9AAC}, {0x9AAD, 0x9AAD}, {0x9AAE, 0x9AAE}, {0x9AAF, 0x9AAF}, {0x9AB0, 0x9AB0}, {0x9AB1, 0x9AB1}, {0x9AB2, 0x9AB2}, + {0x9AB3, 0x9AB3}, {0x9AB4, 0x9AB4}, {0x9AB5, 0x9AB5}, {0x9AB6, 0x9AB6}, {0x9AB7, 0x9AB7}, {0x9AB8, 0x9AB8}, {0x9AB9, 0x9AB9}, + {0x9ABA, 0x9ABA}, {0x9ABB, 0x9ABB}, {0x9ABC, 0x9ABC}, {0x9ABD, 0x9ABD}, {0x9ABE, 0x9ABE}, {0x9ABF, 0x9ABF}, {0x9AC0, 0x9AC0}, + {0x9AC1, 0x9AC1}, {0x9AC2, 0x9AC2}, {0x9AC3, 0x9AC3}, {0x9AC4, 0x9AC4}, {0x9AC5, 0x9AC5}, {0x9AC6, 0x9AC6}, {0x9AC7, 0x9AC7}, + {0x9AC8, 0x9AC8}, {0x9AC9, 0x9AC9}, {0x9ACA, 0x9ACA}, {0x9ACB, 0x9ACB}, {0x9ACC, 0x9ACC}, {0x9ACD, 0x9ACD}, {0x9ACE, 0x9ACE}, + {0x9ACF, 0x9ACF}, {0x9AD0, 0x9AD0}, {0x9AD1, 0x9AD1}, {0x9AD2, 0x9AD2}, {0x9AD3, 0x9AD3}, {0x9AD4, 0x9AD4}, {0x9AD5, 0x9AD5}, + {0x9AD6, 0x9AD6}, {0x9AD7, 0x9AD7}, {0x9AD8, 0x9AD8}, {0x9AD9, 0x9AD9}, {0x9ADA, 0x9ADA}, {0x9ADB, 0x9ADB}, {0x9ADC, 0x9ADC}, + {0x9ADD, 0x9ADD}, {0x9ADE, 0x9ADE}, {0x9ADF, 0x9ADF}, {0x9AE0, 0x9AE0}, {0x9AE1, 0x9AE1}, {0x9AE2, 0x9AE2}, {0x9AE3, 0x9AE3}, + {0x9AE4, 0x9AE4}, {0x9AE5, 0x9AE5}, {0x9AE6, 0x9AE6}, {0x9AE7, 0x9AE7}, {0x9AE8, 0x9AE8}, {0x9AE9, 0x9AE9}, {0x9AEA, 0x9AEA}, + {0x9AEB, 0x9AEB}, {0x9AEC, 0x9AEC}, {0x9AED, 0x9AED}, {0x9AEE, 0x9AEE}, {0x9AEF, 0x9AEF}, {0x9AF0, 0x9AF0}, {0x9AF1, 0x9AF1}, + {0x9AF2, 0x9AF2}, {0x9AF3, 0x9AF3}, {0x9AF4, 0x9AF4}, {0x9AF5, 0x9AF5}, {0x9AF6, 0x9AF6}, {0x9AF7, 0x9AF7}, {0x9AF8, 0x9AF8}, + {0x9AF9, 0x9AF9}, {0x9AFA, 0x9AFA}, {0x9AFB, 0x9AFB}, {0x9AFC, 0x9AFC}, {0x9AFD, 0x9AFD}, {0x9AFE, 0x9AFE}, {0x9AFF, 0x9AFF}, + {0x9B00, 0x9B00}, {0x9B01, 0x9B01}, {0x9B02, 0x9B02}, {0x9B03, 0x9B03}, {0x9B04, 0x9B04}, {0x9B05, 0x9B05}, {0x9B06, 0x9B06}, + {0x9B07, 0x9B07}, {0x9B08, 0x9B08}, {0x9B09, 0x9B09}, {0x9B0A, 0x9B0A}, {0x9B0B, 0x9B0B}, {0x9B0C, 0x9B0C}, {0x9B0D, 0x9B0D}, + {0x9B0E, 0x9B0E}, {0x9B0F, 0x9B0F}, {0x9B10, 0x9B10}, {0x9B11, 0x9B11}, {0x9B12, 0x9B12}, {0x9B13, 0x9B13}, {0x9B14, 0x9B14}, + {0x9B15, 0x9B15}, {0x9B16, 0x9B16}, {0x9B17, 0x9B17}, {0x9B18, 0x9B18}, {0x9B19, 0x9B19}, {0x9B1A, 0x9B1A}, {0x9B1B, 0x9B1B}, + {0x9B1C, 0x9B1C}, {0x9B1D, 0x9B1D}, {0x9B1E, 0x9B1E}, {0x9B1F, 0x9B1F}, {0x9B20, 0x9B20}, {0x9B21, 0x9B21}, {0x9B22, 0x9B22}, + {0x9B23, 0x9B23}, {0x9B24, 0x9B24}, {0x9B25, 0x9B25}, {0x9B26, 0x9B26}, {0x9B27, 0x9B27}, {0x9B28, 0x9B28}, {0x9B29, 0x9B29}, + {0x9B2A, 0x9B2A}, {0x9B2B, 0x9B2B}, {0x9B2C, 0x9B2C}, {0x9B2D, 0x9B2D}, {0x9B2E, 0x9B2E}, {0x9B2F, 0x9B2F}, {0x9B30, 0x9B30}, + {0x9B31, 0x9B31}, {0x9B32, 0x9B32}, {0x9B33, 0x9B33}, {0x9B34, 0x9B34}, {0x9B35, 0x9B35}, {0x9B36, 0x9B36}, {0x9B37, 0x9B37}, + {0x9B38, 0x9B38}, {0x9B39, 0x9B39}, {0x9B3A, 0x9B3A}, {0x9B3B, 0x9B3B}, {0x9B3C, 0x9B3C}, {0x9B3D, 0x9B3D}, {0x9B3E, 0x9B3E}, + {0x9B3F, 0x9B3F}, {0x9B40, 0x9B40}, {0x9B41, 0x9B41}, {0x9B42, 0x9B42}, {0x9B43, 0x9B43}, {0x9B44, 0x9B44}, {0x9B45, 0x9B45}, + {0x9B46, 0x9B46}, {0x9B47, 0x9B47}, {0x9B48, 0x9B48}, {0x9B49, 0x9B49}, {0x9B4A, 0x9B4A}, {0x9B4B, 0x9B4B}, {0x9B4C, 0x9B4C}, + {0x9B4D, 0x9B4D}, {0x9B4E, 0x9B4E}, {0x9B4F, 0x9B4F}, {0x9B50, 0x9B50}, {0x9B51, 0x9B51}, {0x9B52, 0x9B52}, {0x9B53, 0x9B53}, + {0x9B54, 0x9B54}, {0x9B55, 0x9B55}, {0x9B56, 0x9B56}, {0x9B57, 0x9B57}, {0x9B58, 0x9B58}, {0x9B59, 0x9B59}, {0x9B5A, 0x9B5A}, + {0x9B5B, 0x9B5B}, {0x9B5C, 0x9B5C}, {0x9B5D, 0x9B5D}, {0x9B5E, 0x9B5E}, {0x9B5F, 0x9B5F}, {0x9B60, 0x9B60}, {0x9B61, 0x9B61}, + {0x9B62, 0x9B62}, {0x9B63, 0x9B63}, {0x9B64, 0x9B64}, {0x9B65, 0x9B65}, {0x9B66, 0x9B66}, {0x9B67, 0x9B67}, {0x9B68, 0x9B68}, + {0x9B69, 0x9B69}, {0x9B6A, 0x9B6A}, {0x9B6B, 0x9B6B}, {0x9B6C, 0x9B6C}, {0x9B6D, 0x9B6D}, {0x9B6E, 0x9B6E}, {0x9B6F, 0x9B6F}, + {0x9B70, 0x9B70}, {0x9B71, 0x9B71}, {0x9B72, 0x9B72}, {0x9B73, 0x9B73}, {0x9B74, 0x9B74}, {0x9B75, 0x9B75}, {0x9B76, 0x9B76}, + {0x9B77, 0x9B77}, {0x9B78, 0x9B78}, {0x9B79, 0x9B79}, {0x9B7A, 0x9B7A}, {0x9B7B, 0x9B7B}, {0x9B7C, 0x9B7C}, {0x9B7D, 0x9B7D}, + {0x9B7E, 0x9B7E}, {0x9B7F, 0x9B7F}, {0x9B80, 0x9B80}, {0x9B81, 0x9B81}, {0x9B82, 0x9B82}, {0x9B83, 0x9B83}, {0x9B84, 0x9B84}, + {0x9B85, 0x9B85}, {0x9B86, 0x9B86}, {0x9B87, 0x9B87}, {0x9B88, 0x9B88}, {0x9B89, 0x9B89}, {0x9B8A, 0x9B8A}, {0x9B8B, 0x9B8B}, + {0x9B8C, 0x9B8C}, {0x9B8D, 0x9B8D}, {0x9B8E, 0x9B8E}, {0x9B8F, 0x9B8F}, {0x9B90, 0x9B90}, {0x9B91, 0x9B91}, {0x9B92, 0x9B92}, + {0x9B93, 0x9B93}, {0x9B94, 0x9B94}, {0x9B95, 0x9B95}, {0x9B96, 0x9B96}, {0x9B97, 0x9B97}, {0x9B98, 0x9B98}, {0x9B99, 0x9B99}, + {0x9B9A, 0x9B9A}, {0x9B9B, 0x9B9B}, {0x9B9C, 0x9B9C}, {0x9B9D, 0x9B9D}, {0x9B9E, 0x9B9E}, {0x9B9F, 0x9B9F}, {0x9BA0, 0x9BA0}, + {0x9BA1, 0x9BA1}, {0x9BA2, 0x9BA2}, {0x9BA3, 0x9BA3}, {0x9BA4, 0x9BA4}, {0x9BA5, 0x9BA5}, {0x9BA6, 0x9BA6}, {0x9BA7, 0x9BA7}, + {0x9BA8, 0x9BA8}, {0x9BA9, 0x9BA9}, {0x9BAA, 0x9BAA}, {0x9BAB, 0x9BAB}, {0x9BAC, 0x9BAC}, {0x9BAD, 0x9BAD}, {0x9BAE, 0x9BAE}, + {0x9BAF, 0x9BAF}, {0x9BB0, 0x9BB0}, {0x9BB1, 0x9BB1}, {0x9BB2, 0x9BB2}, {0x9BB3, 0x9BB3}, {0x9BB4, 0x9BB4}, {0x9BB5, 0x9BB5}, + {0x9BB6, 0x9BB6}, {0x9BB7, 0x9BB7}, {0x9BB8, 0x9BB8}, {0x9BB9, 0x9BB9}, {0x9BBA, 0x9BBA}, {0x9BBB, 0x9BBB}, {0x9BBC, 0x9BBC}, + {0x9BBD, 0x9BBD}, {0x9BBE, 0x9BBE}, {0x9BBF, 0x9BBF}, {0x9BC0, 0x9BC0}, {0x9BC1, 0x9BC1}, {0x9BC2, 0x9BC2}, {0x9BC3, 0x9BC3}, + {0x9BC4, 0x9BC4}, {0x9BC5, 0x9BC5}, {0x9BC6, 0x9BC6}, {0x9BC7, 0x9BC7}, {0x9BC8, 0x9BC8}, {0x9BC9, 0x9BC9}, {0x9BCA, 0x9BCA}, + {0x9BCB, 0x9BCB}, {0x9BCC, 0x9BCC}, {0x9BCD, 0x9BCD}, {0x9BCE, 0x9BCE}, {0x9BCF, 0x9BCF}, {0x9BD0, 0x9BD0}, {0x9BD1, 0x9BD1}, + {0x9BD2, 0x9BD2}, {0x9BD3, 0x9BD3}, {0x9BD4, 0x9BD4}, {0x9BD5, 0x9BD5}, {0x9BD6, 0x9BD6}, {0x9BD7, 0x9BD7}, {0x9BD8, 0x9BD8}, + {0x9BD9, 0x9BD9}, {0x9BDA, 0x9BDA}, {0x9BDB, 0x9BDB}, {0x9BDC, 0x9BDC}, {0x9BDD, 0x9BDD}, {0x9BDE, 0x9BDE}, {0x9BDF, 0x9BDF}, + {0x9BE0, 0x9BE0}, {0x9BE1, 0x9BE1}, {0x9BE2, 0x9BE2}, {0x9BE3, 0x9BE3}, {0x9BE4, 0x9BE4}, {0x9BE5, 0x9BE5}, {0x9BE6, 0x9BE6}, + {0x9BE7, 0x9BE7}, {0x9BE8, 0x9BE8}, {0x9BE9, 0x9BE9}, {0x9BEA, 0x9BEA}, {0x9BEB, 0x9BEB}, {0x9BEC, 0x9BEC}, {0x9BED, 0x9BED}, + {0x9BEE, 0x9BEE}, {0x9BEF, 0x9BEF}, {0x9BF0, 0x9BF0}, {0x9BF1, 0x9BF1}, {0x9BF2, 0x9BF2}, {0x9BF3, 0x9BF3}, {0x9BF4, 0x9BF4}, + {0x9BF5, 0x9BF5}, {0x9BF6, 0x9BF6}, {0x9BF7, 0x9BF7}, {0x9BF8, 0x9BF8}, {0x9BF9, 0x9BF9}, {0x9BFA, 0x9BFA}, {0x9BFB, 0x9BFB}, + {0x9BFC, 0x9BFC}, {0x9BFD, 0x9BFD}, {0x9BFE, 0x9BFE}, {0x9BFF, 0x9BFF}, {0x9C00, 0x9C00}, {0x9C01, 0x9C01}, {0x9C02, 0x9C02}, + {0x9C03, 0x9C03}, {0x9C04, 0x9C04}, {0x9C05, 0x9C05}, {0x9C06, 0x9C06}, {0x9C07, 0x9C07}, {0x9C08, 0x9C08}, {0x9C09, 0x9C09}, + {0x9C0A, 0x9C0A}, {0x9C0B, 0x9C0B}, {0x9C0C, 0x9C0C}, {0x9C0D, 0x9C0D}, {0x9C0E, 0x9C0E}, {0x9C0F, 0x9C0F}, {0x9C10, 0x9C10}, + {0x9C11, 0x9C11}, {0x9C12, 0x9C12}, {0x9C13, 0x9C13}, {0x9C14, 0x9C14}, {0x9C15, 0x9C15}, {0x9C16, 0x9C16}, {0x9C17, 0x9C17}, + {0x9C18, 0x9C18}, {0x9C19, 0x9C19}, {0x9C1A, 0x9C1A}, {0x9C1B, 0x9C1B}, {0x9C1C, 0x9C1C}, {0x9C1D, 0x9C1D}, {0x9C1E, 0x9C1E}, + {0x9C1F, 0x9C1F}, {0x9C20, 0x9C20}, {0x9C21, 0x9C21}, {0x9C22, 0x9C22}, {0x9C23, 0x9C23}, {0x9C24, 0x9C24}, {0x9C25, 0x9C25}, + {0x9C26, 0x9C26}, {0x9C27, 0x9C27}, {0x9C28, 0x9C28}, {0x9C29, 0x9C29}, {0x9C2A, 0x9C2A}, {0x9C2B, 0x9C2B}, {0x9C2C, 0x9C2C}, + {0x9C2D, 0x9C2D}, {0x9C2E, 0x9C2E}, {0x9C2F, 0x9C2F}, {0x9C30, 0x9C30}, {0x9C31, 0x9C31}, {0x9C32, 0x9C32}, {0x9C33, 0x9C33}, + {0x9C34, 0x9C34}, {0x9C35, 0x9C35}, {0x9C36, 0x9C36}, {0x9C37, 0x9C37}, {0x9C38, 0x9C38}, {0x9C39, 0x9C39}, {0x9C3A, 0x9C3A}, + {0x9C3B, 0x9C3B}, {0x9C3C, 0x9C3C}, {0x9C3D, 0x9C3D}, {0x9C3E, 0x9C3E}, {0x9C3F, 0x9C3F}, {0x9C40, 0x9C40}, {0x9C41, 0x9C41}, + {0x9C42, 0x9C42}, {0x9C43, 0x9C43}, {0x9C44, 0x9C44}, {0x9C45, 0x9C45}, {0x9C46, 0x9C46}, {0x9C47, 0x9C47}, {0x9C48, 0x9C48}, + {0x9C49, 0x9C49}, {0x9C4A, 0x9C4A}, {0x9C4B, 0x9C4B}, {0x9C4C, 0x9C4C}, {0x9C4D, 0x9C4D}, {0x9C4E, 0x9C4E}, {0x9C4F, 0x9C4F}, + {0x9C50, 0x9C50}, {0x9C51, 0x9C51}, {0x9C52, 0x9C52}, {0x9C53, 0x9C53}, {0x9C54, 0x9C54}, {0x9C55, 0x9C55}, {0x9C56, 0x9C56}, + {0x9C57, 0x9C57}, {0x9C58, 0x9C58}, {0x9C59, 0x9C59}, {0x9C5A, 0x9C5A}, {0x9C5B, 0x9C5B}, {0x9C5C, 0x9C5C}, {0x9C5D, 0x9C5D}, + {0x9C5E, 0x9C5E}, {0x9C5F, 0x9C5F}, {0x9C60, 0x9C60}, {0x9C61, 0x9C61}, {0x9C62, 0x9C62}, {0x9C63, 0x9C63}, {0x9C64, 0x9C64}, + {0x9C65, 0x9C65}, {0x9C66, 0x9C66}, {0x9C67, 0x9C67}, {0x9C68, 0x9C68}, {0x9C69, 0x9C69}, {0x9C6A, 0x9C6A}, {0x9C6B, 0x9C6B}, + {0x9C6C, 0x9C6C}, {0x9C6D, 0x9C6D}, {0x9C6E, 0x9C6E}, {0x9C6F, 0x9C6F}, {0x9C70, 0x9C70}, {0x9C71, 0x9C71}, {0x9C72, 0x9C72}, + {0x9C73, 0x9C73}, {0x9C74, 0x9C74}, {0x9C75, 0x9C75}, {0x9C76, 0x9C76}, {0x9C77, 0x9C77}, {0x9C78, 0x9C78}, {0x9C79, 0x9C79}, + {0x9C7A, 0x9C7A}, {0x9C7B, 0x9C7B}, {0x9C7C, 0x9C7C}, {0x9C7D, 0x9C7D}, {0x9C7E, 0x9C7E}, {0x9C7F, 0x9C7F}, {0x9C80, 0x9C80}, + {0x9C81, 0x9C81}, {0x9C82, 0x9C82}, {0x9C83, 0x9C83}, {0x9C84, 0x9C84}, {0x9C85, 0x9C85}, {0x9C86, 0x9C86}, {0x9C87, 0x9C87}, + {0x9C88, 0x9C88}, {0x9C89, 0x9C89}, {0x9C8A, 0x9C8A}, {0x9C8B, 0x9C8B}, {0x9C8C, 0x9C8C}, {0x9C8D, 0x9C8D}, {0x9C8E, 0x9C8E}, + {0x9C8F, 0x9C8F}, {0x9C90, 0x9C90}, {0x9C91, 0x9C91}, {0x9C92, 0x9C92}, {0x9C93, 0x9C93}, {0x9C94, 0x9C94}, {0x9C95, 0x9C95}, + {0x9C96, 0x9C96}, {0x9C97, 0x9C97}, {0x9C98, 0x9C98}, {0x9C99, 0x9C99}, {0x9C9A, 0x9C9A}, {0x9C9B, 0x9C9B}, {0x9C9C, 0x9C9C}, + {0x9C9D, 0x9C9D}, {0x9C9E, 0x9C9E}, {0x9C9F, 0x9C9F}, {0x9CA0, 0x9CA0}, {0x9CA1, 0x9CA1}, {0x9CA2, 0x9CA2}, {0x9CA3, 0x9CA3}, + {0x9CA4, 0x9CA4}, {0x9CA5, 0x9CA5}, {0x9CA6, 0x9CA6}, {0x9CA7, 0x9CA7}, {0x9CA8, 0x9CA8}, {0x9CA9, 0x9CA9}, {0x9CAA, 0x9CAA}, + {0x9CAB, 0x9CAB}, {0x9CAC, 0x9CAC}, {0x9CAD, 0x9CAD}, {0x9CAE, 0x9CAE}, {0x9CAF, 0x9CAF}, {0x9CB0, 0x9CB0}, {0x9CB1, 0x9CB1}, + {0x9CB2, 0x9CB2}, {0x9CB3, 0x9CB3}, {0x9CB4, 0x9CB4}, {0x9CB5, 0x9CB5}, {0x9CB6, 0x9CB6}, {0x9CB7, 0x9CB7}, {0x9CB8, 0x9CB8}, + {0x9CB9, 0x9CB9}, {0x9CBA, 0x9CBA}, {0x9CBB, 0x9CBB}, {0x9CBC, 0x9CBC}, {0x9CBD, 0x9CBD}, {0x9CBE, 0x9CBE}, {0x9CBF, 0x9CBF}, + {0x9CC0, 0x9CC0}, {0x9CC1, 0x9CC1}, {0x9CC2, 0x9CC2}, {0x9CC3, 0x9CC3}, {0x9CC4, 0x9CC4}, {0x9CC5, 0x9CC5}, {0x9CC6, 0x9CC6}, + {0x9CC7, 0x9CC7}, {0x9CC8, 0x9CC8}, {0x9CC9, 0x9CC9}, {0x9CCA, 0x9CCA}, {0x9CCB, 0x9CCB}, {0x9CCC, 0x9CCC}, {0x9CCD, 0x9CCD}, + {0x9CCE, 0x9CCE}, {0x9CCF, 0x9CCF}, {0x9CD0, 0x9CD0}, {0x9CD1, 0x9CD1}, {0x9CD2, 0x9CD2}, {0x9CD3, 0x9CD3}, {0x9CD4, 0x9CD4}, + {0x9CD5, 0x9CD5}, {0x9CD6, 0x9CD6}, {0x9CD7, 0x9CD7}, {0x9CD8, 0x9CD8}, {0x9CD9, 0x9CD9}, {0x9CDA, 0x9CDA}, {0x9CDB, 0x9CDB}, + {0x9CDC, 0x9CDC}, {0x9CDD, 0x9CDD}, {0x9CDE, 0x9CDE}, {0x9CDF, 0x9CDF}, {0x9CE0, 0x9CE0}, {0x9CE1, 0x9CE1}, {0x9CE2, 0x9CE2}, + {0x9CE3, 0x9CE3}, {0x9CE4, 0x9CE4}, {0x9CE5, 0x9CE5}, {0x9CE6, 0x9CE6}, {0x9CE7, 0x9CE7}, {0x9CE8, 0x9CE8}, {0x9CE9, 0x9CE9}, + {0x9CEA, 0x9CEA}, {0x9CEB, 0x9CEB}, {0x9CEC, 0x9CEC}, {0x9CED, 0x9CED}, {0x9CEE, 0x9CEE}, {0x9CEF, 0x9CEF}, {0x9CF0, 0x9CF0}, + {0x9CF1, 0x9CF1}, {0x9CF2, 0x9CF2}, {0x9CF3, 0x9CF3}, {0x9CF4, 0x9CF4}, {0x9CF5, 0x9CF5}, {0x9CF6, 0x9CF6}, {0x9CF7, 0x9CF7}, + {0x9CF8, 0x9CF8}, {0x9CF9, 0x9CF9}, {0x9CFA, 0x9CFA}, {0x9CFB, 0x9CFB}, {0x9CFC, 0x9CFC}, {0x9CFD, 0x9CFD}, {0x9CFE, 0x9CFE}, + {0x9CFF, 0x9CFF}, {0x9D00, 0x9D00}, {0x9D01, 0x9D01}, {0x9D02, 0x9D02}, {0x9D03, 0x9D03}, {0x9D04, 0x9D04}, {0x9D05, 0x9D05}, + {0x9D06, 0x9D06}, {0x9D07, 0x9D07}, {0x9D08, 0x9D08}, {0x9D09, 0x9D09}, {0x9D0A, 0x9D0A}, {0x9D0B, 0x9D0B}, {0x9D0C, 0x9D0C}, + {0x9D0D, 0x9D0D}, {0x9D0E, 0x9D0E}, {0x9D0F, 0x9D0F}, {0x9D10, 0x9D10}, {0x9D11, 0x9D11}, {0x9D12, 0x9D12}, {0x9D13, 0x9D13}, + {0x9D14, 0x9D14}, {0x9D15, 0x9D15}, {0x9D16, 0x9D16}, {0x9D17, 0x9D17}, {0x9D18, 0x9D18}, {0x9D19, 0x9D19}, {0x9D1A, 0x9D1A}, + {0x9D1B, 0x9D1B}, {0x9D1C, 0x9D1C}, {0x9D1D, 0x9D1D}, {0x9D1E, 0x9D1E}, {0x9D1F, 0x9D1F}, {0x9D20, 0x9D20}, {0x9D21, 0x9D21}, + {0x9D22, 0x9D22}, {0x9D23, 0x9D23}, {0x9D24, 0x9D24}, {0x9D25, 0x9D25}, {0x9D26, 0x9D26}, {0x9D27, 0x9D27}, {0x9D28, 0x9D28}, + {0x9D29, 0x9D29}, {0x9D2A, 0x9D2A}, {0x9D2B, 0x9D2B}, {0x9D2C, 0x9D2C}, {0x9D2D, 0x9D2D}, {0x9D2E, 0x9D2E}, {0x9D2F, 0x9D2F}, + {0x9D30, 0x9D30}, {0x9D31, 0x9D31}, {0x9D32, 0x9D32}, {0x9D33, 0x9D33}, {0x9D34, 0x9D34}, {0x9D35, 0x9D35}, {0x9D36, 0x9D36}, + {0x9D37, 0x9D37}, {0x9D38, 0x9D38}, {0x9D39, 0x9D39}, {0x9D3A, 0x9D3A}, {0x9D3B, 0x9D3B}, {0x9D3C, 0x9D3C}, {0x9D3D, 0x9D3D}, + {0x9D3E, 0x9D3E}, {0x9D3F, 0x9D3F}, {0x9D40, 0x9D40}, {0x9D41, 0x9D41}, {0x9D42, 0x9D42}, {0x9D43, 0x9D43}, {0x9D44, 0x9D44}, + {0x9D45, 0x9D45}, {0x9D46, 0x9D46}, {0x9D47, 0x9D47}, {0x9D48, 0x9D48}, {0x9D49, 0x9D49}, {0x9D4A, 0x9D4A}, {0x9D4B, 0x9D4B}, + {0x9D4C, 0x9D4C}, {0x9D4D, 0x9D4D}, {0x9D4E, 0x9D4E}, {0x9D4F, 0x9D4F}, {0x9D50, 0x9D50}, {0x9D51, 0x9D51}, {0x9D52, 0x9D52}, + {0x9D53, 0x9D53}, {0x9D54, 0x9D54}, {0x9D55, 0x9D55}, {0x9D56, 0x9D56}, {0x9D57, 0x9D57}, {0x9D58, 0x9D58}, {0x9D59, 0x9D59}, + {0x9D5A, 0x9D5A}, {0x9D5B, 0x9D5B}, {0x9D5C, 0x9D5C}, {0x9D5D, 0x9D5D}, {0x9D5E, 0x9D5E}, {0x9D5F, 0x9D5F}, {0x9D60, 0x9D60}, + {0x9D61, 0x9D61}, {0x9D62, 0x9D62}, {0x9D63, 0x9D63}, {0x9D64, 0x9D64}, {0x9D65, 0x9D65}, {0x9D66, 0x9D66}, {0x9D67, 0x9D67}, + {0x9D68, 0x9D68}, {0x9D69, 0x9D69}, {0x9D6A, 0x9D6A}, {0x9D6B, 0x9D6B}, {0x9D6C, 0x9D6C}, {0x9D6D, 0x9D6D}, {0x9D6E, 0x9D6E}, + {0x9D6F, 0x9D6F}, {0x9D70, 0x9D70}, {0x9D71, 0x9D71}, {0x9D72, 0x9D72}, {0x9D73, 0x9D73}, {0x9D74, 0x9D74}, {0x9D75, 0x9D75}, + {0x9D76, 0x9D76}, {0x9D77, 0x9D77}, {0x9D78, 0x9D78}, {0x9D79, 0x9D79}, {0x9D7A, 0x9D7A}, {0x9D7B, 0x9D7B}, {0x9D7C, 0x9D7C}, + {0x9D7D, 0x9D7D}, {0x9D7E, 0x9D7E}, {0x9D7F, 0x9D7F}, {0x9D80, 0x9D80}, {0x9D81, 0x9D81}, {0x9D82, 0x9D82}, {0x9D83, 0x9D83}, + {0x9D84, 0x9D84}, {0x9D85, 0x9D85}, {0x9D86, 0x9D86}, {0x9D87, 0x9D87}, {0x9D88, 0x9D88}, {0x9D89, 0x9D89}, {0x9D8A, 0x9D8A}, + {0x9D8B, 0x9D8B}, {0x9D8C, 0x9D8C}, {0x9D8D, 0x9D8D}, {0x9D8E, 0x9D8E}, {0x9D8F, 0x9D8F}, {0x9D90, 0x9D90}, {0x9D91, 0x9D91}, + {0x9D92, 0x9D92}, {0x9D93, 0x9D93}, {0x9D94, 0x9D94}, {0x9D95, 0x9D95}, {0x9D96, 0x9D96}, {0x9D97, 0x9D97}, {0x9D98, 0x9D98}, + {0x9D99, 0x9D99}, {0x9D9A, 0x9D9A}, {0x9D9B, 0x9D9B}, {0x9D9C, 0x9D9C}, {0x9D9D, 0x9D9D}, {0x9D9E, 0x9D9E}, {0x9D9F, 0x9D9F}, + {0x9DA0, 0x9DA0}, {0x9DA1, 0x9DA1}, {0x9DA2, 0x9DA2}, {0x9DA3, 0x9DA3}, {0x9DA4, 0x9DA4}, {0x9DA5, 0x9DA5}, {0x9DA6, 0x9DA6}, + {0x9DA7, 0x9DA7}, {0x9DA8, 0x9DA8}, {0x9DA9, 0x9DA9}, {0x9DAA, 0x9DAA}, {0x9DAB, 0x9DAB}, {0x9DAC, 0x9DAC}, {0x9DAD, 0x9DAD}, + {0x9DAE, 0x9DAE}, {0x9DAF, 0x9DAF}, {0x9DB0, 0x9DB0}, {0x9DB1, 0x9DB1}, {0x9DB2, 0x9DB2}, {0x9DB3, 0x9DB3}, {0x9DB4, 0x9DB4}, + {0x9DB5, 0x9DB5}, {0x9DB6, 0x9DB6}, {0x9DB7, 0x9DB7}, {0x9DB8, 0x9DB8}, {0x9DB9, 0x9DB9}, {0x9DBA, 0x9DBA}, {0x9DBB, 0x9DBB}, + {0x9DBC, 0x9DBC}, {0x9DBD, 0x9DBD}, {0x9DBE, 0x9DBE}, {0x9DBF, 0x9DBF}, {0x9DC0, 0x9DC0}, {0x9DC1, 0x9DC1}, {0x9DC2, 0x9DC2}, + {0x9DC3, 0x9DC3}, {0x9DC4, 0x9DC4}, {0x9DC5, 0x9DC5}, {0x9DC6, 0x9DC6}, {0x9DC7, 0x9DC7}, {0x9DC8, 0x9DC8}, {0x9DC9, 0x9DC9}, + {0x9DCA, 0x9DCA}, {0x9DCB, 0x9DCB}, {0x9DCC, 0x9DCC}, {0x9DCD, 0x9DCD}, {0x9DCE, 0x9DCE}, {0x9DCF, 0x9DCF}, {0x9DD0, 0x9DD0}, + {0x9DD1, 0x9DD1}, {0x9DD2, 0x9DD2}, {0x9DD3, 0x9DD3}, {0x9DD4, 0x9DD4}, {0x9DD5, 0x9DD5}, {0x9DD6, 0x9DD6}, {0x9DD7, 0x9DD7}, + {0x9DD8, 0x9DD8}, {0x9DD9, 0x9DD9}, {0x9DDA, 0x9DDA}, {0x9DDB, 0x9DDB}, {0x9DDC, 0x9DDC}, {0x9DDD, 0x9DDD}, {0x9DDE, 0x9DDE}, + {0x9DDF, 0x9DDF}, {0x9DE0, 0x9DE0}, {0x9DE1, 0x9DE1}, {0x9DE2, 0x9DE2}, {0x9DE3, 0x9DE3}, {0x9DE4, 0x9DE4}, {0x9DE5, 0x9DE5}, + {0x9DE6, 0x9DE6}, {0x9DE7, 0x9DE7}, {0x9DE8, 0x9DE8}, {0x9DE9, 0x9DE9}, {0x9DEA, 0x9DEA}, {0x9DEB, 0x9DEB}, {0x9DEC, 0x9DEC}, + {0x9DED, 0x9DED}, {0x9DEE, 0x9DEE}, {0x9DEF, 0x9DEF}, {0x9DF0, 0x9DF0}, {0x9DF1, 0x9DF1}, {0x9DF2, 0x9DF2}, {0x9DF3, 0x9DF3}, + {0x9DF4, 0x9DF4}, {0x9DF5, 0x9DF5}, {0x9DF6, 0x9DF6}, {0x9DF7, 0x9DF7}, {0x9DF8, 0x9DF8}, {0x9DF9, 0x9DF9}, {0x9DFA, 0x9DFA}, + {0x9DFB, 0x9DFB}, {0x9DFC, 0x9DFC}, {0x9DFD, 0x9DFD}, {0x9DFE, 0x9DFE}, {0x9DFF, 0x9DFF}, {0x9E00, 0x9E00}, {0x9E01, 0x9E01}, + {0x9E02, 0x9E02}, {0x9E03, 0x9E03}, {0x9E04, 0x9E04}, {0x9E05, 0x9E05}, {0x9E06, 0x9E06}, {0x9E07, 0x9E07}, {0x9E08, 0x9E08}, + {0x9E09, 0x9E09}, {0x9E0A, 0x9E0A}, {0x9E0B, 0x9E0B}, {0x9E0C, 0x9E0C}, {0x9E0D, 0x9E0D}, {0x9E0E, 0x9E0E}, {0x9E0F, 0x9E0F}, + {0x9E10, 0x9E10}, {0x9E11, 0x9E11}, {0x9E12, 0x9E12}, {0x9E13, 0x9E13}, {0x9E14, 0x9E14}, {0x9E15, 0x9E15}, {0x9E16, 0x9E16}, + {0x9E17, 0x9E17}, {0x9E18, 0x9E18}, {0x9E19, 0x9E19}, {0x9E1A, 0x9E1A}, {0x9E1B, 0x9E1B}, {0x9E1C, 0x9E1C}, {0x9E1D, 0x9E1D}, + {0x9E1E, 0x9E1E}, {0x9E1F, 0x9E1F}, {0x9E20, 0x9E20}, {0x9E21, 0x9E21}, {0x9E22, 0x9E22}, {0x9E23, 0x9E23}, {0x9E24, 0x9E24}, + {0x9E25, 0x9E25}, {0x9E26, 0x9E26}, {0x9E27, 0x9E27}, {0x9E28, 0x9E28}, {0x9E29, 0x9E29}, {0x9E2A, 0x9E2A}, {0x9E2B, 0x9E2B}, + {0x9E2C, 0x9E2C}, {0x9E2D, 0x9E2D}, {0x9E2E, 0x9E2E}, {0x9E2F, 0x9E2F}, {0x9E30, 0x9E30}, {0x9E31, 0x9E31}, {0x9E32, 0x9E32}, + {0x9E33, 0x9E33}, {0x9E34, 0x9E34}, {0x9E35, 0x9E35}, {0x9E36, 0x9E36}, {0x9E37, 0x9E37}, {0x9E38, 0x9E38}, {0x9E39, 0x9E39}, + {0x9E3A, 0x9E3A}, {0x9E3B, 0x9E3B}, {0x9E3C, 0x9E3C}, {0x9E3D, 0x9E3D}, {0x9E3E, 0x9E3E}, {0x9E3F, 0x9E3F}, {0x9E40, 0x9E40}, + {0x9E41, 0x9E41}, {0x9E42, 0x9E42}, {0x9E43, 0x9E43}, {0x9E44, 0x9E44}, {0x9E45, 0x9E45}, {0x9E46, 0x9E46}, {0x9E47, 0x9E47}, + {0x9E48, 0x9E48}, {0x9E49, 0x9E49}, {0x9E4A, 0x9E4A}, {0x9E4B, 0x9E4B}, {0x9E4C, 0x9E4C}, {0x9E4D, 0x9E4D}, {0x9E4E, 0x9E4E}, + {0x9E4F, 0x9E4F}, {0x9E50, 0x9E50}, {0x9E51, 0x9E51}, {0x9E52, 0x9E52}, {0x9E53, 0x9E53}, {0x9E54, 0x9E54}, {0x9E55, 0x9E55}, + {0x9E56, 0x9E56}, {0x9E57, 0x9E57}, {0x9E58, 0x9E58}, {0x9E59, 0x9E59}, {0x9E5A, 0x9E5A}, {0x9E5B, 0x9E5B}, {0x9E5C, 0x9E5C}, + {0x9E5D, 0x9E5D}, {0x9E5E, 0x9E5E}, {0x9E5F, 0x9E5F}, {0x9E60, 0x9E60}, {0x9E61, 0x9E61}, {0x9E62, 0x9E62}, {0x9E63, 0x9E63}, + {0x9E64, 0x9E64}, {0x9E65, 0x9E65}, {0x9E66, 0x9E66}, {0x9E67, 0x9E67}, {0x9E68, 0x9E68}, {0x9E69, 0x9E69}, {0x9E6A, 0x9E6A}, + {0x9E6B, 0x9E6B}, {0x9E6C, 0x9E6C}, {0x9E6D, 0x9E6D}, {0x9E6E, 0x9E6E}, {0x9E6F, 0x9E6F}, {0x9E70, 0x9E70}, {0x9E71, 0x9E71}, + {0x9E72, 0x9E72}, {0x9E73, 0x9E73}, {0x9E74, 0x9E74}, {0x9E75, 0x9E75}, {0x9E76, 0x9E76}, {0x9E77, 0x9E77}, {0x9E78, 0x9E78}, + {0x9E79, 0x9E79}, {0x9E7A, 0x9E7A}, {0x9E7B, 0x9E7B}, {0x9E7C, 0x9E7C}, {0x9E7D, 0x9E7D}, {0x9E7E, 0x9E7E}, {0x9E7F, 0x9E7F}, + {0x9E80, 0x9E80}, {0x9E81, 0x9E81}, {0x9E82, 0x9E82}, {0x9E83, 0x9E83}, {0x9E84, 0x9E84}, {0x9E85, 0x9E85}, {0x9E86, 0x9E86}, + {0x9E87, 0x9E87}, {0x9E88, 0x9E88}, {0x9E89, 0x9E89}, {0x9E8A, 0x9E8A}, {0x9E8B, 0x9E8B}, {0x9E8C, 0x9E8C}, {0x9E8D, 0x9E8D}, + {0x9E8E, 0x9E8E}, {0x9E8F, 0x9E8F}, {0x9E90, 0x9E90}, {0x9E91, 0x9E91}, {0x9E92, 0x9E92}, {0x9E93, 0x9E93}, {0x9E94, 0x9E94}, + {0x9E95, 0x9E95}, {0x9E96, 0x9E96}, {0x9E97, 0x9E97}, {0x9E98, 0x9E98}, {0x9E99, 0x9E99}, {0x9E9A, 0x9E9A}, {0x9E9B, 0x9E9B}, + {0x9E9C, 0x9E9C}, {0x9E9D, 0x9E9D}, {0x9E9E, 0x9E9E}, {0x9E9F, 0x9E9F}, {0x9EA0, 0x9EA0}, {0x9EA1, 0x9EA1}, {0x9EA2, 0x9EA2}, + {0x9EA3, 0x9EA3}, {0x9EA4, 0x9EA4}, {0x9EA5, 0x9EA5}, {0x9EA6, 0x9EA6}, {0x9EA7, 0x9EA7}, {0x9EA8, 0x9EA8}, {0x9EA9, 0x9EA9}, + {0x9EAA, 0x9EAA}, {0x9EAB, 0x9EAB}, {0x9EAC, 0x9EAC}, {0x9EAD, 0x9EAD}, {0x9EAE, 0x9EAE}, {0x9EAF, 0x9EAF}, {0x9EB0, 0x9EB0}, + {0x9EB1, 0x9EB1}, {0x9EB2, 0x9EB2}, {0x9EB3, 0x9EB3}, {0x9EB4, 0x9EB4}, {0x9EB5, 0x9EB5}, {0x9EB6, 0x9EB6}, {0x9EB7, 0x9EB7}, + {0x9EB8, 0x9EB8}, {0x9EB9, 0x9EB9}, {0x9EBA, 0x9EBA}, {0x9EBB, 0x9EBB}, {0x9EBC, 0x9EBC}, {0x9EBD, 0x9EBD}, {0x9EBE, 0x9EBE}, + {0x9EBF, 0x9EBF}, {0x9EC0, 0x9EC0}, {0x9EC1, 0x9EC1}, {0x9EC2, 0x9EC2}, {0x9EC3, 0x9EC3}, {0x9EC4, 0x9EC4}, {0x9EC5, 0x9EC5}, + {0x9EC6, 0x9EC6}, {0x9EC7, 0x9EC7}, {0x9EC8, 0x9EC8}, {0x9EC9, 0x9EC9}, {0x9ECA, 0x9ECA}, {0x9ECB, 0x9ECB}, {0x9ECC, 0x9ECC}, + {0x9ECD, 0x9ECD}, {0x9ECE, 0x9ECE}, {0x9ECF, 0x9ECF}, {0x9ED0, 0x9ED0}, {0x9ED1, 0x9ED1}, {0x9ED2, 0x9ED2}, {0x9ED3, 0x9ED3}, + {0x9ED4, 0x9ED4}, {0x9ED5, 0x9ED5}, {0x9ED6, 0x9ED6}, {0x9ED7, 0x9ED7}, {0x9ED8, 0x9ED8}, {0x9ED9, 0x9ED9}, {0x9EDA, 0x9EDA}, + {0x9EDB, 0x9EDB}, {0x9EDC, 0x9EDC}, {0x9EDD, 0x9EDD}, {0x9EDE, 0x9EDE}, {0x9EDF, 0x9EDF}, {0x9EE0, 0x9EE0}, {0x9EE1, 0x9EE1}, + {0x9EE2, 0x9EE2}, {0x9EE3, 0x9EE3}, {0x9EE4, 0x9EE4}, {0x9EE5, 0x9EE5}, {0x9EE6, 0x9EE6}, {0x9EE7, 0x9EE7}, {0x9EE8, 0x9EE8}, + {0x9EE9, 0x9EE9}, {0x9EEA, 0x9EEA}, {0x9EEB, 0x9EEB}, {0x9EEC, 0x9EEC}, {0x9EED, 0x9EED}, {0x9EEE, 0x9EEE}, {0x9EEF, 0x9EEF}, + {0x9EF0, 0x9EF0}, {0x9EF1, 0x9EF1}, {0x9EF2, 0x9EF2}, {0x9EF3, 0x9EF3}, {0x9EF4, 0x9EF4}, {0x9EF5, 0x9EF5}, {0x9EF6, 0x9EF6}, + {0x9EF7, 0x9EF7}, {0x9EF8, 0x9EF8}, {0x9EF9, 0x9EF9}, {0x9EFA, 0x9EFA}, {0x9EFB, 0x9EFB}, {0x9EFC, 0x9EFC}, {0x9EFD, 0x9EFD}, + {0x9EFE, 0x9EFE}, {0x9EFF, 0x9EFF}, {0x9F00, 0x9F00}, {0x9F01, 0x9F01}, {0x9F02, 0x9F02}, {0x9F03, 0x9F03}, {0x9F04, 0x9F04}, + {0x9F05, 0x9F05}, {0x9F06, 0x9F06}, {0x9F07, 0x9F07}, {0x9F08, 0x9F08}, {0x9F09, 0x9F09}, {0x9F0A, 0x9F0A}, {0x9F0B, 0x9F0B}, + {0x9F0C, 0x9F0C}, {0x9F0D, 0x9F0D}, {0x9F0E, 0x9F0E}, {0x9F0F, 0x9F0F}, {0x9F10, 0x9F10}, {0x9F11, 0x9F11}, {0x9F12, 0x9F12}, + {0x9F13, 0x9F13}, {0x9F14, 0x9F14}, {0x9F15, 0x9F15}, {0x9F16, 0x9F16}, {0x9F17, 0x9F17}, {0x9F18, 0x9F18}, {0x9F19, 0x9F19}, + {0x9F1A, 0x9F1A}, {0x9F1B, 0x9F1B}, {0x9F1C, 0x9F1C}, {0x9F1D, 0x9F1D}, {0x9F1E, 0x9F1E}, {0x9F1F, 0x9F1F}, {0x9F20, 0x9F20}, + {0x9F21, 0x9F21}, {0x9F22, 0x9F22}, {0x9F23, 0x9F23}, {0x9F24, 0x9F24}, {0x9F25, 0x9F25}, {0x9F26, 0x9F26}, {0x9F27, 0x9F27}, + {0x9F28, 0x9F28}, {0x9F29, 0x9F29}, {0x9F2A, 0x9F2A}, {0x9F2B, 0x9F2B}, {0x9F2C, 0x9F2C}, {0x9F2D, 0x9F2D}, {0x9F2E, 0x9F2E}, + {0x9F2F, 0x9F2F}, {0x9F30, 0x9F30}, {0x9F31, 0x9F31}, {0x9F32, 0x9F32}, {0x9F33, 0x9F33}, {0x9F34, 0x9F34}, {0x9F35, 0x9F35}, + {0x9F36, 0x9F36}, {0x9F37, 0x9F37}, {0x9F38, 0x9F38}, {0x9F39, 0x9F39}, {0x9F3A, 0x9F3A}, {0x9F3B, 0x9F3B}, {0x9F3C, 0x9F3C}, + {0x9F3D, 0x9F3D}, {0x9F3E, 0x9F3E}, {0x9F3F, 0x9F3F}, {0x9F40, 0x9F40}, {0x9F41, 0x9F41}, {0x9F42, 0x9F42}, {0x9F43, 0x9F43}, + {0x9F44, 0x9F44}, {0x9F45, 0x9F45}, {0x9F46, 0x9F46}, {0x9F47, 0x9F47}, {0x9F48, 0x9F48}, {0x9F49, 0x9F49}, {0x9F4A, 0x9F4A}, + {0x9F4B, 0x9F4B}, {0x9F4C, 0x9F4C}, {0x9F4D, 0x9F4D}, {0x9F4E, 0x9F4E}, {0x9F4F, 0x9F4F}, {0x9F50, 0x9F50}, {0x9F51, 0x9F51}, + {0x9F52, 0x9F52}, {0x9F53, 0x9F53}, {0x9F54, 0x9F54}, {0x9F55, 0x9F55}, {0x9F56, 0x9F56}, {0x9F57, 0x9F57}, {0x9F58, 0x9F58}, + {0x9F59, 0x9F59}, {0x9F5A, 0x9F5A}, {0x9F5B, 0x9F5B}, {0x9F5C, 0x9F5C}, {0x9F5D, 0x9F5D}, {0x9F5E, 0x9F5E}, {0x9F5F, 0x9F5F}, + {0x9F60, 0x9F60}, {0x9F61, 0x9F61}, {0x9F62, 0x9F62}, {0x9F63, 0x9F63}, {0x9F64, 0x9F64}, {0x9F65, 0x9F65}, {0x9F66, 0x9F66}, + {0x9F67, 0x9F67}, {0x9F68, 0x9F68}, {0x9F69, 0x9F69}, {0x9F6A, 0x9F6A}, {0x9F6B, 0x9F6B}, {0x9F6C, 0x9F6C}, {0x9F6D, 0x9F6D}, + {0x9F6E, 0x9F6E}, {0x9F6F, 0x9F6F}, {0x9F70, 0x9F70}, {0x9F71, 0x9F71}, {0x9F72, 0x9F72}, {0x9F73, 0x9F73}, {0x9F74, 0x9F74}, + {0x9F75, 0x9F75}, {0x9F76, 0x9F76}, {0x9F77, 0x9F77}, {0x9F78, 0x9F78}, {0x9F79, 0x9F79}, {0x9F7A, 0x9F7A}, {0x9F7B, 0x9F7B}, + {0x9F7C, 0x9F7C}, {0x9F7D, 0x9F7D}, {0x9F7E, 0x9F7E}, {0x9F7F, 0x9F7F}, {0x9F80, 0x9F80}, {0x9F81, 0x9F81}, {0x9F82, 0x9F82}, + {0x9F83, 0x9F83}, {0x9F84, 0x9F84}, {0x9F85, 0x9F85}, {0x9F86, 0x9F86}, {0x9F87, 0x9F87}, {0x9F88, 0x9F88}, {0x9F89, 0x9F89}, + {0x9F8A, 0x9F8A}, {0x9F8B, 0x9F8B}, {0x9F8C, 0x9F8C}, {0x9F8D, 0x9F8D}, {0x9F8E, 0x9F8E}, {0x9F8F, 0x9F8F}, {0x9F90, 0x9F90}, + {0x9F91, 0x9F91}, {0x9F92, 0x9F92}, {0x9F93, 0x9F93}, {0x9F94, 0x9F94}, {0x9F95, 0x9F95}, {0x9F96, 0x9F96}, {0x9F97, 0x9F97}, + {0x9F98, 0x9F98}, {0x9F99, 0x9F99}, {0x9F9A, 0x9F9A}, {0x9F9B, 0x9F9B}, {0x9F9C, 0x9F9C}, {0x9F9D, 0x9F9D}, {0x9F9E, 0x9F9E}, + {0x9F9F, 0x9F9F}, {0x9FA0, 0x9FA0}, {0x9FA1, 0x9FA1}, {0x9FA2, 0x9FA2}, {0x9FA3, 0x9FA3}, {0x9FA4, 0x9FA4}, {0x9FA5, 0x9FA5}, + {0x9FA6, 0x9FA6}, {0x9FA7, 0x9FA7}, {0x9FA8, 0x9FA8}, {0x9FA9, 0x9FA9}, {0x9FAA, 0x9FAA}, {0x9FAB, 0x9FAB}, {0x9FAC, 0x9FAC}, + {0x9FAD, 0x9FAD}, {0x9FAE, 0x9FAE}, {0x9FAF, 0x9FAF}, {0x9FB0, 0x9FB0}, {0x9FB1, 0x9FB1}, {0x9FB2, 0x9FB2}, {0x9FB3, 0x9FB3}, + {0x9FB4, 0x9FB4}, {0x9FB5, 0x9FB5}, {0x9FB6, 0x9FB6}, {0x9FB7, 0x9FB7}, {0x9FB8, 0x9FB8}, {0x9FB9, 0x9FB9}, {0x9FBA, 0x9FBA}, + {0x9FBB, 0x9FBB}, {0x9FBC, 0x9FBC}, {0x9FBD, 0x9FBD}, {0x9FBE, 0x9FBE}, {0x9FBF, 0x9FBF}, {0x9FC0, 0x9FC0}, {0x9FC1, 0x9FC1}, + {0x9FC2, 0x9FC2}, {0x9FC3, 0x9FC3}, {0x9FC4, 0x9FC4}, {0x9FC5, 0x9FC5}, {0x9FC6, 0x9FC6}, {0x9FC7, 0x9FC7}, {0x9FC8, 0x9FC8}, + {0x9FC9, 0x9FC9}, {0x9FCA, 0x9FCA}, {0x9FCB, 0x9FCB}, {0x9FCC, 0x9FCC}, {0x9FCD, 0x9FCD}, {0x9FCE, 0x9FCE}, {0x9FCF, 0x9FCF}, + {0x9FD0, 0x9FD0}, {0x9FD1, 0x9FD1}, {0x9FD2, 0x9FD2}, {0x9FD3, 0x9FD3}, {0x9FD4, 0x9FD4}, {0x9FD5, 0x9FD5}, {0x9FD6, 0x9FD6}, + {0x9FD7, 0x9FD7}, {0x9FD8, 0x9FD8}, {0x9FD9, 0x9FD9}, {0x9FDA, 0x9FDA}, {0x9FDB, 0x9FDB}, {0x9FDC, 0x9FDC}, {0x9FDD, 0x9FDD}, + {0x9FDE, 0x9FDE}, {0x9FDF, 0x9FDF}, {0x9FE0, 0x9FE0}, {0x9FE1, 0x9FE1}, {0x9FE2, 0x9FE2}, {0x9FE3, 0x9FE3}, {0x9FE4, 0x9FE4}, + {0x9FE5, 0x9FE5}, {0x9FE6, 0x9FE6}, {0x9FE7, 0x9FE7}, {0x9FE8, 0x9FE8}, {0x9FE9, 0x9FE9}, {0x9FEA, 0x9FEA}, {0x9FEB, 0x9FEB}, + {0x9FEC, 0x9FEC}, {0x9FED, 0x9FED}, {0x9FEE, 0x9FEE}, {0x9FEF, 0x9FEF}, {0x9FF0, 0x9FF0}, {0x9FF1, 0x9FF1}, {0x9FF2, 0x9FF2}, + {0x9FF3, 0x9FF3}, {0x9FF4, 0x9FF4}, {0x9FF5, 0x9FF5}, {0x9FF6, 0x9FF6}, {0x9FF7, 0x9FF7}, {0x9FF8, 0x9FF8}, {0x9FF9, 0x9FF9}, + {0x9FFA, 0x9FFA}, {0x9FFB, 0x9FFB}, {0x9FFC, 0x9FFC}, {0x9FFD, 0x9FFD}, {0x9FFE, 0x9FFE}, {0x9FFF, 0x9FFF}, // Halfwidth and Fullwidth Forms (Latin) {0xFF41, 0xFF21}, {0xFF42, 0xFF22}, {0xFF43, 0xFF23}, {0xFF44, 0xFF24}, {0xFF45, 0xFF25}, {0xFF46, 0xFF26}, {0xFF47, 0xFF27}, {0xFF48, 0xFF28}, {0xFF49, 0xFF29}, {0xFF4A, 0xFF2A}, {0xFF4B, 0xFF2B}, {0xFF4C, 0xFF2C}, {0xFF4D, 0xFF2D}, {0xFF4E, 0xFF2E}, @@ -199,6 +3213,8 @@ constexpr std::pair kAlphabet[] = { // clang-format on }; +#if RX_WITH_STDLIB_DEBUG + constexpr int checkAlphabetSorted() { for (int i = 1; i < std::end(kAlphabet) - std::begin(kAlphabet); i++) { if (kAlphabet[i - 1] >= kAlphabet[i]) { @@ -227,6 +3243,8 @@ constexpr bool checkAlphabetLowUpperUtf8SizeEquals() { static_assert(checkAlphabetSorted() == -1, "Alphabet must be sorted"); static_assert(checkAlphabetLowUpperUtf8SizeEquals(), "The length of utf8 capital and small letters must be the same"); +#endif // RX_WITH_STDLIB_DEBUG + CustomLocale::CustomLocale() noexcept { for (uint32_t i = 0; i < UINT16_MAX; ++i) { customLocale_[i].isAlpha = false; diff --git a/cpp_src/tools/serializer.h b/cpp_src/tools/serializer.h index f6a532815..0f80dc496 100644 --- a/cpp_src/tools/serializer.h +++ b/cpp_src/tools/serializer.h @@ -147,9 +147,9 @@ class Serializer { Variant getPVStringVariant(); const v_string_hdr* getPVStringPtr(); - const uint8_t* buf_; - size_t len_; - size_t pos_; + const uint8_t* buf_{nullptr}; + size_t len_{0}; + size_t pos_{0}; }; class WrSerializer { @@ -265,8 +265,8 @@ class WrSerializer { } private: - WrSerializer* ser_; - size_t pos_; + const WrSerializer* ser_{nullptr}; + size_t pos_{0}; }; public: @@ -289,8 +289,8 @@ class WrSerializer { void End(); private: - WrSerializer* ser_; - size_t pos_; + WrSerializer* ser_{nullptr}; + size_t pos_{0}; }; SliceHelper StartSlice() { @@ -465,22 +465,20 @@ class WrSerializer { size_t Cap() const noexcept { return cap_; } void Reserve(size_t cap) { if (cap > cap_) { - cap_ = cap; - uint8_t* b = new uint8_t[cap_]; - memcpy(b, buf_, len_); + auto b = std::make_unique(cap); + memcpy(b.get(), buf_, len_); if (HasAllocatedBuffer()) { delete[] buf_; // NOLINT(*.NewDelete) False positive } - buf_ = b; + buf_ = b.release(); + cap_ = cap; hasExternalBuf_ = false; } } RX_ALWAYS_INLINE std::string_view Slice() const noexcept { return {reinterpret_cast(buf_), len_}; } const char* c_str() noexcept { - if (!len_ || buf_[len_] != 0) { - grow(1); - buf_[len_] = 0; - } + grow(1); + buf_[len_] = 0; return reinterpret_cast(buf_); } @@ -493,11 +491,11 @@ class WrSerializer { Reserve((newCap == newCapAligned) ? newCap : (newCapAligned + 0x1000)); } } - uint8_t* buf_ = nullptr; - size_t len_ = 0; - size_t cap_ = 0; + uint8_t* buf_{nullptr}; + size_t len_{0}; + size_t cap_{0}; uint8_t inBuf_[0x100]; - bool hasExternalBuf_ = false; + bool hasExternalBuf_{false}; }; inline int msgpack_wrserializer_write(void* data, const char* buf, size_t len) { diff --git a/dependencies.sh b/dependencies.sh index 2c0b85e97..fc6bac526 100755 --- a/dependencies.sh +++ b/dependencies.sh @@ -40,7 +40,7 @@ debian_debs="build-essential g++ libunwind-dev libgoogle-perftools-dev libsnappy alpine_apks="g++ snappy-dev leveldb-dev libunwind-dev make curl cmake unzip git" arch_pkgs="gcc snappy leveldb make curl cmake unzip git" redos_rpms="gcc gcc-c++ make snappy-devel leveldb-devel gperftools-devel findutils curl tar unzip git cmake rpm-build python-srpm-macros" -altlinux_rpms="gcc gcc-c++ make libsnappy-devel libleveldb-devel gperftools-devel curl unzip git cmake ctest rpm-build rpmdevtools" +altlinux_rpms="gcc gcc-c++ make libsnappy-devel libleveldb-devel libgperftools-devel curl unzip git cmake ctest rpm-build rpmdevtools" cmake_installed () { info_msg "Check for installed cmake ..... " diff --git a/dsl/dsl.go b/dsl/dsl.go index bf4945939..1cf39afa5 100644 --- a/dsl/dsl.go +++ b/dsl/dsl.go @@ -71,6 +71,10 @@ type Aggregation struct { Fields []string `json:"fields"` } +type EqualPosition struct { + Positions []string `json:"positions"` +} + type sort Sort type Sort struct { @@ -80,13 +84,14 @@ type Sort struct { } type Filter struct { - Op string `json:"Op,omitempty"` - Field string `json:"Field,omitempty"` - Joined *JoinQuery `json:"Join_Query,omitempty"` - SubQ *SubQuery `json:"Subquery,omitempty"` - Cond string `json:"Cond,omitempty"` - Value interface{} `json:"Value,omitempty"` - Filters []Filter `json:"Filters,omitempty"` + Op string `json:"Op,omitempty"` + Field string `json:"Field,omitempty"` + Joined *JoinQuery `json:"Join_Query,omitempty"` + SubQ *SubQuery `json:"Subquery,omitempty"` + Cond string `json:"Cond,omitempty"` + Value interface{} `json:"Value,omitempty"` + EqualPositions []EqualPosition `json:"equal_positions,omitempty"` + Filters []Filter `json:"Filters,omitempty"` } type JoinOnCondition struct { @@ -136,13 +141,14 @@ type SubQuery struct { } type filter struct { - Op string `json:"op,omitempty"` - Field string `json:"field,omitempty"` - Joined *joinQuery `json:"join_query,omitempty"` - SubQ *subQuery `json:"subquery,omitempty"` - Cond string `json:"cond,omitempty"` - Value value `json:"value,omitempty"` - Filters []filter `json:"filters,omitempty"` + Op string `json:"op,omitempty"` + Field string `json:"field,omitempty"` + Joined *joinQuery `json:"join_query,omitempty"` + SubQ *subQuery `json:"subquery,omitempty"` + Cond string `json:"cond,omitempty"` + Value value `json:"value,omitempty"` + EqualPositions []EqualPosition `json:"equal_positions,omitempty"` + Filters []filter `json:"filters,omitempty"` } type value struct { @@ -216,6 +222,7 @@ func (f *Filter) fillFilter(flt *filter) error { f.Op = flt.Op f.Cond = flt.Cond f.Field = flt.Field + f.EqualPositions = flt.EqualPositions if flt.Joined != nil { f.Joined = &JoinQuery{joinQueryBase: joinQueryBase{Namespace: flt.Joined.Namespace, Type: flt.Joined.Type, Sort: flt.Joined.Sort, diff --git a/fulltext.md b/fulltext.md index a464a2b76..a6bfdddb0 100644 --- a/fulltext.md +++ b/fulltext.md @@ -18,6 +18,7 @@ Reindexer has builtin full text search engine. This document describes usage of - [Highlight](#highlight) - [Snippet](#snippet) - [Snippet_n](#snippet_n) + - [Debug_rank](#debug_rank) - [Typos algorithm](#typos-algorithm) - [Typos handling details](#typos-handling-details) - [More examples](#more-examples) @@ -193,7 +194,7 @@ It is possible to merge multiple queries results and sort final result by releva ``` ## Using select functions It is possible to use select functions to process result data. -For now you can use snippet, snippet_n and highlight. For composite indexes the result of the function will be written in to corresponding subfields. +For now you can use snippet, snippet_n and highlight, debug_rank. For composite indexes the result of the function will be written in to corresponding subfields. You can not put [,)\0] symbols in functions params. If the value contains special characters, it must be enclosed in single quotes. @@ -273,6 +274,10 @@ b.Query("items").Match("text", query).Limit(limit).Offset(offset).Functions("tex result: "{me text str}" +### Debug_rank + +This function outputs additional information about ranking of the found word in the text in the key-value format. Returned format and content may vary depending on reindexer's version. Works with `text`-index only. + ## Typos algorithm Reindexer finds misspelled words by matching terms with deleted symbols. diff --git a/query.go b/query.go index f6aed23f7..313843655 100644 --- a/query.go +++ b/query.go @@ -1047,6 +1047,9 @@ func (q *Query) Get() (item interface{}, found bool) { // GetCtx will execute query, and return 1 st item, panic on error func (q *Query) GetCtx(ctx context.Context) (item interface{}, found bool) { + if q.root != nil { + q = q.root + } iter := q.Limit(1).MustExecCtx(ctx) defer iter.Close() if iter.Next() { @@ -1062,6 +1065,9 @@ func (q *Query) GetJson() (json []byte, found bool) { // GetJsonCtx will execute query, and return 1 st item, panic on error func (q *Query) GetJsonCtx(ctx context.Context) (json []byte, found bool) { + if q.root != nil { + q = q.root + } it := q.Limit(1).ExecToJsonCtx(ctx) defer it.Close() if it.Error() != nil { diff --git a/reindexer_impl.go b/reindexer_impl.go index f7958f27a..bd1af2daf 100644 --- a/reindexer_impl.go +++ b/reindexer_impl.go @@ -870,7 +870,7 @@ func (db *reindexerImpl) mustBeginTx(ctx context.Context, namespace string) *Tx return tx } -func (db *reindexerImpl) addFilterDSL(filter *dsl.Filter, q *Query) error { +func (db *reindexerImpl) addFilterDSL(filter *dsl.Filter, q *Query, fields *map[string]bool) error { if filter.Field == "" { return ErrEmptyFieldName } @@ -880,6 +880,7 @@ func (db *reindexerImpl) addFilterDSL(filter *dsl.Filter, q *Query) error { } if filter.Value != nil || cond == bindings.ANY || cond == bindings.EMPTY { // Skip filter if value is nil (for backwards compatibility reasons) + (*fields)[filter.Field] = q.nextOp == opAND q.Where(filter.Field, cond, filter.Value) } else { q.And() @@ -1036,9 +1037,12 @@ func (db *reindexerImpl) addSubqueryDSL(filter *dsl.Filter, q *Query) error { } func (db *reindexerImpl) handleFiltersDSL(filters []dsl.Filter, joinIDs *map[string]int, q *Query) (*Query, error) { + equalPositionsFilters := make([]*dsl.Filter, 0, len(filters)) + fields := make(map[string]bool) + for fi := range filters { filter := &filters[fi] - switch strings.ToLower(filters[fi].Op) { + switch strings.ToLower(filter.Op) { case "": q.And() case "and": @@ -1048,7 +1052,7 @@ func (db *reindexerImpl) handleFiltersDSL(filters []dsl.Filter, joinIDs *map[str case "not": q.Not() default: - return nil, bindings.NewError(fmt.Sprintf("rq: dsl filter op is invalid: '%s'", filters[fi].Op), ErrCodeParams) + return nil, bindings.NewError(fmt.Sprintf("rq: dsl filter op is invalid: '%s'", filter.Op), ErrCodeParams) } if filter.Joined != nil { @@ -1107,14 +1111,63 @@ func (db *reindexerImpl) handleFiltersDSL(filters []dsl.Filter, joinIDs *map[str return nil, err } continue + } else if len(filter.EqualPositions) > 0 { + equalPositionsFilters = append(equalPositionsFilters, filter) + continue } - if err := db.addFilterDSL(filter, q); err != nil { + if err := db.addFilterDSL(filter, q, &fields); err != nil { return nil, err } } + + if err := db.processEqualPositions(q, equalPositionsFilters, fields); err != nil { + return nil, err + } + return q, nil } +func (db *reindexerImpl) processEqualPositions(q *Query, filters []*dsl.Filter, conditionFields map[string]bool) error { + for _, filter := range filters { + if filter.Cond != "" || + filter.Op != "" || + filter.Field != "" || + filter.Value != nil || + filter.Filters != nil || + filter.Joined != nil || + filter.SubQ != nil { + return bindings.NewError("rq: filter: filter with 'equal_positions'-field should not contain any other fields besides it", ErrCodeParams) + } + + for _, EqualPositionsElement := range filter.EqualPositions { + fieldsCount := len(EqualPositionsElement.Positions) + if fieldsCount < 2 { + return bindings.NewError(fmt.Sprintf("rq: filter: 'equal_positions' is supposed to have at least 2 arguments. Arguments: %v", + EqualPositionsElement.Positions), ErrCodeParams) + } + + fields := make([]string, 0, fieldsCount) + for _, field := range EqualPositionsElement.Positions { + isAndOp, exist := conditionFields[field] + if !exist { + return bindings.NewError("rq: filter: fields from 'equal_positions'-filter must be specified in the 'where'-conditions of other filters in the current bracket", + ErrCodeParams) + } + if !isAndOp { + return bindings.NewError(fmt.Sprintf("rq: filter: only AND operation allowed for equal position; equal position field with not AND operation: '%s'; equal position fields: %v", + field, + EqualPositionsElement.Positions), + ErrCodeParams) + } + fields = append(fields, field) + } + + q.EqualPosition(fields...) + } + } + return nil +} + func (db *reindexerImpl) addAggregationsDSL(q *Query, aggs []dsl.Aggregation) error { for _, agg := range aggs { if len(agg.Fields) == 0 { diff --git a/test/dsl_test.go b/test/dsl_test.go index 35d317475..5e0f44971 100644 --- a/test/dsl_test.go +++ b/test/dsl_test.go @@ -26,6 +26,12 @@ type TestDSLJoinItem struct { JID int `reindex:"jid,,pk"` } +type TestDSLEqualPositionItem struct { + ID int `reindex:"id,,pk"` + ArrayField1 []int `reindex:"array_field_1"` + ArrayField2 []int `reindex:"array_field_2"` +} + func init() { tnamespaces["test_namespace_dsl"] = TestDSLItem{} tnamespaces["test_namespace_dsl_ft"] = TestDSLFtItem{} @@ -34,6 +40,8 @@ func init() { tnamespaces["test_namespace_dsl_2"] = TestDSLItem{} tnamespaces["test_namespace_dsl_joined_3"] = TestDSLJoinItem{} + + tnamespaces["test_namespace_dsl_equal_position"] = TestDSLEqualPositionItem{} } func newTestDSLItem(id int) interface{} { @@ -117,6 +125,15 @@ func getTestDSLJoinItemsIDs(items []interface{}) []int { return resultIDs } +func getTestDSLEqualPositionItemsIDs(items []interface{}) []int { + resultIDs := make([]int, len(items)) + for i, v := range items { + item := v.(*TestDSLEqualPositionItem) + resultIDs[i] = item.ID + } + return resultIDs +} + func execDSLTwice(t *testing.T, testF func(*testing.T, *reindexer.Query), jsonDSL string) { var marshaledJSON []byte { @@ -142,6 +159,21 @@ func execDSLTwice(t *testing.T, testF func(*testing.T, *reindexer.Query), jsonDS } } +func fillTestDSLEqualPositionItem(t *testing.T, ns string, start int, count int) { + tx := newTestTx(DB, ns) + for i := 0; i < count; i++ { + if err := tx.Upsert( + TestDSLEqualPositionItem{ + ID: start + i, + ArrayField1: []int{1 - i%2, 1, 2, 3, 100 * (i % 2)}, + ArrayField2: []int{0 + i%2, -1, -2, -3, 100}, + }); err != nil { + require.NoError(t, err) + } + } + tx.MustCommit() +} + func TestDSLQueries(t *testing.T) { t.Parallel() @@ -149,6 +181,7 @@ func TestDSLQueries(t *testing.T) { fillTestDSLFtItems(t, "test_namespace_dsl_ft") fillTestDSLJoinItems(t, "test_namespace_dsl_joined_1", 80, 40) fillTestDSLJoinItems(t, "test_namespace_dsl_joined_2", 10, 10) + fillTestDSLEqualPositionItem(t, "test_namespace_dsl_equal_position", 0, 10) t.Run("basic dsl parsing", func(t *testing.T) { const jsonDSL = ` @@ -1739,6 +1772,97 @@ func TestDSLQueries(t *testing.T) { require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) }, jsonDSL) }) + + t.Run("dsl with equal_positions", func(t *testing.T) { + const eqPosFilter = ` + { + "equal_positions": + [ + { + "positions": + [ + "array_field_1", + "array_field_2" + ] + } + ] + }` + + whereFilter := func(val1 int, val2 int) string { + return fmt.Sprintf( + ` + { + "field": "array_field_1", + "cond": "eq", + "value": %d + }, + { + "field": "array_field_2", + "cond": "eq", + "value": %d + }`, + val1, + val2, + ) + } + + // the corresponding sql-like condition: + // ( array_field_1 = 100 AND array_field_2 = 100 EQUAL_POSITION(array_field_1, array_field_2) ) + // AND + // ( + // ( array_field_1 = 1 AND array_field_2 = 0 EQUAL_POSITION(array_field_1, array_field_2) ) + // OR + // ( array_field_1 = 0 AND array_field_2 = 1 EQUAL_POSITION(array_field_1, array_field_2) ) + // ) + jsonDSL := fmt.Sprintf( + ` + { + "namespace": "test_namespace_dsl_equal_position", + "type": "select", + "filters": + [ + %[1]s, + %[4]s, + { + "filters": + [ + { + "filters": + [ + %[2]s, + %[4]s + ] + }, + { + "op": "or", + "filters": + [ + %[3]s, + %[4]s + ] + } + ] + } + ], + "sort": { + "field": "id" + } + }`, + whereFilter(100, 100), + whereFilter(1, 0), + whereFilter(0, 1), + eqPosFilter, + ) + + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + it := q.MustExec() + require.NoError(t, it.Error()) + expectedIDs := []int{1, 3, 5, 7, 9} + items, err := it.FetchAll() + require.NoError(t, err) + require.Equal(t, expectedIDs, getTestDSLEqualPositionItemsIDs(items)) + }, jsonDSL) + }) } func TestDSLQueriesParsingErrors(t *testing.T) { @@ -2966,4 +3090,115 @@ func TestCreateDSLQueriesErrors(t *testing.T) { ` checkErrorQueryFrom(t, jsonDSL, "rq: nested join quieries are not supported") }) + + const wrongJsonDSLTmplt = ` + { + "namespace": "test_namespace_dsl_equal_position", + "type": "select", + "filters": + [ + { + "op": "and", + "cond": "eq", + "field": "f1", + "value": 0 + }, + { + "op": "and", + "cond": "eq", + "field": "f2", + "value": 0 + }, + %s + ] + }` + + testCase := func(errorMessage string, equalPositions string) { + checkErrorQueryFrom(t, fmt.Sprintf(wrongJsonDSLTmplt, equalPositions), errorMessage) + } + + t.Run("dsl equal_positions must contain at least 2 arguments", func(t *testing.T) { + testCase( + "rq: filter: 'equal_positions' is supposed to have at least 2 arguments. Arguments: [f1]", + `{ + "equal_positions": + [ + { + "positions": + [ + "f1" + ] + } + ] + + }`, + ) + }) + + t.Run("dsl equal_positions fields must be specified in other filters", func(t *testing.T) { + testCase( + "rq: filter: fields from 'equal_positions'-filter must be specified in the 'where'-conditions of other filters in the current bracket", + `{ + "equal_positions": + [ + { + "positions": + [ + "f1", + "f2", + "f3" + ] + } + ] + + }`, + ) + }) + + t.Run("dsl equal_positions should not contain extra fields", func(t *testing.T) { + testCase( + "rq: filter: filter with 'equal_positions'-field should not contain any other fields besides it", + `{ + "equal_positions": + [ + { + "positions": + [ + "f1", + "f2" + ] + } + ], + "value": 100, + "cond": "eq", + "field": "f1" + }`, + ) + }) + + t.Run("dsl equal_positions fields should be represented using AND operation only", func(t *testing.T) { + testCase( + "rq: filter: only AND operation allowed for equal position; equal position field with not AND operation: 'f3'; equal position fields: [f1 f2 f3]", + `{ + "op": "or", + "cond": "eq", + "field": "f3", + "value": 0 + }, + { + "equal_positions": + [ + { + "positions": + [ + "f1", + "f2", + "f3" + ] + } + ] + + }`, + ) + }) } diff --git a/test/queries_test.go b/test/queries_test.go index 5c5ec2095..ee491e037 100644 --- a/test/queries_test.go +++ b/test/queries_test.go @@ -558,7 +558,7 @@ func TestQueries(t *testing.T) { panic(err) } - CheckTestItemsQueries(t, testCaseWithIDOnlyIndexe) + CheckTestItemsQueries(t, testCaseWithIDOnlyIndexes) }) t.Run("Sparse indexed queries", func(t *testing.T) { t.Parallel() @@ -1267,7 +1267,7 @@ var testCaseWithCommonIndexes = IndexesTestCase{ }, Item: TestItem{}, } -var testCaseWithIDOnlyIndexe = IndexesTestCase{ +var testCaseWithIDOnlyIndexes = IndexesTestCase{ Name: "TEST WITH ID ONLY INDEX", Namespace: "test_items_id_only", Options: sortDistinctOptions{