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 PANDA_VERIFIER_UTIL_DESCRIPTOR_STRING_H__ 17 #define PANDA_VERIFIER_UTIL_DESCRIPTOR_STRING_H__ 18 19 #include "libpandabase/utils/hash.h" 20 #include "libpandabase/utils/utf.h" 21 22 #include "macros.h" 23 24 #include <cstring> 25 #include <type_traits> 26 27 namespace panda::verifier { 28 29 namespace mode { 30 struct ExactCmp { 31 }; 32 struct NonExactCmp { 33 }; 34 } // namespace mode 35 36 // NB!: non-owning wrapper for mutf8 strings 37 template <typename Mode = mode::ExactCmp> 38 class DescriptorString { 39 static_assert(std::is_same_v<Mode, mode::ExactCmp> || std::is_same_v<Mode, mode::NonExactCmp>); 40 41 public: 42 DescriptorString() = default; DescriptorString(const uint8_t * mutf8_str)43 DescriptorString(const uint8_t *mutf8_str) 44 : hash_ {PseudoFnvHashString(mutf8_str)}, 45 mutf8_str_len_ {std::strlen(utf::Mutf8AsCString(mutf8_str))}, 46 mutf8_str_ {mutf8_str} 47 { 48 } DescriptorString(const char * str)49 DescriptorString(const char *str) : DescriptorString {utf::CStringAsMutf8(str)} {} 50 DescriptorString(const DescriptorString &other) = default; 51 DescriptorString(DescriptorString &&) = default; 52 DescriptorString &operator=(const DescriptorString &) = default; 53 DescriptorString &operator=(DescriptorString &&) = default; 54 bool operator==(const DescriptorString &rhs) const 55 { 56 ASSERT(IsValid()); 57 if (mutf8_str_ == rhs.mutf8_str_) { 58 ASSERT(hash_ == rhs.hash_ && mutf8_str_len_ == rhs.mutf8_str_len_); 59 return true; 60 } 61 if (hash_ != rhs.hash_) { 62 ASSERT(mutf8_str_ != rhs.mutf8_str_); 63 return false; 64 } 65 if (mutf8_str_len_ != rhs.mutf8_str_len_) { 66 return false; 67 } 68 if constexpr (std::is_same_v<Mode, mode::ExactCmp>) { 69 return utf::IsEqual(mutf8_str_, rhs.mutf8_str_); 70 } 71 // NB! Regarding mode::NonExactCmp 72 // Assumption: probability of different strings with same len and hash is very low 73 // Use it only if there is the need for speed 74 return true; 75 } 76 bool operator!=(const DescriptorString &rhs) const 77 { 78 return !operator==(rhs); 79 } 80 operator const uint8_t *() const 81 { 82 return AsMutf8(); 83 } 84 operator const char *() const 85 { 86 return reinterpret_cast<const char *>(AsMutf8()); 87 } AsMutf8()88 const uint8_t *AsMutf8() const 89 { 90 ASSERT(IsValid()); 91 return mutf8_str_; 92 } IsValid()93 bool IsValid() const 94 { 95 return mutf8_str_ != nullptr; 96 } GetLength()97 size_t GetLength() const 98 { 99 return mutf8_str_len_; 100 } 101 102 private: 103 uint32_t hash_ = 0; 104 size_t mutf8_str_len_ = 0; 105 const uint8_t *mutf8_str_ = nullptr; 106 107 template <typename T> 108 friend struct std::hash; 109 }; 110 111 template <typename Mode> 112 std::ostream &operator<<(std::ostream &os, const DescriptorString<Mode> &str) 113 { 114 return os << utf::Mutf8AsCString(str.AsMutf8()); 115 } 116 117 } // namespace panda::verifier 118 119 namespace std { 120 121 template <typename Mode> 122 struct hash<panda::verifier::DescriptorString<Mode>> { 123 size_t operator()(const panda::verifier::DescriptorString<Mode> &desc_str) const noexcept 124 { 125 return static_cast<size_t>(desc_str.hash_); 126 } 127 }; 128 129 } // namespace std 130 131 #endif // !PANDA_VERIFIER_UTIL_DESCRIPTOR_STRING_H__ 132