Add ability to generate a deterministic UUID from a string value

This commit is contained in:
Jason Perkins 2012-12-16 16:41:55 -05:00
parent e4d62bd307
commit b88b606f33
4 changed files with 68 additions and 9 deletions

View File

@ -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],

View File

@ -62,6 +62,7 @@ static const luaL_Reg os_functions[] = {
static const luaL_Reg string_functions[] = {
{ "endswith", string_endswith },
{ "hash", string_hash },
{ NULL, NULL }
};

View File

@ -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
View 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;
}