diff options
-rw-r--r-- | src/nvim/eval.c | 2 | ||||
-rw-r--r-- | src/nvim/globals.h | 4 | ||||
-rw-r--r-- | src/nvim/hashtab.c | 12 | ||||
-rw-r--r-- | src/nvim/hashtab.h | 9 | ||||
-rw-r--r-- | test/unit/eval/helpers.lua | 31 |
5 files changed, 45 insertions, 13 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index f355b3eac4..a96cc82260 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6445,7 +6445,7 @@ void dict_free(dict_T *d) { */ dictitem_T *dictitem_alloc(char_u *key) FUNC_ATTR_NONNULL_RET { - dictitem_T *di = xmalloc(sizeof(dictitem_T) + STRLEN(key)); + dictitem_T *di = xmalloc(offsetof(dictitem_T, di_key) + STRLEN(key) + 1); #ifndef __clang_analyzer__ STRCPY(di->di_key, key); #endif diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 872ff8d5b8..2b9abb1cc5 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -409,10 +409,6 @@ EXTERN struct caller_scope { } provider_caller_scope; EXTERN int provider_call_nesting INIT(= 0); -/* Magic number used for hashitem "hi_key" value indicating a deleted item. - * Only the address is used. */ -EXTERN char_u hash_removed; - EXTERN int t_colors INIT(= 256); // int value of T_CCO diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c index fa4077f22f..376f33e23e 100644 --- a/src/nvim/hashtab.c +++ b/src/nvim/hashtab.c @@ -36,6 +36,8 @@ # include "hashtab.c.generated.h" #endif +char hash_removed; + /// Initialize an empty hash table. void hash_init(hashtab_T *ht) { @@ -380,3 +382,13 @@ hash_T hash_hash(char_u *key) return hash; } + +/// Function to get HI_KEY_REMOVED value +/// +/// Used for testing because luajit ffi does not allow getting addresses of +/// globals. +const char_u *_hash_key_removed(void) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + return HI_KEY_REMOVED; +} diff --git a/src/nvim/hashtab.h b/src/nvim/hashtab.h index 7233d8c47c..0da2b13f2e 100644 --- a/src/nvim/hashtab.h +++ b/src/nvim/hashtab.h @@ -5,14 +5,19 @@ #include "nvim/types.h" +/// Magic number used for hashitem "hi_key" value indicating a deleted item +/// +/// Only the address is used. +extern char hash_removed; + /// Type for hash number (hash calculation result). typedef size_t hash_T; /// The address of "hash_removed" is used as a magic number /// for hi_key to indicate a removed item. -#define HI_KEY_REMOVED &hash_removed +#define HI_KEY_REMOVED ((char_u *)&hash_removed) #define HASHITEM_EMPTY(hi) ((hi)->hi_key == NULL \ - || (hi)->hi_key == &hash_removed) + || (hi)->hi_key == (char_u *)&hash_removed) /// A hastable item. /// diff --git a/test/unit/eval/helpers.lua b/test/unit/eval/helpers.lua index 1feeb5c4f7..c3c27e4fed 100644 --- a/test/unit/eval/helpers.lua +++ b/test/unit/eval/helpers.lua @@ -5,7 +5,8 @@ local to_cstr = helpers.to_cstr local ffi = helpers.ffi local eq = helpers.eq -local eval = cimport('./src/nvim/eval.h', './src/nvim/eval_defs.h') +local eval = cimport('./src/nvim/eval.h', './src/nvim/eval_defs.h', + './src/nvim/hashtab.h') local null_string = {[true]='NULL string'} local null_list = {[true]='NULL list'} @@ -168,7 +169,9 @@ lst2tbl = function(l, processed) return ret end -local function dict_iter(d) +local hi_key_removed = eval._hash_key_removed() + +local function dict_iter(d, return_hi) local init_s = { todo=d.dv_hashtab.ht_used, hi=d.dv_hashtab.ht_array, @@ -176,13 +179,18 @@ local function dict_iter(d) local function f(s, _) if s.todo == 0 then return nil end while s.todo > 0 do - if s.hi.hi_key ~= nil and s.hi ~= eval.hash_removed then + if s.hi.hi_key ~= nil and s.hi.hi_key ~= hi_key_removed then local key = ffi.string(s.hi.hi_key) - local di = ffi.cast('dictitem_T*', - s.hi.hi_key - ffi.offsetof('dictitem_T', 'di_key')) + local ret + if return_hi then + ret = s.hi + else + ret = ffi.cast('dictitem_T*', + s.hi.hi_key - ffi.offsetof('dictitem_T', 'di_key')) + end s.todo = s.todo - 1 s.hi = s.hi + 1 - return key, di + return key, ret end s.hi = s.hi + 1 end @@ -195,6 +203,16 @@ local function first_di(d) return select(2, f(init_s, v)) end +local function dict_items(d) + local ret = {[0]=0} + for k, hi in dict_iter(d) do + ret[k] = hi + ret[0] = ret[0] + 1 + ret[ret[0]] = hi + end + return ret +end + dct2tbl = function(d, processed) if d == nil then return null_dict @@ -395,4 +413,5 @@ return { alloc_logging_helpers=alloc_logging_helpers, list_items=list_items, + dict_items=dict_items, } |