diff --git a/.clang-format b/.clang-format index 927dad4..1edc97c 100644 --- a/.clang-format +++ b/.clang-format @@ -15,3 +15,4 @@ AlignConsecutiveDeclarations: AlignFunctionPointers: false PadOperators: false AlignConsecutiveMacros: true +AllowShortCaseLabelsOnASingleLine: true diff --git a/.gitignore b/.gitignore index 1c8bc1f..e0e7234 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.o +*.so .cache .json *.elf diff --git a/lookup3.c b/lookup3.c new file mode 100644 index 0000000..959d7a6 --- /dev/null +++ b/lookup3.c @@ -0,0 +1,63 @@ +#include +#include + +#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) + +// clang-format off +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} + +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} +// clang-format on + +uint32_t lookup3(const void *key, size_t length, uint32_t initval) { + uint32_t a, b, c; + const uint8_t *k; + const uint32_t *data32Bit; + + data32Bit = key; + a = b = c = 0xdeadbeef + (((uint32_t)length) << 2) + initval; + + while (length > 12) { + a += *(data32Bit++); + b += *(data32Bit++); + c += *(data32Bit++); + mix(a, b, c); + length -= 12; + } + + k = (const uint8_t *)data32Bit; + switch (length) { + case 12: c += ((uint32_t)k[11]) << 24; + case 11: c += ((uint32_t)k[10]) << 16; + case 10: c += ((uint32_t)k[9]) << 8; + case 9: c += k[8]; + case 8: b += ((uint32_t)k[7]) << 24; + case 7: b += ((uint32_t)k[6]) << 16; + case 6: b += ((uint32_t)k[5]) << 8; + case 5: b += k[4]; + case 4: a += ((uint32_t)k[3]) << 24; + case 3: a += ((uint32_t)k[2]) << 16; + case 2: a += ((uint32_t)k[1]) << 8; + case 1: a += k[0]; break; + case 0: return c; + } + final(a, b, c); + return c; +} diff --git a/lua_lib/Makefile b/lua_lib/Makefile new file mode 100644 index 0000000..001e6e9 --- /dev/null +++ b/lua_lib/Makefile @@ -0,0 +1,21 @@ +CC ?= gcc +CFLAGS ?= -Wall -O2 -fPIC +LDFLAGS ?= + +TARGET = lookup3.so +SRC = lua_lookup3.c +OBJS = lua_lookup3.o lookup3.o + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) -shared -o $@ $^ $(LDFLAGS) + +lua_lookup3.o: $(SRC) + $(CC) $(CFLAGS) -c -o $@ $< + +lookup3.o: ../lookup3.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + rm -f $(TARGET) $(OBJS) diff --git a/lua_lib/driver.lua b/lua_lib/driver.lua new file mode 100644 index 0000000..84dd76b --- /dev/null +++ b/lua_lib/driver.lua @@ -0,0 +1,2 @@ +local myhash = require "lookup3" +print(myhash.lookup3("hello", 0) % 100) diff --git a/lua_lib/lua_lookup3.c b/lua_lib/lua_lookup3.c new file mode 100644 index 0000000..eaa11cc --- /dev/null +++ b/lua_lib/lua_lookup3.c @@ -0,0 +1,27 @@ +#include +#include +#include + +uint32_t lookup3(const void *key, size_t length, uint32_t initval); + +// Lua wrapper +static int l_lookup3(lua_State *L) { + size_t len; + const char *str = luaL_checklstring(L, 1, &len); // get string + length + uint32_t initval = (uint32_t)luaL_checkinteger(L, 2); // get initval + + uint32_t hash = lookup3(str, len, initval); + + lua_pushinteger(L, hash); // return the hash + return 1; // number of return values +} + +// Module open function +int luaopen_lookup3(lua_State *L) { + lua_newtable(L); + + lua_pushcfunction(L, l_lookup3); + lua_setfield(L, -2, "lookup3"); + + return 1; // return the table +}