1 /**
2 * Copyright (c) 2025 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 #include <cstdint>
17 #include <cstdlib>
18 #include <array>
19 #include <sstream>
20 #include <securec.h>
21 #include <sys/types.h>
22 #include <random>
23
24 #include "tools/format_logger.h"
25 #include "Util.h"
26 #include "stdlib/native/core/stdlib_ani_helpers.h"
27
28 namespace ark::ets::sdk::util {
29
30 constexpr int UUID_LEN = 37;
31 constexpr uint32_t NULL_FOUR_HIGH_BITS_IN_16 = 0x0FFF;
32 constexpr uint32_t RFC4122_UUID_VERSION_MARKER = 0x4000;
33 constexpr uint32_t NULL_TWO_HIGH_BITS_IN_16 = 0x3FFF;
34 constexpr uint32_t RFC4122_UUID_RESERVED_BITS = 0x8000;
35
36 template <typename S>
GenRandUint()37 S GenRandUint()
38 {
39 static auto device = std::random_device();
40 static auto randomGenerator = std::mt19937(device());
41 static auto range = std::uniform_int_distribution<S>();
42
43 return range(randomGenerator);
44 }
45
GenUuid4(ani_env * env)46 std::string GenUuid4(ani_env *env)
47 {
48 std::array<char, UUID_LEN> uuidStr = {0};
49 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
50 int n = snprintf_s(
51 uuidStr.begin(), UUID_LEN, UUID_LEN - 1, "%08x-%04x-%04x-%04x-%012x", GenRandUint<uint32_t>(),
52 GenRandUint<uint16_t>(), (GenRandUint<uint16_t>() & NULL_FOUR_HIGH_BITS_IN_16) | RFC4122_UUID_VERSION_MARKER,
53 (GenRandUint<uint16_t>() & NULL_TWO_HIGH_BITS_IN_16) | RFC4122_UUID_RESERVED_BITS, GenRandUint<uint64_t>());
54 if ((n < 0) || (n > static_cast<int>(UUID_LEN))) {
55 stdlib::ThrowNewError(env, "Lstd/core/RuntimeException;", "GenerateRandomUUID failed", "Lstd/core/String;:V");
56 return std::string();
57 }
58 std::stringstream res;
59 res << uuidStr.data();
60
61 return res.str();
62 }
63
64 extern "C" {
ETSApiUtilHelperGenerateRandomUUID(ani_env * env,ani_class klass,ani_boolean entropyCache)65 ANI_EXPORT ani_string ETSApiUtilHelperGenerateRandomUUID(ani_env *env, [[maybe_unused]] ani_class klass,
66 ani_boolean entropyCache)
67 {
68 static std::string lastGeneratedUUID;
69 if (entropyCache != ANI_TRUE || lastGeneratedUUID.empty()) {
70 lastGeneratedUUID = GenUuid4(env);
71 }
72 return stdlib::CreateUtf8String(env, lastGeneratedUUID.data(), lastGeneratedUUID.size());
73 }
74 } // extern "C"
75
76 } // namespace ark::ets::sdk::util
77