Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: OpenGIS Simple Features Reference Implementation 4 : * Purpose: Implements Open FileGDB OGR driver. 5 : * Author: Even Rouault, <even dot rouault at spatialys.com> 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2022, Even Rouault <even dot rouault at spatialys.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "cpl_port.h" 14 : #include "ogr_openfilegdb.h" 15 : 16 : #include <random> 17 : #include <sstream> 18 : 19 : /************************************************************************/ 20 : /* CPLGettimeofday() */ 21 : /************************************************************************/ 22 : 23 : #if defined(_WIN32) && !defined(__CYGWIN__) 24 : #include <sys/timeb.h> 25 : 26 : namespace 27 : { 28 : struct CPLTimeVal 29 : { 30 : time_t tv_sec; /* seconds */ 31 : long tv_usec; /* and microseconds */ 32 : }; 33 : } // namespace 34 : 35 : static int CPLGettimeofday(struct CPLTimeVal *tp, void * /* timezonep*/) 36 : { 37 : struct _timeb theTime; 38 : 39 : _ftime(&theTime); 40 : tp->tv_sec = static_cast<time_t>(theTime.time); 41 : tp->tv_usec = theTime.millitm * 1000; 42 : return 0; 43 : } 44 : #else 45 : #include <sys/time.h> /* for gettimeofday() */ 46 : #define CPLTimeVal timeval 47 : #define CPLGettimeofday(t, u) gettimeofday(t, u) 48 : #endif 49 : 50 : /***********************************************************************/ 51 : /* OFGDBGenerateUUID() */ 52 : /***********************************************************************/ 53 : 54 : // Probably not the best UUID generator ever. One issue is that mt19937 55 : // uses only a 32-bit seed. 56 : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW 57 1335 : std::string OFGDBGenerateUUID(bool bInit) 58 : { 59 : struct CPLTimeVal tv; 60 1335 : memset(&tv, 0, sizeof(tv)); 61 : static uint32_t nCounter = 0; 62 : const bool bReproducibleUUID = 63 1335 : CPLTestBool(CPLGetConfigOption("OPENFILEGDB_REPRODUCIBLE_UUID", "NO")); 64 : 65 1335 : if (bInit) 66 : { 67 229 : if (bReproducibleUUID) 68 30 : nCounter = 0; 69 229 : return std::string(); 70 : } 71 : 72 1106 : uint32_t nCounterLocal = nCounter; 73 : // From POSIX.1-2001 as an example of an implementation of rand() 74 : // for reproducible output. 75 : // We have to use that rather than relying on std::mt19937 + 76 : // std::uniform_int_distribution since they don't given the same output 77 : // from the same seed on all platforms. 78 4320 : const auto reproducibleRand = [&nCounterLocal]() 79 : { 80 4320 : nCounterLocal = static_cast<uint32_t>( 81 4320 : (static_cast<uint64_t>(nCounterLocal) * 1103515245U + 12345U) & 82 : UINT32_MAX); 83 4320 : return (nCounterLocal / 65536U) % 32768U; 84 1106 : }; 85 : 86 2212 : std::stringstream ss; 87 : 88 : { 89 1106 : if (!bReproducibleUUID) 90 : { 91 962 : CPLGettimeofday(&tv, nullptr); 92 962 : ++nCounter; 93 : } 94 1106 : std::mt19937 gen(nCounter + 95 1106 : static_cast<unsigned>(tv.tv_sec ^ tv.tv_usec)); 96 1106 : std::uniform_int_distribution<> dis(0, 15); 97 : 98 1106 : ss << "{"; 99 1106 : ss << std::hex; 100 9954 : for (int i = 0; i < 8; i++) 101 : { 102 8848 : ss << (bReproducibleUUID ? (reproducibleRand() % 16) : dis(gen)); 103 : } 104 1106 : ss << "-"; 105 5530 : for (int i = 0; i < 4; i++) 106 : { 107 4424 : ss << (bReproducibleUUID ? (reproducibleRand() % 16) : dis(gen)); 108 : } 109 1106 : ss << "-4"; 110 4424 : for (int i = 0; i < 3; i++) 111 : { 112 3318 : ss << (bReproducibleUUID ? (reproducibleRand() % 16) : dis(gen)); 113 : } 114 : } 115 : 116 : { 117 1106 : if (!bReproducibleUUID) 118 : { 119 962 : CPLGettimeofday(&tv, nullptr); 120 962 : ++nCounter; 121 : } 122 1106 : std::mt19937 gen(nCounter + 123 1106 : static_cast<unsigned>(tv.tv_sec ^ tv.tv_usec)); 124 1106 : std::uniform_int_distribution<> dis(0, 15); 125 1106 : std::uniform_int_distribution<> dis2(8, 11); 126 : 127 1106 : ss << "-"; 128 1106 : ss << (bReproducibleUUID ? 8 : dis2(gen)); 129 4424 : for (int i = 0; i < 3; i++) 130 : { 131 3318 : ss << (bReproducibleUUID ? (reproducibleRand() % 16) : dis(gen)); 132 : } 133 1106 : ss << "-"; 134 14378 : for (int i = 0; i < 12; i++) 135 : { 136 13272 : ss << (bReproducibleUUID ? (reproducibleRand() % 16) : dis(gen)); 137 : }; 138 1106 : ss << "}"; 139 : } 140 : 141 1106 : if (bReproducibleUUID) 142 144 : nCounter = nCounterLocal; 143 : 144 1106 : return ss.str(); 145 : }