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 1266 : std::string OFGDBGenerateUUID(bool bInit) 58 : { 59 : struct CPLTimeVal tv; 60 1266 : memset(&tv, 0, sizeof(tv)); 61 : static uint32_t nCounter = 0; 62 : const bool bReproducibleUUID = 63 1266 : CPLTestBool(CPLGetConfigOption("OPENFILEGDB_REPRODUCIBLE_UUID", "NO")); 64 : 65 1266 : if (bInit) 66 : { 67 228 : if (bReproducibleUUID) 68 1 : nCounter = 0; 69 228 : return std::string(); 70 : } 71 : 72 1038 : 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 120 : const auto reproducibleRand = [&nCounterLocal]() 79 : { 80 120 : nCounterLocal = nCounterLocal * 1103515245U + 12345U; 81 120 : return (nCounterLocal / 65536U) % 32768U; 82 1038 : }; 83 : 84 2076 : std::stringstream ss; 85 : 86 : { 87 1038 : if (!bReproducibleUUID) 88 : { 89 1034 : CPLGettimeofday(&tv, nullptr); 90 1034 : ++nCounter; 91 : } 92 1038 : std::mt19937 gen(nCounter + 93 1038 : static_cast<unsigned>(tv.tv_sec ^ tv.tv_usec)); 94 1038 : std::uniform_int_distribution<> dis(0, 15); 95 : 96 1038 : ss << "{"; 97 1038 : ss << std::hex; 98 9342 : for (int i = 0; i < 8; i++) 99 : { 100 8304 : ss << (bReproducibleUUID ? (reproducibleRand() % 16) : dis(gen)); 101 : } 102 1038 : ss << "-"; 103 5190 : for (int i = 0; i < 4; i++) 104 : { 105 4152 : ss << (bReproducibleUUID ? (reproducibleRand() % 16) : dis(gen)); 106 : } 107 1038 : ss << "-4"; 108 4152 : for (int i = 0; i < 3; i++) 109 : { 110 3114 : ss << (bReproducibleUUID ? (reproducibleRand() % 16) : dis(gen)); 111 : } 112 : } 113 : 114 : { 115 1038 : if (!bReproducibleUUID) 116 : { 117 1034 : CPLGettimeofday(&tv, nullptr); 118 1034 : ++nCounter; 119 : } 120 1038 : std::mt19937 gen(nCounter + 121 1038 : static_cast<unsigned>(tv.tv_sec ^ tv.tv_usec)); 122 1038 : std::uniform_int_distribution<> dis(0, 15); 123 1038 : std::uniform_int_distribution<> dis2(8, 11); 124 : 125 1038 : ss << "-"; 126 1038 : ss << (bReproducibleUUID ? 8 : dis2(gen)); 127 4152 : for (int i = 0; i < 3; i++) 128 : { 129 3114 : ss << (bReproducibleUUID ? (reproducibleRand() % 16) : dis(gen)); 130 : } 131 1038 : ss << "-"; 132 13494 : for (int i = 0; i < 12; i++) 133 : { 134 12456 : ss << (bReproducibleUUID ? (reproducibleRand() % 16) : dis(gen)); 135 : }; 136 1038 : ss << "}"; 137 : } 138 : 139 1038 : if (bReproducibleUUID) 140 4 : nCounter = nCounterLocal; 141 : 142 1038 : return ss.str(); 143 : }