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,  }  | 
