Add ability to generate a deterministic UUID from a string value
This commit is contained in:
parent
e4d62bd307
commit
b88b606f33
@ -5,27 +5,48 @@
|
||||
*/
|
||||
|
||||
#include "premake.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#include <Objbase.h>
|
||||
#endif
|
||||
|
||||
int os_uuid(lua_State* L)
|
||||
{
|
||||
unsigned char bytes[16];
|
||||
char uuid[38];
|
||||
uint32_t buffer[4];
|
||||
uint8_t* bytes = (uint8_t*)buffer;
|
||||
|
||||
/* If a name argument is supplied, build the UUID from that. For speed we
|
||||
* are using a simple DBJ2 hashing function; if this isn't sufficient we
|
||||
* can switch to a full RFC 4122 §4.3 implementation later. */
|
||||
const char* name = luaL_optstring(L, 1, NULL);
|
||||
if (name != NULL)
|
||||
{
|
||||
buffer[0] = do_hash(name, 0);
|
||||
buffer[1] = do_hash(name, 'L');
|
||||
buffer[2] = do_hash(name, 'u');
|
||||
buffer[3] = do_hash(name, 'a');
|
||||
}
|
||||
|
||||
/* If no name is supplied, try to build one properly */
|
||||
else
|
||||
{
|
||||
#if PLATFORM_WINDOWS
|
||||
CoCreateGuid((GUID*)bytes);
|
||||
CoCreateGuid((GUID*)buffer);
|
||||
#else
|
||||
int result;
|
||||
|
||||
/* not sure how to get a UUID here, so I fake it */
|
||||
FILE* rnd = fopen("/dev/urandom", "rb");
|
||||
result = fread(bytes, 16, 1, rnd);
|
||||
result = fread(buffer, 16, 1, rnd);
|
||||
fclose(rnd);
|
||||
if (!result)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
sprintf(uuid, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
bytes[0], bytes[1], bytes[2], bytes[3],
|
||||
|
@ -62,6 +62,7 @@ static const luaL_Reg os_functions[] = {
|
||||
|
||||
static const luaL_Reg string_functions[] = {
|
||||
{ "endswith", string_endswith },
|
||||
{ "hash", string_hash },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -47,6 +47,7 @@
|
||||
|
||||
|
||||
/* Bootstrapping helper functions */
|
||||
unsigned long do_hash(const char* str, int seed);
|
||||
int do_isfile(const char* filename);
|
||||
|
||||
|
||||
@ -70,6 +71,7 @@ int os_rmdir(lua_State* L);
|
||||
int os_stat(lua_State* L);
|
||||
int os_uuid(lua_State* L);
|
||||
int string_endswith(lua_State* L);
|
||||
int string_hash(lua_State* L);
|
||||
|
||||
/* Engine interface */
|
||||
int premake_init(lua_State* L);
|
||||
|
35
src/host/string_hash.c
Normal file
35
src/host/string_hash.c
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* \file string_hash.c
|
||||
* \brief Computes a hash value for a string.
|
||||
* \author Copyright (c) 2012 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include "premake.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
int string_hash(lua_State* L)
|
||||
{
|
||||
const char* str = luaL_checkstring(L, 1);
|
||||
lua_pushnumber(L, do_hash(str, 0));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
unsigned long do_hash(const char* str, int seed)
|
||||
{
|
||||
/* DJB2 hashing; see http://www.cse.yorku.ca/~oz/hash.html */
|
||||
|
||||
unsigned long hash = 5381;
|
||||
|
||||
if (seed != 0) {
|
||||
hash = hash * 33 + seed;
|
||||
}
|
||||
|
||||
while (*str) {
|
||||
hash = hash * 33 + (*str);
|
||||
str++;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
Loading…
Reference in New Issue
Block a user