1 /* 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_JS_COLLATOR_H 17 #define ECMASCRIPT_JS_COLLATOR_H 18 19 #include "ecmascript/js_locale.h" 20 21 #include "unicode/udata.h" 22 23 namespace panda::ecmascript { 24 enum class UsageOption : uint8_t { SORT = 0x01, SEARCH, EXCEPTION }; 25 enum class CaseFirstOption : uint8_t { UPPER = 0x01, LOWER, FALSE_OPTION, UNDEFINED, EXCEPTION }; 26 enum class SensitivityOption : uint8_t { BASE = 0x01, ACCENT, CASE, VARIANT, UNDEFINED, EXCEPTION }; 27 enum class CompareStringsOption : uint8_t { NONE = 0x01, TRY_FAST_PATH }; 28 29 class JSCollator : public JSObject { 30 public: 31 // NOLINTNEXTLINE (readability-identifier-naming, fuchsia-statically-constructed-objects) 32 static const CString uIcuDataColl; 33 34 static const std::map<std::string, CaseFirstOption> caseFirstMap; 35 36 static const std::map<CaseFirstOption, UColAttributeValue> uColAttributeValueMap; 37 38 static const std::vector<LocaleMatcherOption> LOCALE_MATCHER_OPTION; 39 static const std::vector<std::string> LOCALE_MATCHER_OPTION_NAME; 40 41 static const std::vector<CaseFirstOption> CASE_FIRST_OPTION; 42 static const std::vector<std::string> CASE_FIRST_OPTION_NAME; 43 44 static const std::set<std::string> RELEVANT_EXTENSION_KEYS; 45 46 static const std::vector<SensitivityOption> SENSITIVITY_OPTION; 47 static const std::vector<std::string> SENSITIVITY_OPTION_NAME; 48 49 static const std::vector<UsageOption> USAGE_OPTION; 50 static const std::vector<std::string> USAGE_OPTION_NAME; 51 52 // All the available locales that are statically known to fulfill fast path conditions. 53 static const char *const FAST_LOCALE[]; 54 55 CAST_CHECK(JSCollator, IsJSCollator); 56 57 static constexpr size_t ICU_FIELD_OFFSET = JSObject::SIZE; 58 // icu field. 59 ACCESSORS(IcuField, ICU_FIELD_OFFSET, LOCALE_OFFSET) 60 ACCESSORS(Locale, LOCALE_OFFSET, COLLATION_OFFSET) 61 ACCESSORS(Collation, COLLATION_OFFSET, BOUND_COMPARE_OFFSET) 62 ACCESSORS(BoundCompare, BOUND_COMPARE_OFFSET, BIT_FIELD_OFFSET) 63 ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET) 64 DEFINE_ALIGN_SIZE(LAST_OFFSET); 65 66 // define BitField 67 static constexpr size_t USAGE_BITS = 2; 68 static constexpr size_t CASE_FIRST_BITS = 3; 69 static constexpr size_t SENSITIVITY_BITS = 3; 70 static constexpr size_t IGNORE_PUNCTUATION_BITS = 1; 71 static constexpr size_t NUMERIC_BITS = 1; 72 FIRST_BIT_FIELD(BitField, Usage, UsageOption, USAGE_BITS) 73 NEXT_BIT_FIELD(BitField, CaseFirst, CaseFirstOption, CASE_FIRST_BITS, Usage) 74 NEXT_BIT_FIELD(BitField, Sensitivity, SensitivityOption, SENSITIVITY_BITS, CaseFirst) 75 NEXT_BIT_FIELD(BitField, IgnorePunctuation, bool, IGNORE_PUNCTUATION_BITS, Sensitivity) 76 NEXT_BIT_FIELD(BitField, Numeric, bool, NUMERIC_BITS, IgnorePunctuation) 77 78 DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, ICU_FIELD_OFFSET, BIT_FIELD_OFFSET) 79 DECL_DUMP() 80 GetIcuCollator() const81 icu::Collator *GetIcuCollator() const 82 { 83 ASSERT(GetIcuField().IsJSNativePointer()); 84 JSNativePointer *nativePointer = JSNativePointer::Cast(GetIcuField().GetTaggedObject()); 85 auto result = nativePointer->GetExternalPointer(); 86 return reinterpret_cast<icu::Collator *>(result); 87 } 88 FreeIcuCollator([[maybe_unused]] void *env, void *pointer, [[maybe_unused]] void *hint = nullptr)89 static void FreeIcuCollator([[maybe_unused]] void *env, void *pointer, [[maybe_unused]] void *hint = nullptr) 90 { 91 if (pointer == nullptr) { 92 return; 93 } 94 auto icuCollator = reinterpret_cast<icu::Collator *>(pointer); 95 delete icuCollator; 96 } 97 98 static void SetIcuCollator(JSThread *thread, const JSHandle<JSCollator> &collator, 99 icu::Collator *icuCollator, const NativePointerCallback &callback); 100 101 // 11.1.1 InitializeCollator ( collator, locales, options ) 102 static JSHandle<JSCollator> InitializeCollator(JSThread *thread, const JSHandle<JSCollator> &collator, 103 const JSHandle<JSTaggedValue> &locales, 104 const JSHandle<JSTaggedValue> &options, 105 bool forIcuCache = false, 106 bool enableLocaleCache = false); 107 108 static icu::Collator *GetCachedIcuCollator(JSThread *thread, const JSHandle<JSTaggedValue> &locales); 109 static icu::Collator *GetCachedIcuCollator(JSThread *thread, const JSTaggedValue &locales); 110 111 // 11.3.4 Intl.Collator.prototype.resolvedOptions () 112 static JSHandle<JSObject> ResolvedOptions(JSThread *thread, const JSHandle<JSCollator> &collator); 113 114 static JSHandle<TaggedArray> GetAvailableLocales(JSThread *thread, bool enableLocaleCache = false); 115 116 static CompareStringsOption CompareStringsOptionFor(JSThread *thread, JSHandle<JSTaggedValue> locales); 117 118 static CompareStringsOption CompareStringsOptionFor(JSThread *thread, JSHandle<JSTaggedValue> locales, 119 JSHandle<JSTaggedValue> options); 120 121 static JSTaggedValue CompareStrings(JSThread *thread, const icu::Collator *icuCollator, 122 const JSHandle<EcmaString> &string1, const JSHandle<EcmaString> &string2, 123 CompareStringsOption csOption = CompareStringsOption::NONE); 124 125 private: 126 static CaseFirstOption StringToCaseFirstOption(const std::string &str); 127 128 static UColAttributeValue OptionToUColAttribute(CaseFirstOption caseFirstOption); 129 130 static std::set<std::string> BuildLocaleSet(const std::vector<std::string> &availableLocales, const char *path, 131 const char *key); 132 133 static void SetNumericOption(icu::Collator *icuCollator, bool numeric); 134 135 static void SetCaseFirstOption(icu::Collator *icuCollator, CaseFirstOption caseFirstOption); 136 }; 137 } // namespace panda::ecmascript 138 #endif // ECMASCRIPT_JS_COLLATOR_H 139