aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/uid.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2023-05-02 10:01:47 +0200
committerGitHub <[email protected]>2023-05-02 10:01:47 +0200
commit075d17f8ada47e990fe94606c3d21df409223465 (patch)
treee50549b766a2f3c354798a54ff73404217b4c9af /src/zencore/uid.cpp
parentfix: bundle shouldn't append content zip to zen (diff)
downloadzen-075d17f8ada47e990fe94606c3d21df409223465.tar.xz
zen-075d17f8ada47e990fe94606c3d21df409223465.zip
moved source directories into `/src` (#264)
* moved source directories into `/src` * updated bundle.lua for new `src` path * moved some docs, icon * removed old test trees
Diffstat (limited to 'src/zencore/uid.cpp')
-rw-r--r--src/zencore/uid.cpp148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/zencore/uid.cpp b/src/zencore/uid.cpp
new file mode 100644
index 000000000..86cdfae3a
--- /dev/null
+++ b/src/zencore/uid.cpp
@@ -0,0 +1,148 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#include <zencore/uid.h>
+
+#include <zencore/endian.h>
+#include <zencore/string.h>
+#include <zencore/testing.h>
+
+#include <atomic>
+#include <bit>
+#include <chrono>
+#include <random>
+#include <set>
+#include <unordered_map>
+
+namespace zen {
+
+//////////////////////////////////////////////////////////////////////////
+
+namespace detail {
+ static bool OidInitialised;
+ static uint32_t RunId;
+ static std::atomic_uint32_t Serial;
+} // namespace detail
+
+//////////////////////////////////////////////////////////////////////////
+
+const Oid Oid::Zero = {{0u, 0u, 0u}};
+const Oid Oid::Max = {{~0u, ~0u, ~0u}};
+
+void
+Oid::Initialize()
+{
+ if (!detail::OidInitialised)
+ {
+ std::random_device Rng;
+ detail::RunId = Rng();
+ detail::Serial = Rng();
+
+ detail::OidInitialised = true;
+ }
+}
+
+const Oid&
+Oid::Generate()
+{
+ if (!detail::OidInitialised)
+ {
+ Oid::Initialize();
+ }
+
+ const uint64_t kOffset = 1'609'459'200; // Seconds from 1970 -> 2021
+ const uint64_t Time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) - kOffset;
+
+ OidBits[0] = ToNetworkOrder(uint32_t(Time));
+ OidBits[1] = ToNetworkOrder(uint32_t(++detail::Serial));
+ OidBits[2] = detail::RunId;
+
+ return *this;
+}
+
+Oid
+Oid::NewOid()
+{
+ return Oid().Generate();
+}
+
+Oid
+Oid::FromHexString(const std::string_view String)
+{
+ ZEN_ASSERT(String.size() == 2 * sizeof(Oid::OidBits));
+
+ Oid Id;
+
+ if (ParseHexBytes(String.data(), String.size(), reinterpret_cast<uint8_t*>(Id.OidBits)))
+ {
+ return Id;
+ }
+ else
+ {
+ return Oid::Zero;
+ }
+}
+
+Oid
+Oid::FromMemory(const void* Ptr)
+{
+ Oid Id;
+ memcpy(Id.OidBits, Ptr, sizeof Id);
+ return Id;
+}
+
+void
+Oid::ToString(char OutString[StringLength])
+{
+ ToHexBytes(reinterpret_cast<const uint8_t*>(OidBits), sizeof(Oid::OidBits), OutString);
+}
+
+StringBuilderBase&
+Oid::ToString(StringBuilderBase& OutString) const
+{
+ String_t Str;
+ ToHexBytes(reinterpret_cast<const uint8_t*>(OidBits), sizeof(Oid::OidBits), Str);
+
+ OutString.AppendRange(Str, &Str[StringLength]);
+
+ return OutString;
+}
+
+#if ZEN_WITH_TESTS
+
+TEST_CASE("Oid")
+{
+ SUBCASE("Basic")
+ {
+ Oid id1 = Oid::NewOid();
+ ZEN_UNUSED(id1);
+
+ std::vector<Oid> ids;
+ std::set<Oid> idset;
+ std::unordered_map<Oid, int, Oid::Hasher> idmap;
+
+ const int Count = 1000;
+
+ for (int i = 0; i < Count; ++i)
+ {
+ Oid id;
+ id.Generate();
+
+ ids.emplace_back(id);
+ idset.insert(id);
+ idmap.insert({id, i});
+ }
+
+ CHECK(ids.size() == Count);
+ CHECK(idset.size() == Count); // All ids should be unique
+ CHECK(idmap.size() == Count); // Ditto
+ }
+}
+
+void
+uid_forcelink()
+{
+}
+
+#endif
+
+} // namespace zen