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