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