• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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