24#include <boost/random/mersenne_twister.hpp>
25#include <boost/uuid/uuid_generators.hpp>
26#include <boost/uuid/name_generator_sha1.hpp>
27#include <boost/uuid/uuid_io.hpp>
29#if BOOST_VERSION >= 106700
30#include <boost/uuid/entropy_error.hpp>
49static thread_local boost::mt19937
rng;
50static thread_local boost::uuids::basic_random_generator<boost::mt19937>
randomGenerator;
76#if BOOST_VERSION >= 106700
90#if BOOST_VERSION >= 106700
92 catch(
const boost::uuids::entropy_error& )
94 wxLogFatalError(
"A Boost UUID entropy exception was thrown in %s:%s.",
95 __FILE__, __FUNCTION__ );
104 wxASSERT( null == 0 );
111 if( !aString.empty() && aString.length() <= 8
112 && std::all_of( aString.begin(), aString.end(),
113 [](
unsigned char c )
115 return std::isxdigit( c );
121 for( int i = 0; i < 4; i++ )
123 int start = static_cast<int>( aString.length() ) - 8 + i * 2;
126 start = std::max( 0, start );
127 int len = std::max( 0, end - start );
129 std::string octet = aString.substr( start, len );
130 m_uuid.data[i + 12] = strtol( octet.data(), nullptr, 16 );
143#if BOOST_VERSION >= 106700
150#if BOOST_VERSION >= 106700
152 catch(
const boost::uuids::entropy_error& )
154 wxLogFatalError(
"A Boost UUID entropy exception was thrown in %s:%s.",
155 __FILE__, __FUNCTION__ );
170 KIID(
std::string( aString.ToUTF8() ) )
177 static wxString niluuidStr =
niluuid.AsString();
179 if( aCandidate.Length() != niluuidStr.Length() )
182 for( wxChar c : aCandidate )
184 if( c >=
'0' && c <=
'9' )
187 if( c >=
'a' && c <=
'f' )
190 if( c >=
'A' && c <=
'F' )
205 m_uuid.data[12] =
static_cast<uint8_t
>( aTimestamp >> 24 );
206 m_uuid.data[13] =
static_cast<uint8_t
>( aTimestamp >> 16 );
207 m_uuid.data[14] =
static_cast<uint8_t
>( aTimestamp >> 8 );
208 m_uuid.data[15] =
static_cast<uint8_t
>( aTimestamp );
222 ret |=
m_uuid.data[12] << 24;
223 ret |=
m_uuid.data[13] << 16;
224 ret |=
m_uuid.data[14] << 8;
233 return boost::uuids::hash_value(
m_uuid );
240 static const boost::uuids::uuid nsUuid =
stringGenerator(
"8b8b58e2-3d21-4a24-9dcf-42e0f14001a2" );
242 boost::uuids::name_generator_sha1 nameGenerator( nsUuid );
245 id.m_uuid = nameGenerator( aName );
253 std::copy( aBytes.begin(), aBytes.end(),
id.m_uuid.begin() );
266 return boost::uuids::to_string(
m_uuid );
272 return boost::uuids::to_string(
m_uuid );
278 std::array<uint8_t, 16>
result;
304 for(
int i = 15; i >= 0; --i )
318 for(
int i = 0; i < 16; ++i )
332 std::uint64_t h1 = 0xcbf29ce484222325ULL;
333 std::uint64_t h2 = 0x84222325cbf29ce4ULL;
335 for( wxChar c : aName )
337 h1 ^=
static_cast<std::uint64_t
>( c );
338 h1 *= 0x100000001b3ULL;
339 h2 ^=
static_cast<std::uint64_t
>( c ) * 0x9E3779B97F4A7C15ULL;
340 h2 = ( h2 << 13 ) | ( h2 >> 51 );
343 const wxString uuid = wxString::Format(
344 wxS(
"%08x-%04x-%04x-%04x-%012llx" ),
345 static_cast<unsigned>( h1 >> 32 ),
346 static_cast<unsigned>( ( h1 >> 16 ) & 0xffff ),
347 static_cast<unsigned>( h1 & 0xffff ),
348 static_cast<unsigned>( h2 & 0xffff ),
349 static_cast<unsigned long long>( h2 >> 16 ) & 0xffffffffffffULL );
370 for(
const wxString& pathStep : wxSplit( aString,
'/' ) )
372 if( !pathStep.empty() )
373 emplace_back(
KIID( pathStep ) );
383 if( aPath.size() >
copy.size() )
386 for(
size_t i = 0; i < aPath.size(); ++i )
388 if(
copy.at( i ) != aPath.at( i ) )
395 for(
size_t i = aPath.size(); i <
copy.size(); ++i )
396 push_back(
copy.at( i ) );
404 if( aPath.size() > size() )
410 while( !copyThat.empty() )
412 if( *std::prev( copyThis.end() ) != *std::prev( copyThat.end() ) )
427 for(
const KIID& pathStep : *
this )
442 aKIID =
KIID( aJson.get<std::string>() );
bool EndsWith(const KIID_PATH &aPath) const
Test if aPath from the last path towards the first path.
bool MakeRelativeTo(const KIID_PATH &aPath)
wxString AsString() const
static void SeedGenerator(unsigned int aSeed)
Re-initialize the UUID generator with a given seed (for testing or QA purposes)
wxString AsString() const
std::array< uint8_t, 16 > AsBytes() const
static KIID Combine(const KIID &aFirst, const KIID &aSecond)
Creates a deterministic KIID from two input KIIDs by XORing their underlying UUIDs.
boost::uuids::uuid m_uuid
void Increment()
Generates a deterministic replacement for a given ID.
std::string AsStdString() const
wxString AsLegacyTimestampString() const
timestamp_t AsLegacyTimestamp() const
static KIID FromBytes(const std::array< uint8_t, 16 > &aBytes)
static void CreateNilUuids(bool aNil=true)
A performance optimization which disables/enables the generation of pseudo-random UUIDs.
static bool SniffTest(const wxString &aCandidate)
Returns true if a string has the correct formatting to be a KIID.
static KIID FromDeterministicString(const wxString &aName)
Build a deterministic UUID from an arbitrary name string.
static KIID FromName(const std::string &aName)
Return a KIID derived from a name, the same name always gives the same KIID.
void Clone(const KIID &aUUID)
bool IsLegacyTimestamp() const
void ConvertTimestampToUuid()
Change an existing time stamp based UUID into a true UUID.
static boost::uuids::nil_generator nilGenerator
static thread_local boost::uuids::basic_random_generator< boost::mt19937 > randomGenerator
void from_json(const nlohmann::json &aJson, KIID &aKIID)
static thread_local boost::mt19937 rng
static boost::uuids::string_generator stringGenerator
static thread_local bool g_createNilUuids
void to_json(nlohmann::json &aJson, const KIID &aKIID)
KICOMMON_API KIID niluuid
uint32_t timestamp_t
timestamp_t is our type to represent unique IDs for all kinds of elements; historically simply the ti...
wxString result
Test unit parsing edge cases and error handling.