Skip to content

Commit

Permalink
switched to klib
Browse files Browse the repository at this point in the history
  - slightly better perf
  - slightly better memory footprint
  - handles any key types (not limited to string and numbers anymore)
  - much better iterator (previous one was duplicating memory)
  • Loading branch information
andresy committed Oct 12, 2015
1 parent 735f6cd commit d2bec10
Show file tree
Hide file tree
Showing 133 changed files with 819 additions and 44,461 deletions.
6 changes: 0 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,10 @@ cmake_policy(VERSION 2.8)

set(PKGNAME tds)

include_directories(tommyds/tommyds)

add_library(${PKGNAME} MODULE
"tds_utils.c"
"tds_elem.c"
"tds_hash.c"
"tommyds/tommyds/tommyhashlin.c"
"tommyds/tommyds/tommylist.c"
"tommyds/tommyds/tommyhash.c"
"tommyds/tommyds/tommyarrayof.c"
)

install(TARGETS ${PKGNAME} LIBRARY
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Data structures which do not rely on Lua memory allocator, nor being
limited by Lua garbage collector.

Under the hood, this is a LuaJIT FFI interface to Tommy DS.
Under the hood, this is a LuaJIT FFI interface to [klib](http://attractivechaos.github.io/klib).

## Example

Expand Down
28 changes: 11 additions & 17 deletions cdefs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,38 @@ local ffi = require 'ffi'

ffi.cdef[[

/* elem */
typedef void (*tds_elem_pointer_free_ptrfunc)(void*);
typedef struct tds_elem_ tds_elem;

tds_elem *tds_elem_new(void);
void tds_elem_free(tds_elem *elem);
uint32_t tds_elem_hashkey(tds_elem *elem);
int tds_elem_isequal(tds_elem *elem1, tds_elem *elem2);
void tds_elem_set_number(tds_elem *elem, double num);
void tds_elem_set_string(tds_elem *elem, const char *str, size_t size);
void tds_elem_set_pointer(tds_elem *elem, void *ptr, void (*free)(void*));
double tds_elem_get_number(tds_elem *elem);
const char* tds_elem_get_string(tds_elem *elem);
size_t tds_elem_get_string_size(tds_elem *elem);
void* tds_elem_get_pointer(tds_elem *elem);
typedef void (*tds_elem_pointer_free_ptrfunc)(void*);
tds_elem_pointer_free_ptrfunc tds_elem_get_pointer_free(tds_elem *elem);
char tds_elem_type(tds_elem *elem);
void tds_elem_free_content(tds_elem *elem);

typedef struct tds_hash_object_ tds_hash_object;
tds_hash_object *tds_hash_object_new(void);
tds_elem* tds_hash_object_key(tds_hash_object *obj);
tds_elem* tds_hash_object_value(tds_hash_object *obj);
void tds_hash_object_free(tds_hash_object *obj);

/* hash */
typedef struct tds_hash_ tds_hash;
tds_hash* tds_hash_new();
void tds_hash_insert(tds_hash *hash, tds_hash_object *obj);
tds_hash_object* tds_hash_search_string(tds_hash *hash, const char *str, long size);
tds_hash_object* tds_hash_remove_string(tds_hash *hash, const char *str, long size);
tds_hash_object* tds_hash_search_number(tds_hash *hash, double number);
tds_hash_object* tds_hash_remove_number(tds_hash *hash, double number);
tds_hash_object* tds_hash_search_pointer(tds_hash *hash, void* ptr);
tds_hash_object* tds_hash_remove_pointer(tds_hash *hash, void* ptr);
unsigned long tds_hash_size(tds_hash *hash);
void tds_hash_remove(tds_hash *hash, tds_hash_object *obj);
void tds_hash_insert(tds_hash *hash, tds_elem *key, tds_elem *val);
int tds_hash_search(tds_hash *hash, tds_elem *key, tds_elem *val);
int tds_hash_remove(tds_hash *hash, tds_elem *key);
void tds_hash_retain(tds_hash *hash);
void tds_hash_free(tds_hash* hash);

/* iterator */
typedef struct tds_hash_iterator_ tds_hash_iterator;
tds_hash_iterator* tds_hash_iterator_new(tds_hash* hash);
tds_hash_object* tds_hash_iterator_next(tds_hash_iterator* iterator);
int tds_hash_iterator_next(tds_hash_iterator* iterator, tds_elem *key, tds_elem *val);
void tds_hash_iterator_free(tds_hash_iterator* iterator);

]]
62 changes: 21 additions & 41 deletions hash.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ local tds = require 'tds.env'
local elem = require 'tds.elem'
local C = tds.C

-- hash-independent temporary buffers
local key__ = C.tds_elem_new()
local val__ = C.tds_elem_new()
ffi.gc(key__, C.tds_elem_free)
ffi.gc(val__, C.tds_elem_free)

local hash = {}
local NULL = not jit and ffi.C.NULL or nil

Expand All @@ -16,49 +22,25 @@ function hash.__new()
return self
end

local function findkey(self, lkey)
local obj
if type(lkey) == 'string' then
obj = C.tds_hash_search_string(self, lkey, #lkey)
elseif type(lkey) == 'number' then
obj = C.tds_hash_search_number(self, lkey)
else
error('string or number key expected')
end
return obj
end

function hash:__newindex(lkey, lval)
assert(self)
local obj = findkey(self, lkey)
if obj ~= NULL then
if lval then
local val = C.tds_hash_object_value(obj)
C.tds_elem_free_content(val)
elem.set(val, lval)
else
C.tds_hash_remove(self, obj)
C.tds_hash_object_free(obj)
end
else
if lval then
local obj = C.tds_hash_object_new()
local key = C.tds_hash_object_key(obj)
local val = C.tds_hash_object_value(obj)
elem.set(val, lval)
elem.set(key, lkey)
C.tds_hash_insert(self, obj)
end
assert(lkey, 'hash index is nil')
elem.set(key__, lkey)
if lval then
elem.set(val__, lval)
end
C.tds_hash_insert(self, key__, lval and val__ or NULL)
end

function hash:__index(lkey)
local lval
assert(self)
local obj = findkey(self, lkey)
if obj ~= NULL then
local val = elem.get(C.tds_hash_object_value(obj))
return val
assert(lkey, 'hash index is nil')
elem.set(key__, lkey)
if C.tds_hash_search(self, key__, val__) == 0 then
lval = elem.get(val__)
end
return lval
end

function hash:__len()
Expand All @@ -70,13 +52,11 @@ function hash:__pairs()
assert(self)
local iterator = C.tds_hash_iterator_new(self)
ffi.gc(iterator, C.tds_hash_iterator_free)

return function()
local obj = C.tds_hash_iterator_next(iterator)
if obj ~= NULL then
local key = elem.get(C.tds_hash_object_key(obj))
local val = elem.get(C.tds_hash_object_value(obj))
return key, val
if C.tds_hash_iterator_next(iterator, key__, val__) == 0 then
local lkey = elem.get(key__)
local lval = elem.get(val__)
return lkey, lval
end
end
end
Expand Down
Loading

0 comments on commit d2bec10

Please sign in to comment.