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