18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#ifndef API_BASE_UTIL_UID_H
178bf80f4bSopenharmony_ci#define API_BASE_UTIL_UID_H
188bf80f4bSopenharmony_ci
198bf80f4bSopenharmony_ci#include <cstddef>
208bf80f4bSopenharmony_ci#include <cstdint>
218bf80f4bSopenharmony_ci
228bf80f4bSopenharmony_ci#include <base/containers/string_view.h>
238bf80f4bSopenharmony_ci#include <base/namespace.h>
248bf80f4bSopenharmony_ci#include <base/util/hash.h>
258bf80f4bSopenharmony_ci#include <base/util/log.h>
268bf80f4bSopenharmony_ci
278bf80f4bSopenharmony_ciBASE_BEGIN_NAMESPACE()
288bf80f4bSopenharmony_ciconstexpr uint8_t HexToDec(char c) noexcept
298bf80f4bSopenharmony_ci{
308bf80f4bSopenharmony_ci    if (c <= '9' && c >= '0') {
318bf80f4bSopenharmony_ci        return static_cast<uint8_t>(c - '0');
328bf80f4bSopenharmony_ci    }
338bf80f4bSopenharmony_ci    if (c <= 'F' && c >= 'A') {
348bf80f4bSopenharmony_ci        return static_cast<uint8_t>(c - 'A' + 10);
358bf80f4bSopenharmony_ci    }
368bf80f4bSopenharmony_ci    if (c <= 'f' && c >= 'a') {
378bf80f4bSopenharmony_ci        return static_cast<uint8_t>(c - 'a' + 10);
388bf80f4bSopenharmony_ci    }
398bf80f4bSopenharmony_ci    return 0;
408bf80f4bSopenharmony_ci}
418bf80f4bSopenharmony_ci
428bf80f4bSopenharmony_ciconstexpr uint8_t HexToUint8(const char* c) noexcept
438bf80f4bSopenharmony_ci{
448bf80f4bSopenharmony_ci    return static_cast<uint8_t>((HexToDec(c[0]) << 4U) + HexToDec(c[1]));
458bf80f4bSopenharmony_ci}
468bf80f4bSopenharmony_ci
478bf80f4bSopenharmony_ciconstexpr bool IsUidString(string_view str) noexcept
488bf80f4bSopenharmony_ci{
498bf80f4bSopenharmony_ci    // UID string in the form 8-4-4-4-12. A total of 36 characters (32 hexadecimal characters and 4 hyphens).
508bf80f4bSopenharmony_ci    if (str.size() != 36U) {
518bf80f4bSopenharmony_ci        return false;
528bf80f4bSopenharmony_ci    }
538bf80f4bSopenharmony_ci
548bf80f4bSopenharmony_ci    auto hexChars = [](string_view str) {
558bf80f4bSopenharmony_ci        for (const auto& c : str) {
568bf80f4bSopenharmony_ci            if (!((c <= '9' && c >= '0') || (c <= 'F' && c >= 'A') || (c <= 'f' && c >= 'a'))) {
578bf80f4bSopenharmony_ci                return false;
588bf80f4bSopenharmony_ci            }
598bf80f4bSopenharmony_ci        }
608bf80f4bSopenharmony_ci        return true;
618bf80f4bSopenharmony_ci    };
628bf80f4bSopenharmony_ci    return hexChars(str.substr(0U, 8U)) && (str[8U] == '-') && hexChars(str.substr(9U, 4U)) && (str[13U] == '-') &&
638bf80f4bSopenharmony_ci           hexChars(str.substr(14U, 4U)) && (str[18U] == '-') && hexChars(str.substr(19U, 4U)) && (str[23U] == '-') &&
648bf80f4bSopenharmony_ci           hexChars(str.substr(24U, 12U));
658bf80f4bSopenharmony_ci}
668bf80f4bSopenharmony_ci
678bf80f4bSopenharmony_cistruct Uid {
688bf80f4bSopenharmony_ci    constexpr Uid() noexcept = default;
698bf80f4bSopenharmony_ci
708bf80f4bSopenharmony_ci    explicit constexpr Uid(const uint8_t (&values)[16]) noexcept
718bf80f4bSopenharmony_ci    {
728bf80f4bSopenharmony_ci        uint64_t value = 0U;
738bf80f4bSopenharmony_ci        for (auto first = values, last = values + 8; first != last; ++first) {
748bf80f4bSopenharmony_ci            value = (value << 8) | *first; // 8: Multiply by 256
758bf80f4bSopenharmony_ci        }
768bf80f4bSopenharmony_ci        data[0] = value;
778bf80f4bSopenharmony_ci
788bf80f4bSopenharmony_ci        value = 0U;
798bf80f4bSopenharmony_ci        for (auto first = values + 8, last = values + 16; first != last; ++first) {
808bf80f4bSopenharmony_ci            value = (value << 8) | *first; // 8: Multiply by 256
818bf80f4bSopenharmony_ci        }
828bf80f4bSopenharmony_ci        data[1] = value;
838bf80f4bSopenharmony_ci    }
848bf80f4bSopenharmony_ci
858bf80f4bSopenharmony_ci    explicit constexpr Uid(const char (&str)[37])
868bf80f4bSopenharmony_ci    {
878bf80f4bSopenharmony_ci        if (IsUidString(str)) {
888bf80f4bSopenharmony_ci            auto src = str;
898bf80f4bSopenharmony_ci
908bf80f4bSopenharmony_ci            uint64_t value = 0U;
918bf80f4bSopenharmony_ci            for (size_t i = 0; i < sizeof(uint32_t); ++i) {
928bf80f4bSopenharmony_ci                value = (value << 8) | HexToUint8(src); // 8: Multiply by 256
938bf80f4bSopenharmony_ci                src += 2;
948bf80f4bSopenharmony_ci            }
958bf80f4bSopenharmony_ci            ++src;
968bf80f4bSopenharmony_ci            for (size_t i = 0; i < sizeof(uint16_t); ++i) {
978bf80f4bSopenharmony_ci                value = (value << 8) | HexToUint8(src); // 8: Multiply by 256
988bf80f4bSopenharmony_ci                src += 2;
998bf80f4bSopenharmony_ci            }
1008bf80f4bSopenharmony_ci            ++src;
1018bf80f4bSopenharmony_ci            for (size_t i = 0; i < sizeof(uint16_t); ++i) {
1028bf80f4bSopenharmony_ci                value = (value << 8) | HexToUint8(src); // 8: Multiply by 256
1038bf80f4bSopenharmony_ci                src += 2;
1048bf80f4bSopenharmony_ci            }
1058bf80f4bSopenharmony_ci            ++src;
1068bf80f4bSopenharmony_ci            data[0U] = value;
1078bf80f4bSopenharmony_ci
1088bf80f4bSopenharmony_ci            value = 0U;
1098bf80f4bSopenharmony_ci            for (size_t i = 0; i < sizeof(uint16_t); ++i) {
1108bf80f4bSopenharmony_ci                value = (value << 8) | HexToUint8(src); // 8: Multiply by 256
1118bf80f4bSopenharmony_ci                src += 2;
1128bf80f4bSopenharmony_ci            }
1138bf80f4bSopenharmony_ci            ++src;
1148bf80f4bSopenharmony_ci            for (size_t i = 0; i < (sizeof(uint16_t) * 3); ++i) {
1158bf80f4bSopenharmony_ci                value = (value << 8) | HexToUint8(src); // 8: Multiply by 256
1168bf80f4bSopenharmony_ci                src += 2;
1178bf80f4bSopenharmony_ci            }
1188bf80f4bSopenharmony_ci            data[1U] = value;
1198bf80f4bSopenharmony_ci        }
1208bf80f4bSopenharmony_ci    }
1218bf80f4bSopenharmony_ci
1228bf80f4bSopenharmony_ci    constexpr int compare(const Uid& rhs) const
1238bf80f4bSopenharmony_ci    {
1248bf80f4bSopenharmony_ci        if (data[0] < rhs.data[0]) {
1258bf80f4bSopenharmony_ci            return -1;
1268bf80f4bSopenharmony_ci        }
1278bf80f4bSopenharmony_ci        if (data[0] > rhs.data[0]) {
1288bf80f4bSopenharmony_ci            return 1;
1298bf80f4bSopenharmony_ci        }
1308bf80f4bSopenharmony_ci        if (data[1] < rhs.data[1]) {
1318bf80f4bSopenharmony_ci            return -1;
1328bf80f4bSopenharmony_ci        }
1338bf80f4bSopenharmony_ci        if (data[1] > rhs.data[1]) {
1348bf80f4bSopenharmony_ci            return 1;
1358bf80f4bSopenharmony_ci        }
1368bf80f4bSopenharmony_ci        return 0;
1378bf80f4bSopenharmony_ci    }
1388bf80f4bSopenharmony_ci    uint64_t data[2u] {};
1398bf80f4bSopenharmony_ci};
1408bf80f4bSopenharmony_ci
1418bf80f4bSopenharmony_ciinline constexpr bool operator<(const Uid& lhs, const Uid& rhs)
1428bf80f4bSopenharmony_ci{
1438bf80f4bSopenharmony_ci    if (lhs.data[0] > rhs.data[0]) {
1448bf80f4bSopenharmony_ci        return false;
1458bf80f4bSopenharmony_ci    }
1468bf80f4bSopenharmony_ci    if (lhs.data[0] < rhs.data[0]) {
1478bf80f4bSopenharmony_ci        return true;
1488bf80f4bSopenharmony_ci    }
1498bf80f4bSopenharmony_ci    if (lhs.data[1] < rhs.data[1]) {
1508bf80f4bSopenharmony_ci        return true;
1518bf80f4bSopenharmony_ci    }
1528bf80f4bSopenharmony_ci    return false;
1538bf80f4bSopenharmony_ci}
1548bf80f4bSopenharmony_ci
1558bf80f4bSopenharmony_ciinline constexpr bool operator==(const Uid& lhs, const Uid& rhs)
1568bf80f4bSopenharmony_ci{
1578bf80f4bSopenharmony_ci    return (lhs.data[0U] == rhs.data[0U]) && (lhs.data[1U] == rhs.data[1U]);
1588bf80f4bSopenharmony_ci}
1598bf80f4bSopenharmony_ci
1608bf80f4bSopenharmony_ciinline constexpr bool operator!=(const Uid& lhs, const Uid& rhs)
1618bf80f4bSopenharmony_ci{
1628bf80f4bSopenharmony_ci    return !(lhs == rhs);
1638bf80f4bSopenharmony_ci}
1648bf80f4bSopenharmony_ci
1658bf80f4bSopenharmony_citemplate<>
1668bf80f4bSopenharmony_ciinline uint64_t hash(const Uid& value)
1678bf80f4bSopenharmony_ci{
1688bf80f4bSopenharmony_ci    return Hash(value.data[0], value.data[1]);
1698bf80f4bSopenharmony_ci}
1708bf80f4bSopenharmony_ciBASE_END_NAMESPACE()
1718bf80f4bSopenharmony_ci
1728bf80f4bSopenharmony_ci#endif // API_BASE_UTIL_UID_H
173