1 /*
2  * Copyright (c) 2024 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 API_BASE_UTIL_UID_H
17 #define API_BASE_UTIL_UID_H
18 
19 #include <cstddef>
20 #include <cstdint>
21 
22 #include <base/containers/string_view.h>
23 #include <base/namespace.h>
24 #include <base/util/hash.h>
25 #include <base/util/log.h>
26 
BASE_BEGIN_NAMESPACE()27 BASE_BEGIN_NAMESPACE()
28 constexpr uint8_t HexToDec(char c) noexcept
29 {
30     if (c <= '9' && c >= '0') {
31         return static_cast<uint8_t>(c - '0');
32     }
33     if (c <= 'F' && c >= 'A') {
34         return static_cast<uint8_t>(c - 'A' + 10);
35     }
36     if (c <= 'f' && c >= 'a') {
37         return static_cast<uint8_t>(c - 'a' + 10);
38     }
39     return 0;
40 }
41 
HexToUint8(const char * c)42 constexpr uint8_t HexToUint8(const char* c) noexcept
43 {
44     return static_cast<uint8_t>((HexToDec(c[0]) << 4U) + HexToDec(c[1]));
45 }
46 
IsUidString(string_view str)47 constexpr bool IsUidString(string_view str) noexcept
48 {
49     // UID string in the form 8-4-4-4-12. A total of 36 characters (32 hexadecimal characters and 4 hyphens).
50     if (str.size() != 36U) {
51         return false;
52     }
53 
54     auto hexChars = [](string_view str) {
55         for (const auto& c : str) {
56             if (!((c <= '9' && c >= '0') || (c <= 'F' && c >= 'A') || (c <= 'f' && c >= 'a'))) {
57                 return false;
58             }
59         }
60         return true;
61     };
62     return hexChars(str.substr(0U, 8U)) && (str[8U] == '-') && hexChars(str.substr(9U, 4U)) && (str[13U] == '-') &&
63            hexChars(str.substr(14U, 4U)) && (str[18U] == '-') && hexChars(str.substr(19U, 4U)) && (str[23U] == '-') &&
64            hexChars(str.substr(24U, 12U));
65 }
66 
67 struct Uid {
68     constexpr Uid() noexcept = default;
69 
UidUid70     explicit constexpr Uid(const uint8_t (&values)[16]) noexcept
71     {
72         uint64_t value = 0U;
73         for (auto first = values, last = values + 8; first != last; ++first) {
74             value = (value << 8) | *first; // 8: Multiply by 256
75         }
76         data[0] = value;
77 
78         value = 0U;
79         for (auto first = values + 8, last = values + 16; first != last; ++first) {
80             value = (value << 8) | *first; // 8: Multiply by 256
81         }
82         data[1] = value;
83     }
84 
UidUid85     explicit constexpr Uid(const char (&str)[37])
86     {
87         if (IsUidString(str)) {
88             auto src = str;
89 
90             uint64_t value = 0U;
91             for (size_t i = 0; i < sizeof(uint32_t); ++i) {
92                 value = (value << 8) | HexToUint8(src); // 8: Multiply by 256
93                 src += 2;
94             }
95             ++src;
96             for (size_t i = 0; i < sizeof(uint16_t); ++i) {
97                 value = (value << 8) | HexToUint8(src); // 8: Multiply by 256
98                 src += 2;
99             }
100             ++src;
101             for (size_t i = 0; i < sizeof(uint16_t); ++i) {
102                 value = (value << 8) | HexToUint8(src); // 8: Multiply by 256
103                 src += 2;
104             }
105             ++src;
106             data[0U] = value;
107 
108             value = 0U;
109             for (size_t i = 0; i < sizeof(uint16_t); ++i) {
110                 value = (value << 8) | HexToUint8(src); // 8: Multiply by 256
111                 src += 2;
112             }
113             ++src;
114             for (size_t i = 0; i < (sizeof(uint16_t) * 3); ++i) {
115                 value = (value << 8) | HexToUint8(src); // 8: Multiply by 256
116                 src += 2;
117             }
118             data[1U] = value;
119         }
120     }
121 
compareUid122     constexpr int compare(const Uid& rhs) const
123     {
124         if (data[0] < rhs.data[0]) {
125             return -1;
126         }
127         if (data[0] > rhs.data[0]) {
128             return 1;
129         }
130         if (data[1] < rhs.data[1]) {
131             return -1;
132         }
133         if (data[1] > rhs.data[1]) {
134             return 1;
135         }
136         return 0;
137     }
138     uint64_t data[2u] {};
139 };
140 
141 inline constexpr bool operator<(const Uid& lhs, const Uid& rhs)
142 {
143     if (lhs.data[0] > rhs.data[0]) {
144         return false;
145     }
146     if (lhs.data[0] < rhs.data[0]) {
147         return true;
148     }
149     if (lhs.data[1] < rhs.data[1]) {
150         return true;
151     }
152     return false;
153 }
154 
155 inline constexpr bool operator==(const Uid& lhs, const Uid& rhs)
156 {
157     return (lhs.data[0U] == rhs.data[0U]) && (lhs.data[1U] == rhs.data[1U]);
158 }
159 
160 inline constexpr bool operator!=(const Uid& lhs, const Uid& rhs)
161 {
162     return !(lhs == rhs);
163 }
164 
165 template<>
hash(const Uid & value)166 inline uint64_t hash(const Uid& value)
167 {
168     return Hash(value.data[0], value.data[1]);
169 }
170 BASE_END_NAMESPACE()
171 
172 #endif // API_BASE_UTIL_UID_H
173