aboutsummaryrefslogtreecommitdiff
path: root/zencore/uid.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2021-08-18 13:03:33 +0200
committerStefan Boberg <[email protected]>2021-08-18 13:03:33 +0200
commitb7d5adf55ccbb0588a62aeacac0c133756729edd (patch)
treea76fac18b44202baa92c5dd6605440880e37891d /zencore/uid.cpp
parentAdded ToNetworkOrder() functions (diff)
downloadzen-b7d5adf55ccbb0588a62aeacac0c133756729edd.tar.xz
zen-b7d5adf55ccbb0588a62aeacac0c133756729edd.zip
Cleaned up ObjectId generation and made it portable
Diffstat (limited to 'zencore/uid.cpp')
-rw-r--r--zencore/uid.cpp102
1 files changed, 16 insertions, 86 deletions
diff --git a/zencore/uid.cpp b/zencore/uid.cpp
index 347333445..b22ac7896 100644
--- a/zencore/uid.cpp
+++ b/zencore/uid.cpp
@@ -2,16 +2,13 @@
#include <zencore/uid.h>
+#include <zencore/endian.h>
#include <zencore/string.h>
-#if _WIN32
-# include <zencore/windows.h>
-# include <bcrypt.h>
-# pragma comment(lib, "bcrypt.lib")
-#endif
-
#include <atomic>
#include <bit>
+#include <chrono>
+#include <random>
#include <set>
#include <unordered_map>
@@ -21,59 +18,10 @@ namespace zen {
//////////////////////////////////////////////////////////////////////////
-template<typename T>
-T
-EndianSwap(T value)
-{
- uint8_t dest[sizeof value];
-
- memcpy(dest, &value, sizeof value);
-
- for (int i = 0; i < sizeof(value); i++)
- {
- uint8_t& other = dest[sizeof(value) - i - 1];
-
- uint8_t temp = dest[i];
- dest[i] = other;
- other = temp;
- }
-
- T ret;
-
- memcpy(&ret, &value, sizeof value);
-
- return ret;
-}
-
-#if _WIN32
-__forceinline uint16_t
-EndianSwap(uint16_t value)
-{
- return _byteswap_ushort(value);
-}
-
-__forceinline uint32_t
-EndianSwap(uint32_t value)
-{
- return _byteswap_ulong(value);
-}
-
-__forceinline uint64_t
-EndianSwap(uint64_t value)
-{
- return _byteswap_uint64(value);
-}
-#endif
-
-//////////////////////////////////////////////////////////////////////////
-
namespace detail {
static bool OidInitialised;
static uint32_t RunId;
static std::atomic_uint32_t Serial;
-
- // Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 - used for Windows impl
- constexpr int64_t kEpochBias = 116'444'736'000'000'000ull;
} // namespace detail
//////////////////////////////////////////////////////////////////////////
@@ -84,48 +32,30 @@ const Oid Oid::Max = {{~0u, ~0u, ~0u}};
void
Oid::Initialize()
{
- using namespace detail;
-
- if (OidInitialised)
- return;
-
- OidInitialised = true;
-
-#if _WIN32
- char rng[8];
- BCryptGenRandom(NULL, (PUCHAR)rng, sizeof rng, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+ if (!detail::OidInitialised)
+ {
+ std::random_device Rng;
+ detail::RunId = Rng();
+ detail::Serial = Rng();
- memcpy(&RunId, &rng[0], sizeof(RunId));
- memcpy((void*)&Serial, &rng[4], sizeof(Serial));
-#else
-# error Must implement Oid::Initialize
-#endif
+ detail::OidInitialised = true;
+ }
}
const Oid&
Oid::Generate()
{
- using namespace detail;
-
- if (!OidInitialised)
+ if (!detail::OidInitialised)
{
Oid::Initialize();
}
-#if _WIN32
- FILETIME filetime;
-
- GetSystemTimeAsFileTime(&filetime); // Time is UTC
-
- uint64_t filetime64;
- memcpy(&filetime64, &filetime, sizeof filetime);
+ 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] = EndianSwap(uint32_t((filetime64 - kEpochBias) / 10'000'000l));
- OidBits[1] = EndianSwap(uint32_t(Serial++));
- OidBits[2] = RunId;
-#else
-# error Must implement Oid::Generate
-#endif
+ OidBits[0] = ToNetworkOrder(uint32_t(Time));
+ OidBits[1] = ToNetworkOrder(uint32_t(++detail::Serial));
+ OidBits[2] = detail::RunId;
return *this;
}