Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
GUID.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6#include <cinttypes>
7#include <random>
8
12#include "Stroika/Foundation/DataExchange/DefaultSerializer.h"
14
15#include "GUID.h"
16
17using namespace Stroika::Foundation;
18using namespace Stroika::Foundation::Common;
20
21// Comment this in to turn on aggressive noisy DbgTrace in this module
22//#define USE_NOISY_TRACE_IN_THIS_MODULE_ 1
23
24#define G32 "%8" SCNx32
25#define G16 "%4" SCNx16
26#define G8 "%2" SCNx8
27
28/*
29 ********************************************************************************
30 *********************************** Common::GUID *******************************
31 ********************************************************************************
32 */
33Common::GUID Common::GUID::mk_ (const string& src)
34{
36
37 // Allow on parsing EITHER {} delimited, or not
38 DISABLE_COMPILER_MSC_WARNING_START (4996) // MSVC SILLY WARNING ABOUT USING swscanf_s
39 int nchars = -1;
40 int nFields = ::sscanf (src.c_str (), "{" G32 "-" G16 "-" G16 "-" G8 G8 "-" G8 G8 G8 G8 G8 G8 "}%n", &r.Data1, &r.Data2, &r.Data3,
41 &r.Data4[0], &r.Data4[1], &r.Data4[2], &r.Data4[3], &r.Data4[4], &r.Data4[5], &r.Data4[6], &r.Data4[7], &nchars);
42 if (nFields != 11 || nchars != 38) {
43 nchars = -1;
44 nFields = ::sscanf (src.c_str (), G32 "-" G16 "-" G16 "-" G8 G8 "-" G8 G8 G8 G8 G8 G8 "%n", &r.Data1, &r.Data2, &r.Data3,
45 &r.Data4[0], &r.Data4[1], &r.Data4[2], &r.Data4[3], &r.Data4[4], &r.Data4[5], &r.Data4[6], &r.Data4[7], &nchars);
46 }
47 DISABLE_COMPILER_MSC_WARNING_END (4996) // MSVC SILLY WARNING ABOUT USING swscanf_s
48 if (nFields != 11 and nchars != 36) {
49 static const auto kException_ = DataExchange::BadFormatException{"Badly formatted GUID"sv};
50 Execution::Throw (kException_);
51 }
52 return r;
53}
54
55Common::GUID::GUID (const Memory::BLOB& src)
56{
57 if (src.size () != 16) {
58 static const auto kException_ = DataExchange::BadFormatException{"GUID from BLOB must be 16 bytes"sv};
59 Execution::Throw (kException_);
60 }
61 ::memcpy (this, src.begin (), 16);
62}
63
64Characters::String Common::GUID::ToString () const
65{
66 return "{:08x}-{:04x}-{:04x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}"_f(Data1, Data2, Data3, Data4[0], Data4[1], Data4[2],
67 Data4[3], Data4[4], Data4[5], Data4[6], Data4[7]);
68}
69
70Common::GUID::operator Memory::BLOB () const
71{
72 Assert ((end () - begin ()) == 16);
73 return Memory::BLOB{begin (), end ()};
74}
75
76Common::GUID Common::GUID::GenerateNew () noexcept
77{
78 array<uint8_t, 16> randomData;
79 random_device rd;
80 mt19937 gen{rd ()}; //Standard mersenne_twister_engine seeded with rd()
81 uniform_int_distribution<> uniformDist{0, 255};
82 for (size_t i = 0; i < 16; ++i) {
83 randomData[i] = static_cast<uint8_t> (uniformDist (gen));
84 }
85 return GUID{randomData};
86}
87
88/*
89 ********************************************************************************
90 ************** DataExchange::DefaultSerializer<Common::GUID> *******************
91 ********************************************************************************
92 */
93Memory::BLOB DataExchange::DefaultSerializer<Common::GUID>::operator() (const Common::GUID& arg) const
94{
95 return Memory::BLOB{arg.begin (), arg.end ()};
96}