diff options
author | chai <chaifix@163.com> | 2019-08-14 22:50:43 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2019-08-14 22:50:43 +0800 |
commit | 15740faf9fe9fe4be08965098bbf2947e096aeeb (patch) | |
tree | a730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Utilities/GUID.cpp |
Diffstat (limited to 'Runtime/Utilities/GUID.cpp')
-rw-r--r-- | Runtime/Utilities/GUID.cpp | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/Runtime/Utilities/GUID.cpp b/Runtime/Utilities/GUID.cpp new file mode 100644 index 0000000..9fe4f7f --- /dev/null +++ b/Runtime/Utilities/GUID.cpp @@ -0,0 +1,241 @@ +#include "UnityPrefix.h" +#include "GUID.h" +#include "LogAssert.h" +#include "StaticAssert.h" +#include <string> + +#if UNITY_IPHONE +#include <CoreFoundation/CFUUID.h> +#endif + +#if UNITY_WIN +#include <ObjBase.h> +#endif + +#if UNITY_XENON +#include <comdecl.h> +#include <time.h> +#endif + +using namespace std; + +#if UNITY_ANDROID +#include <fcntl.h> +#include <unistd.h> +#elif UNITY_LINUX || UNITY_BB10 || UNITY_TIZEN +#include <fcntl.h> +#include <sys/time.h> +#endif + +#if UNITY_PS3 +#include <sys/random_number.h> +#endif + +#if UNITY_HAVE_GUID_INIT +void UnityGUID::Init () +{ +#if UNITY_OSX || UNITY_IPHONE + CompileTimeAssert (sizeof (CFUUIDBytes) == 16, "GIUD shoud be 16 bytes"); +#elif UNITY_WIN || UNITY_XENON + CompileTimeAssert (sizeof (GUID) == 16, "GIUD shoud be 16 bytes"); +#endif + + +#if UNITY_OSX || UNITY_IPHONE + + CFUUIDRef myUUID; + myUUID = CFUUIDCreate (kCFAllocatorDefault); + CFUUIDBytes bytes = CFUUIDGetUUIDBytes (myUUID); + memcpy (data, &bytes, sizeof (CFUUIDBytes)); + CFRelease (myUUID); + +#elif UNITY_ANDROID || UNITY_LINUX || UNITY_BB10 || UNITY_TIZEN + + #pragma message("Android GUID/UUID creation NOT tested!") + { + unsigned char bytes[16]; + + struct timeval tv ; + gettimeofday(&tv, 0) ; + int fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) + fd = open("/dev/random", O_RDONLY | O_NONBLOCK) ; + + srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec) ; + + // Crank the random number generator a few times + gettimeofday(&tv, 0) ; + for (int i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) rand() ; + + int n = 16 ; + int lose_counter = 0 ; + unsigned char *cp = (unsigned char *) bytes ; + while (n > 0 && fd != -1) + { + int i = read(fd, cp, n) ; + if (i <= 0) + { + if (lose_counter++ > 16) break ; + continue ; + } + n -= i ; + cp += i ; + lose_counter = 0 ; + } + + if (fd != -1) + close(fd); + + // We do this all the time, but this is the only source of + // randomness if /dev/random/urandom is out to lunch. + for (unsigned int i = 0; i<16; ++i) + bytes[i] ^= (rand() >> 7) & 0xFF ; + + // clock_seq is bytes #8 and #9 + uint16_t clock_seq = (uint16_t(bytes[8]) << 8) + bytes[9] ; + clock_seq = (clock_seq & 0x3FFF) | 0x8000 ; + bytes[8] = clock_seq >> 8 ; + bytes[9] = clock_seq & 0xFF ; + + // time_hi_and_version is bytes #6 and #7 + uint16_t time_hi_and_version = (uint16_t(bytes[6]) << 8) + bytes[7] ; + time_hi_and_version = (time_hi_and_version & 0x0FFF) | 0x4000 ; + bytes[6] = time_hi_and_version >> 8 ; + bytes[7] = time_hi_and_version & 0xFF ; + + memcpy (data, &bytes, sizeof (data)); + } +#elif UNITY_WIN + + GUID guid; + ::CoCreateGuid( &guid ); + memcpy( data, &guid, sizeof(guid) ); + +#elif UNITY_PS3 + + sys_get_random_number( &data, sizeof(UnityGUID) ); + +#elif UNITY_XENON + + // RFC 4122, section 4.4 (Algorithms for Creating a UUID from Truly Random or Pseudo-Random Numbers) + // http://www.ietf.org/rfc/rfc4122.txt + GUID guid; + unsigned char* bytes = (unsigned char*)&guid; + + srand( time(NULL) ); + for (unsigned int i = 0; i<16; ++i) + bytes[i] ^= (rand() >> 7) & 0xFF; + + // V4 + guid.Data3 &= 0x0fff; + guid.Data3 |= (4 << 12); + guid.Data4[0] &= 0x3f; + guid.Data4[0] |= 0x80; + + memcpy( data, &guid, sizeof(guid) ); + +#else + + ErrorString("GUID::Init() not implemented."); + +#endif +} +#endif + +bool CompareGUIDStringLess (const UnityGUID& lhsGUID, const UnityGUID& rhsGUID) +{ + char lhs[32]; + char rhs[32]; + GUIDToString(lhsGUID, lhs); + GUIDToString(rhsGUID, rhs); + + for (int i=0;i<32;i++) + { + if (lhs[i] != rhs[i]) + return lhs[i] < rhs[i]; + } + + return false; +} + +const char kHexToLiteral[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + +string GUIDToString(const UnityGUID& guid) +{ + char name[kGUIDStringLength+1]; + GUIDToString (guid, name); + name[kGUIDStringLength] = '\0'; + return name; +} + +void GUIDToString(const UnityGUID& guid, char* name) +{ + for (int i=0;i<4;i++) + { + for (int j=8;j--;) + { + UInt32 cur = guid.data[i]; + cur >>= (j * 4); + cur &= 0xF; + name[i * 8 + j] = kHexToLiteral[cur]; + } + } +} + +UnityGUID StringToGUID (const std::string& guidString) +{ + return StringToGUID(guidString.c_str(), guidString.size()); +} + +UnityGUID StringToGUID (const char* guidString, size_t length) +{ + if (length != kGUIDStringLength) + return UnityGUID (); + + // Initialize hex char to int table + static char s_LiteralToHex[255]; + static bool s_IsInitialized = false; + if (!s_IsInitialized) + { + for (int i=0;i<255;i++) + s_LiteralToHex[i] = -1; + s_LiteralToHex['0'] = 0; + s_LiteralToHex['1'] = 1; + s_LiteralToHex['2'] = 2; + s_LiteralToHex['3'] = 3; + s_LiteralToHex['4'] = 4; + s_LiteralToHex['5'] = 5; + s_LiteralToHex['6'] = 6; + s_LiteralToHex['7'] = 7; + s_LiteralToHex['8'] = 8; + s_LiteralToHex['9'] = 9; + s_LiteralToHex['a'] = 10; + s_LiteralToHex['b'] = 11; + s_LiteralToHex['c'] = 12; + s_LiteralToHex['d'] = 13; + s_LiteralToHex['e'] = 14; + s_LiteralToHex['f'] = 15; + s_IsInitialized = true; + } + + // Convert every hex char into an int [0...16] + int hex[kGUIDStringLength]; + for (int i=0;i<kGUIDStringLength;i++) + hex[i] = s_LiteralToHex[guidString[i]]; + + UnityGUID guid; + for (int i=0;i<4;i++) + { + UInt32 cur = 0; + for (int j=8;j--;) + { + int curHex = hex[i * 8 + j]; + if (curHex == -1) + return UnityGUID (); + + cur |= (curHex << (j * 4)); + } + guid.data[i] = cur; + } + return guid; +} |