diff options
Diffstat (limited to 'src/nvim/shada.c')
-rw-r--r-- | src/nvim/shada.c | 423 |
1 files changed, 197 insertions, 226 deletions
diff --git a/src/nvim/shada.c b/src/nvim/shada.c index c16f3debf9..e9c23e742f 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include <assert.h> #include <inttypes.h> #include <msgpack/object.h> @@ -16,25 +13,25 @@ #include <uv.h> #include "auto/config.h" -#include "klib/khash.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/buffer.h" #include "nvim/cmdhist.h" #include "nvim/eval.h" #include "nvim/eval/decode.h" #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" -#include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds.h" #include "nvim/ex_docmd.h" #include "nvim/fileio.h" +#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/hashtab.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" +#include "nvim/map_defs.h" #include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memory.h" @@ -43,38 +40,26 @@ #include "nvim/normal.h" #include "nvim/ops.h" #include "nvim/option.h" +#include "nvim/option_vars.h" #include "nvim/os/fileio.h" -#include "nvim/os/fs_defs.h" +#include "nvim/os/fs.h" #include "nvim/os/os.h" #include "nvim/os/time.h" #include "nvim/path.h" -#include "nvim/pos.h" +#include "nvim/pos_defs.h" #include "nvim/regexp.h" #include "nvim/search.h" #include "nvim/shada.h" #include "nvim/strings.h" #include "nvim/version.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #ifdef HAVE_BE64TOH -# define _BSD_SOURCE 1 -# define _DEFAULT_SOURCE 1 +# define _BSD_SOURCE 1 // NOLINT(bugprone-reserved-identifier) +# define _DEFAULT_SOURCE 1 // NOLINT(bugprone-reserved-identifier) # include ENDIAN_INCLUDE_FILE #endif -// Note: when using bufset hash pointers are intentionally casted to uintptr_t -// and not to khint32_t or khint64_t: this way compiler must give a warning -// (-Wconversion) when types change. -#ifdef ARCH_32 -KHASH_SET_INIT_INT(bufset) -#elif defined(ARCH_64) -KHASH_SET_INIT_INT64(bufset) -#else -# error Not a 64- or 32-bit architecture -#endif -KHASH_MAP_INIT_STR(fnamebufs, buf_T *) -KHASH_SET_INIT_STR(strset) - #define SEARCH_KEY_MAGIC "sm" #define SEARCH_KEY_SMARTCASE "sc" #define SEARCH_KEY_HAS_LINE_OFFSET "sl" @@ -305,8 +290,6 @@ typedef struct hm_llist_entry { struct hm_llist_entry *prev; ///< Pointer to previous entry or NULL. } HMLListEntry; -KHASH_MAP_INIT_STR(hmll_entries, HMLListEntry *) - /// Sized linked list structure for history merger typedef struct { HMLListEntry *entries; ///< Pointer to the start of the allocated array of @@ -318,9 +301,8 @@ typedef struct { HMLListEntry *last_free_entry; ///< Last unused element in entries array. size_t size; ///< Number of allocated entries. size_t num_entries; ///< Number of entries already used. - khash_t(hmll_entries) contained_entries; ///< Hash mapping all history entry - ///< strings to corresponding entry - ///< pointers. + PMap(cstr_t) contained_entries; ///< Map all history entry strings to + ///< corresponding entry pointers. } HMLList; typedef struct { @@ -348,8 +330,6 @@ typedef struct { Timestamp greatest_timestamp; ///< Greatest timestamp among marks. } FileMarks; -KHASH_MAP_INIT_STR(file_marks, FileMarks) - /// State structure used by shada_write /// /// Before actually writing most of the data is read to this structure. @@ -363,8 +343,8 @@ typedef struct { PossiblyFreedShadaEntry search_pattern; ///< Last search pattern. PossiblyFreedShadaEntry sub_search_pattern; ///< Last s/ search pattern. PossiblyFreedShadaEntry replacement; ///< Last s// replacement string. - khash_t(strset) dumped_variables; ///< Names of already dumped variables. - khash_t(file_marks) file_marks; ///< All file marks. + Set(cstr_t) dumped_variables; ///< Names of already dumped variables. + PMap(cstr_t) file_marks; ///< All file marks. } WriteMergerState; struct sd_read_def; @@ -504,7 +484,7 @@ static inline void hmll_init(HMLList *const hmll, const size_t size) .free_entry = NULL, .size = size, .num_entries = 0, - .contained_entries = KHASH_EMPTY_TABLE(hmll_entries), + .contained_entries = MAP_INIT, }; hmll->last_free_entry = hmll->entries; } @@ -535,10 +515,10 @@ static inline void hmll_remove(HMLList *const hmll, HMLListEntry *const hmll_ent assert(hmll->free_entry == NULL); hmll->free_entry = hmll_entry; } - const khiter_t k = kh_get(hmll_entries, &hmll->contained_entries, - hmll_entry->data.data.history_item.string); - assert(k != kh_end(&hmll->contained_entries)); - kh_del(hmll_entries, &hmll->contained_entries, k); + ptr_t val = pmap_del(cstr_t)(&hmll->contained_entries, + hmll_entry->data.data.history_item.string, NULL); + assert(val); + (void)val; if (hmll_entry->next == NULL) { hmll->last = hmll_entry->prev; } else { @@ -586,11 +566,11 @@ static inline void hmll_insert(HMLList *const hmll, HMLListEntry *hmll_entry, co } target_entry->data = data; target_entry->can_free_entry = can_free_entry; - int kh_ret; - const khiter_t k = kh_put(hmll_entries, &hmll->contained_entries, - data.data.history_item.string, &kh_ret); - if (kh_ret > 0) { - kh_val(&hmll->contained_entries, k) = target_entry; + bool new_item = false; + ptr_t *val = pmap_put_ref(cstr_t)(&hmll->contained_entries, data.data.history_item.string, + NULL, &new_item); + if (new_item) { + *val = target_entry; } hmll->num_entries++; target_entry->prev = hmll_entry; @@ -614,7 +594,7 @@ static inline void hmll_insert(HMLList *const hmll, HMLListEntry *hmll_entry, co static inline void hmll_dealloc(HMLList *const hmll) FUNC_ATTR_NONNULL_ALL { - kh_dealloc(hmll_entries, &hmll->contained_entries); + map_destroy(cstr_t, &hmll->contained_entries); xfree(hmll->entries); } @@ -771,30 +751,6 @@ static void close_file(void *cookie) } } -/// Check whether buffer is in the given set -/// -/// @param[in] set Set to check within. -/// @param[in] buf Buffer to find. -/// -/// @return true or false. -static inline bool in_bufset(const khash_t(bufset) *const set, const buf_T *buf) - FUNC_ATTR_PURE -{ - return kh_get(bufset, set, (uintptr_t)buf) != kh_end(set); -} - -/// Check whether string is in the given set -/// -/// @param[in] set Set to check within. -/// @param[in] buf Buffer to find. -/// -/// @return true or false. -static inline bool in_strset(const khash_t(strset) *const set, char *str) - FUNC_ATTR_PURE -{ - return kh_get(strset, set, str) != kh_end(set); -} - /// Msgpack callback for writing to ShaDaWriteDef* static int msgpack_sd_writer_write(void *data, const char *buf, size_t len) { @@ -837,7 +793,7 @@ static int shada_read_file(const char *const file, const int flags) if (p_verbose > 1) { verbose_enter(); - smsg(_("Reading ShaDa file \"%s\"%s%s%s%s"), + smsg(0, _("Reading ShaDa file \"%s\"%s%s%s%s"), fname, (flags & kShaDaWantInfo) ? _(" info") : "", (flags & kShaDaWantMarks) ? _(" marks") : "", @@ -930,10 +886,11 @@ static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry, } } HMLList *const hmll = &hms_p->hmll; - const khiter_t k = kh_get(hmll_entries, &hms_p->hmll.contained_entries, - entry.data.history_item.string); - if (k != kh_end(&hmll->contained_entries)) { - HMLListEntry *const existing_entry = kh_val(&hmll->contained_entries, k); + cstr_t *key_alloc = NULL; + ptr_t *val = pmap_ref(cstr_t)(&hms_p->hmll.contained_entries, entry.data.history_item.string, + &key_alloc); + if (val) { + HMLListEntry *const existing_entry = *val; if (entry.timestamp > existing_entry->data.timestamp) { hmll_remove(hmll, existing_entry); } else if (!do_iter && entry.timestamp == existing_entry->data.timestamp) { @@ -944,7 +901,7 @@ static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry, existing_entry->data = entry; existing_entry->can_free_entry = can_free_entry; // Previous key was freed above, as part of freeing the ShaDa entry. - kh_key(&hmll->contained_entries, k) = entry.data.history_item.string; + *key_alloc = entry.data.history_item.string; return; } else { return; @@ -1046,24 +1003,27 @@ static inline void hms_dealloc(HistoryMergerState *const hms_p) /// @param[in] fname File name to find. /// /// @return Pointer to the buffer or NULL. -static buf_T *find_buffer(khash_t(fnamebufs) *const fname_bufs, const char *const fname) +static buf_T *find_buffer(PMap(cstr_t) *const fname_bufs, const char *const fname) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - int kh_ret; - khint_t k = kh_put(fnamebufs, fname_bufs, fname, &kh_ret); - if (!kh_ret) { - return kh_val(fname_bufs, k); + cstr_t *key_alloc = NULL; + bool new_item = false; + buf_T **ref = (buf_T **)pmap_put_ref(cstr_t)(fname_bufs, fname, &key_alloc, &new_item); + if (new_item) { + *key_alloc = xstrdup(fname); + } else { + return *ref; // item already existed (can be a NULL value) } - kh_key(fname_bufs, k) = xstrdup(fname); + FOR_ALL_BUFFERS(buf) { if (buf->b_ffname != NULL) { if (path_fnamecmp(fname, buf->b_ffname) == 0) { - kh_val(fname_bufs, k) = buf; + *ref = buf; return buf; } } } - kh_val(fname_bufs, k) = NULL; + *ref = NULL; return NULL; } @@ -1163,9 +1123,9 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) } } ShadaEntry cur_entry; - khash_t(bufset) cl_bufs = KHASH_EMPTY_TABLE(bufset); - khash_t(fnamebufs) fname_bufs = KHASH_EMPTY_TABLE(fnamebufs); - khash_t(strset) oldfiles_set = KHASH_EMPTY_TABLE(strset); + Set(ptr_t) cl_bufs = SET_INIT; + PMap(cstr_t) fname_bufs = MAP_INIT; + Set(cstr_t) oldfiles_set = SET_INIT; if (get_old_files && (oldfiles_list == NULL || force)) { oldfiles_list = tv_list_alloc(kListLenUnknown); set_vim_var_list(VV_OLDFILES, oldfiles_list); @@ -1307,6 +1267,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) .mark = cur_entry.data.filemark.mark, .fnum = (buf == NULL ? 0 : buf->b_fnum), .timestamp = cur_entry.timestamp, + .view = INIT_FMARKV, .additional_data = cur_entry.data.filemark.additional_data, }, }; @@ -1358,8 +1319,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) break; case kSDItemChange: case kSDItemLocalMark: { - if (get_old_files && !in_strset(&oldfiles_set, - cur_entry.data.filemark.fname)) { + if (get_old_files && !set_has(cstr_t, &oldfiles_set, cur_entry.data.filemark.fname)) { char *fname = cur_entry.data.filemark.fname; if (want_marks) { // Do not bother with allocating memory for the string if already @@ -1367,8 +1327,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) // want_marks is set because this way it may be used for a mark. fname = xstrdup(fname); } - int kh_ret; - (void)kh_put(strset, &oldfiles_set, fname, &kh_ret); + set_put(cstr_t, &oldfiles_set, fname); tv_list_append_allocated_string(oldfiles_list, fname); if (!want_marks) { // Avoid free because this string was already used. @@ -1388,6 +1347,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) .mark = cur_entry.data.filemark.mark, .fnum = 0, .timestamp = cur_entry.timestamp, + .view = INIT_FMARKV, .additional_data = cur_entry.data.filemark.additional_data, }; if (cur_entry.type == kSDItemLocalMark) { @@ -1396,8 +1356,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) break; } } else { - int kh_ret; - (void)kh_put(bufset, &cl_bufs, (uintptr_t)buf, &kh_ret); + set_put(ptr_t, &cl_bufs, buf); #define SDE_TO_FMARK(entry) fm #define AFTERFREE(entry) (entry).data.filemark.fname = NULL #define DUMMY_IDX_ADJ(i) @@ -1435,21 +1394,21 @@ shada_read_main_cycle_end: hms_dealloc(&hms[i]); } } - if (cl_bufs.n_occupied) { + if (cl_bufs.h.n_occupied) { FOR_ALL_TAB_WINDOWS(tp, wp) { (void)tp; - if (in_bufset(&cl_bufs, wp->w_buffer)) { + if (set_has(ptr_t, &cl_bufs, wp->w_buffer)) { wp->w_changelistidx = wp->w_buffer->b_changelistlen; } } } - kh_dealloc(bufset, &cl_bufs); + set_destroy(ptr_t, &cl_bufs); const char *key; - kh_foreach_key(&fname_bufs, key, { - xfree((void *)key); + map_foreach_key(&fname_bufs, key, { + xfree((char *)key); }) - kh_dealloc(fnamebufs, &fname_bufs); - kh_dealloc(strset, &oldfiles_set); + map_destroy(cstr_t, &fname_bufs); + set_destroy(cstr_t, &oldfiles_set); } /// Default shada file location: cached path @@ -1491,7 +1450,7 @@ static char *shada_filename(const char *file) // If shell is not performing them then they should be done in main.c // where arguments are parsed, *not here*. expand_env((char *)file, &(NameBuff[0]), MAXPATHL); - file = (const char *)&(NameBuff[0]); + file = &(NameBuff[0]); } } return xstrdup(file); @@ -1544,13 +1503,13 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, ShadaEntr dict_T *const d = (src); \ if (d != NULL) { \ size_t todo = d->dv_hashtab.ht_used; \ - for (const hashitem_T *hi= d->dv_hashtab.ht_array; todo; hi++) { \ + for (const hashitem_T *hi = d->dv_hashtab.ht_array; todo; hi++) { \ if (!HASHITEM_EMPTY(hi)) { \ todo--; \ dictitem_T *const di = TV_DICT_HI2DI(hi); \ - const size_t key_len = strlen((const char *)hi->hi_key); \ + const size_t key_len = strlen(hi->hi_key); \ msgpack_pack_str(spacker, key_len); \ - msgpack_pack_str_body(spacker, (const char *)hi->hi_key, key_len); \ + msgpack_pack_str_body(spacker, hi->hi_key, key_len); \ if (encode_vim_to_msgpack(spacker, &di->di_tv, \ _("additional data of ShaDa " what)) \ == FAIL) { \ @@ -1603,15 +1562,14 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, ShadaEntr break; } case kSDItemVariable: { - if (entry.data.global_var.value.v_type == VAR_TYPE_BLOB) { + if (entry.data.global_var.value.v_type == VAR_BLOB) { // Strings and Blobs both pack as msgpack BINs; differentiate them by // storing an additional VAR_TYPE_BLOB element alongside Blobs list_T *const list = tv_list_alloc(1); tv_list_append_number(list, VAR_TYPE_BLOB); entry.data.global_var.additional_elements = list; } - const size_t arr_size = 2 + (size_t)( - tv_list_len(entry.data.global_var.additional_elements)); + const size_t arr_size = 2 + (size_t)(tv_list_len(entry.data.global_var.additional_elements)); msgpack_pack_array(spacker, arr_size); const String varname = cstr_as_string(entry.data.global_var.name); PACK_BIN(varname); @@ -1639,24 +1597,24 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, ShadaEntr break; } case kSDItemSearchPattern: { - const size_t map_size = (size_t)( - 1 // Search pattern is always present - + ONE_IF_NOT_DEFAULT(entry, search_pattern.magic) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.is_last_used) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.smartcase) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.has_line_offset) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.place_cursor_at_end) - + ONE_IF_NOT_DEFAULT(entry, - search_pattern.is_substitute_pattern) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.highlighted) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.offset) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.search_backward) - // finally, additional data: - + (size_t)( - entry.data.search_pattern.additional_data - ? entry.data.search_pattern.additional_data->dv_hashtab.ht_used - : 0)); - msgpack_pack_map(spacker, map_size); + size_t entry_map_size = ( + 1 // Search pattern is always present + + ONE_IF_NOT_DEFAULT(entry, search_pattern.magic) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.is_last_used) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.smartcase) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.has_line_offset) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.place_cursor_at_end) + + ONE_IF_NOT_DEFAULT(entry, + search_pattern.is_substitute_pattern) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.highlighted) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.offset) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.search_backward) + // finally, additional data: + + ( + entry.data.search_pattern.additional_data + ? entry.data.search_pattern.additional_data->dv_hashtab.ht_used + : 0)); + msgpack_pack_map(spacker, entry_map_size); PACK_STATIC_STR(SEARCH_KEY_PAT); PACK_BIN(cstr_as_string(entry.data.search_pattern.pat)); PACK_BOOL(entry, SEARCH_KEY_MAGIC, magic); @@ -1680,17 +1638,17 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, ShadaEntr case kSDItemGlobalMark: case kSDItemLocalMark: case kSDItemJump: { - const size_t map_size = (size_t)( - 1 // File name - + ONE_IF_NOT_DEFAULT(entry, filemark.mark.lnum) - + ONE_IF_NOT_DEFAULT(entry, filemark.mark.col) - + ONE_IF_NOT_DEFAULT(entry, filemark.name) - // Additional entries, if any: - + (size_t)( - entry.data.filemark.additional_data == NULL - ? 0 - : entry.data.filemark.additional_data->dv_hashtab.ht_used)); - msgpack_pack_map(spacker, map_size); + size_t entry_map_size = ( + 1 // File name + + ONE_IF_NOT_DEFAULT(entry, filemark.mark.lnum) + + ONE_IF_NOT_DEFAULT(entry, filemark.mark.col) + + ONE_IF_NOT_DEFAULT(entry, filemark.name) + // Additional entries, if any: + + ( + entry.data.filemark.additional_data == NULL + ? 0 + : entry.data.filemark.additional_data->dv_hashtab.ht_used)); + msgpack_pack_map(spacker, entry_map_size); PACK_STATIC_STR(KEY_FILE); PACK_BIN(cstr_as_string(entry.data.filemark.fname)); if (!CHECK_DEFAULT(entry, filemark.mark.lnum)) { @@ -1713,15 +1671,15 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, ShadaEntr break; } case kSDItemRegister: { - const size_t map_size = (size_t)(2 // Register contents and name - + ONE_IF_NOT_DEFAULT(entry, reg.type) - + ONE_IF_NOT_DEFAULT(entry, reg.width) - + ONE_IF_NOT_DEFAULT(entry, reg.is_unnamed) - // Additional entries, if any: - + (size_t)(entry.data.reg.additional_data == NULL - ? 0 - : entry.data.reg.additional_data->dv_hashtab.ht_used)); - msgpack_pack_map(spacker, map_size); + size_t entry_map_size = (2 // Register contents and name + + ONE_IF_NOT_DEFAULT(entry, reg.type) + + ONE_IF_NOT_DEFAULT(entry, reg.width) + + ONE_IF_NOT_DEFAULT(entry, reg.is_unnamed) + // Additional entries, if any: + + (entry.data.reg.additional_data == NULL + ? 0 + : entry.data.reg.additional_data->dv_hashtab.ht_used)); + msgpack_pack_map(spacker, entry_map_size); PACK_STATIC_STR(REG_KEY_CONTENTS); msgpack_pack_array(spacker, entry.data.reg.contents_size); for (size_t i = 0; i < entry.data.reg.contents_size; i++) { @@ -1751,20 +1709,20 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, ShadaEntr case kSDItemBufferList: msgpack_pack_array(spacker, entry.data.buffer_list.size); for (size_t i = 0; i < entry.data.buffer_list.size; i++) { - const size_t map_size = (size_t)( - 1 // Buffer name - + (size_t)(entry.data.buffer_list.buffers[i].pos.lnum - != default_pos.lnum) - + (size_t)(entry.data.buffer_list.buffers[i].pos.col - != default_pos.col) - // Additional entries, if any: - + (size_t)( - entry.data.buffer_list.buffers[i].additional_data - == NULL - ? 0 - : (entry.data.buffer_list.buffers[i].additional_data - ->dv_hashtab.ht_used))); - msgpack_pack_map(spacker, map_size); + size_t entry_map_size = ( + 1 // Buffer name + + (size_t)(entry.data.buffer_list.buffers[i].pos.lnum + != default_pos.lnum) + + (size_t)(entry.data.buffer_list.buffers[i].pos.col + != default_pos.col) + // Additional entries, if any: + + ( + entry.data.buffer_list.buffers[i].additional_data + == NULL + ? 0 + : (entry.data.buffer_list.buffers[i].additional_data + ->dv_hashtab.ht_used))); + msgpack_pack_map(spacker, entry_map_size); PACK_STATIC_STR(KEY_FILE); PACK_BIN(cstr_as_string(entry.data.buffer_list.buffers[i].fname)); if (entry.data.buffer_list.buffers[i].pos.lnum != 1) { @@ -2152,7 +2110,7 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re break; } case kSDItemVariable: - if (!in_strset(&wms->dumped_variables, entry.data.global_var.name)) { + if (!set_has(cstr_t, &wms->dumped_variables, entry.data.global_var.name)) { ret = shada_pack_entry(packer, entry, 0); } shada_free_shada_entry(&entry); @@ -2199,6 +2157,12 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re shada_free_shada_entry(&entry); break; } + if (wms->global_marks[idx].data.type == kSDItemMissing) { + if (namedfm[idx].fmark.timestamp >= entry.timestamp) { + shada_free_shada_entry(&entry); + break; + } + } COMPARE_WITH_ENTRY(&wms->global_marks[idx], entry); } break; @@ -2208,14 +2172,13 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re shada_free_shada_entry(&entry); break; } - const char *const fname = (const char *)entry.data.filemark.fname; - khiter_t k; - int kh_ret; - k = kh_put(file_marks, &wms->file_marks, fname, &kh_ret); - FileMarks *const filemarks = &kh_val(&wms->file_marks, k); - if (kh_ret > 0) { - CLEAR_POINTER(filemarks); + const char *const fname = entry.data.filemark.fname; + cstr_t *key = NULL; + ptr_t *val = pmap_put_ref(cstr_t)(&wms->file_marks, fname, &key, NULL); + if (*val == NULL) { + *val = xcalloc(1, sizeof(FileMarks)); } + FileMarks *const filemarks = *val; if (entry.timestamp > filemarks->greatest_timestamp) { filemarks->greatest_timestamp = entry.timestamp; } @@ -2229,20 +2192,35 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re entry; } else { PossiblyFreedShadaEntry *const wms_entry = &filemarks->marks[idx]; + bool set_wms = true; if (wms_entry->data.type != kSDItemMissing) { if (wms_entry->data.timestamp >= entry.timestamp) { shada_free_shada_entry(&entry); break; } if (wms_entry->can_free_entry) { - if (kh_key(&wms->file_marks, k) - == wms_entry->data.data.filemark.fname) { - kh_key(&wms->file_marks, k) = entry.data.filemark.fname; + if (*key == wms_entry->data.data.filemark.fname) { + *key = entry.data.filemark.fname; } shada_free_shada_entry(&wms_entry->data); } + } else { + FOR_ALL_BUFFERS(buf) { + if (buf->b_ffname != NULL + && path_fnamecmp(entry.data.filemark.fname, buf->b_ffname) == 0) { + fmark_T fm; + mark_get(buf, curwin, &fm, kMarkBufLocal, (int)entry.data.filemark.name); + if (fm.timestamp >= entry.timestamp) { + set_wms = false; + shada_free_shada_entry(&entry); + break; + } + } + } + } + if (set_wms) { + *wms_entry = pfs_entry; } - *wms_entry = pfs_entry; } } else { #define AFTERFREE_DUMMY(entry) @@ -2279,11 +2257,11 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re /// @param[in] removable_bufs Cache of buffers ignored due to their location. /// /// @return true or false. -static inline bool ignore_buf(const buf_T *const buf, khash_t(bufset) *const removable_bufs) +static inline bool ignore_buf(const buf_T *const buf, Set(ptr_t) *const removable_bufs) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE { return (buf->b_ffname == NULL || !buf->b_p_bl || bt_quickfix(buf) \ - || bt_terminal(buf) || in_bufset(removable_bufs, buf)); + || bt_terminal(buf) || set_has(ptr_t, removable_bufs, (ptr_t)buf)); } /// Get list of buffers to write to the shada file @@ -2291,7 +2269,7 @@ static inline bool ignore_buf(const buf_T *const buf, khash_t(bufset) *const rem /// @param[in] removable_bufs Buffers which are ignored /// /// @return ShadaEntry List of buffers to save, kSDItemBufferList entry. -static inline ShadaEntry shada_get_buflist(khash_t(bufset) *const removable_bufs) +static inline ShadaEntry shada_get_buflist(Set(ptr_t) *const removable_bufs) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE { int max_bufs = get_shada_parameter('%'); @@ -2369,8 +2347,8 @@ static inline void add_search_pattern(PossiblyFreedShadaEntry *const ret_pse, : pat.off.line), .place_cursor_at_end = ( is_substitute_pattern - ? defaults.data.search_pattern.place_cursor_at_end - : pat.off.end), + ? defaults.data.search_pattern.place_cursor_at_end + : pat.off.end), .offset = (is_substitute_pattern ? defaults.data.search_pattern.offset : pat.off.off), @@ -2459,12 +2437,11 @@ static inline void replace_numbered_mark(WriteMergerState *const wms, const size /// Find buffers ignored due to their location. /// /// @param[out] removable_bufs Cache of buffers ignored due to their location. -static inline void find_removable_bufs(khash_t(bufset) *removable_bufs) +static inline void find_removable_bufs(Set(ptr_t) *removable_bufs) { FOR_ALL_BUFFERS(buf) { if (buf->b_ffname != NULL && shada_removable(buf->b_ffname)) { - int kh_ret; - (void)kh_put(bufset, removable_bufs, (uintptr_t)buf, &kh_ret); + set_put(ptr_t, removable_bufs, (ptr_t)buf); } } } @@ -2516,7 +2493,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef max_reg_lines = get_shada_parameter('"'); } const bool dump_registers = (max_reg_lines != 0); - khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset); + Set(ptr_t) removable_bufs = SET_INIT; const size_t max_kbyte = (size_t)max_kbyte_i; const size_t num_marked_files = (size_t)get_shada_parameter('\''); const bool dump_global_marks = get_shada_parameter('f') != 0; @@ -2524,9 +2501,9 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef // Initialize history merger for (HistoryType i = 0; i < HIST_COUNT; i++) { - long num_saved = get_shada_parameter(hist_type2char(i)); + int num_saved = get_shada_parameter(hist_type2char(i)); if (num_saved == -1) { - num_saved = p_hi; + num_saved = (int)p_hi; } if (num_saved > 0) { dump_history = true; @@ -2571,15 +2548,15 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef .capacity = 5, .items = ((KeyValuePair[]) { { STATIC_CSTR_AS_STRING("generator"), - STRING_OBJ(STATIC_CSTR_AS_STRING("nvim")) }, + STATIC_CSTR_AS_OBJ("nvim") }, { STATIC_CSTR_AS_STRING("version"), - STRING_OBJ(cstr_as_string(longVersion)) }, + CSTR_AS_OBJ(longVersion) }, { STATIC_CSTR_AS_STRING("max_kbyte"), INTEGER_OBJ((Integer)max_kbyte) }, { STATIC_CSTR_AS_STRING("pid"), INTEGER_OBJ((Integer)os_get_pid()) }, { STATIC_CSTR_AS_STRING("encoding"), - STRING_OBJ(cstr_as_string((char *)p_enc)) }, + CSTR_AS_OBJ(p_enc) }, }), } } @@ -2660,8 +2637,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef tv_clear(&vartv); tv_clear(&tgttv); if (spe_ret == kSDWriteSuccessful) { - int kh_ret; - (void)kh_put(strset, &wms->dumped_variables, name, &kh_ret); + set_put(cstr_t, &wms->dumped_variables, name); } } while (var_iter != NULL); } @@ -2714,17 +2690,17 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef const char *fname; if (fm.fmark.fnum == 0) { assert(fm.fname != NULL); - if (shada_removable((const char *)fm.fname)) { + if (shada_removable(fm.fname)) { continue; } - fname = (const char *)fm.fname; + fname = fm.fname; } else { const buf_T *const buf = buflist_findnr(fm.fmark.fnum); if (buf == NULL || buf->b_ffname == NULL - || in_bufset(&removable_bufs, buf)) { + || set_has(ptr_t, &removable_bufs, (ptr_t)buf)) { continue; } - fname = (const char *)buf->b_ffname; + fname = buf->b_ffname; } const PossiblyFreedShadaEntry pf_entry = { .can_free_entry = false, @@ -2757,18 +2733,16 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef // Initialize buffers if (num_marked_files > 0) { FOR_ALL_BUFFERS(buf) { - if (buf->b_ffname == NULL || in_bufset(&removable_bufs, buf)) { + if (buf->b_ffname == NULL || set_has(ptr_t, &removable_bufs, buf)) { continue; } const void *local_marks_iter = NULL; - const char *const fname = (const char *)buf->b_ffname; - khiter_t k; - int kh_ret; - k = kh_put(file_marks, &wms->file_marks, fname, &kh_ret); - FileMarks *const filemarks = &kh_val(&wms->file_marks, k); - if (kh_ret > 0) { - CLEAR_POINTER(filemarks); + const char *const fname = buf->b_ffname; + ptr_t *val = pmap_put_ref(cstr_t)(&wms->file_marks, fname, NULL, NULL); + if (*val == NULL) { + *val = xcalloc(1, sizeof(FileMarks)); } + FileMarks *const filemarks = *val; do { fmark_T fm; char name = NUL; @@ -2885,16 +2859,14 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef PACK_WMS_ENTRY(wms->replacement); #undef PACK_WMS_ENTRY - const size_t file_markss_size = kh_size(&wms->file_marks); + const size_t file_markss_size = map_size(&wms->file_marks); FileMarks **const all_file_markss = xmalloc(file_markss_size * sizeof(*all_file_markss)); FileMarks **cur_file_marks = all_file_markss; - for (khint_t i = kh_begin(&wms->file_marks); i != kh_end(&wms->file_marks); - i++) { - if (kh_exist(&wms->file_marks, i)) { - *cur_file_marks++ = &kh_val(&wms->file_marks, i); - } - } + ptr_t val; + map_foreach_value(&wms->file_marks, val, { + *cur_file_marks++ = val; + }) qsort((void *)all_file_markss, file_markss_size, sizeof(*all_file_markss), &compare_file_marks); const size_t file_markss_to_dump = MIN(num_marked_files, file_markss_size); @@ -2947,10 +2919,13 @@ shada_write_exit: hms_dealloc(&wms->hms[i]); } } - kh_dealloc(file_marks, &wms->file_marks); - kh_dealloc(bufset, &removable_bufs); + map_foreach_value(&wms->file_marks, val, { + xfree(val); + }) + map_destroy(cstr_t, &wms->file_marks); + set_destroy(ptr_t, &removable_bufs); msgpack_packer_free(packer); - kh_dealloc(strset, &wms->dumped_variables); + set_destroy(cstr_t, &wms->dumped_variables); xfree(wms); return ret; } @@ -3040,7 +3015,7 @@ shada_write_file_nomerge: {} if (!os_isdir(fname)) { int ret; char *failed_dir; - if ((ret = os_mkdir_recurse(fname, 0700, &failed_dir)) != 0) { + if ((ret = os_mkdir_recurse(fname, 0700, &failed_dir, NULL)) != 0) { semsg(_(SERR "Failed to create directory %s " "for writing ShaDa file: %s"), failed_dir, os_strerror(ret)); @@ -3071,7 +3046,7 @@ shada_write_file_nomerge: {} if (p_verbose > 1) { verbose_enter(); - smsg(_("Writing ShaDa file \"%s\""), fname); + smsg(0, _("Writing ShaDa file \"%s\""), fname); verbose_leave(); } @@ -3166,8 +3141,8 @@ int shada_read_everything(const char *const fname, const bool forceit, const boo { return shada_read_file(fname, kShaDaWantInfo|kShaDaWantMarks|kShaDaGetOldfiles - |(forceit?kShaDaForceit:0) - |(missing_ok?0:kShaDaMissingError)); + |(forceit ? kShaDaForceit : 0) + |(missing_ok ? 0 : kShaDaMissingError)); } static void shada_free_shada_entry(ShadaEntry *const entry) @@ -3361,7 +3336,6 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const #define ID(s) s #define BINDUP(b) xmemdupz((b).ptr, (b).size) #define TOINT(s) ((int)(s)) -#define TOLONG(s) ((long)(s)) #define TOCHAR(s) ((char)(s)) #define TOU8(s) ((uint8_t)(s)) #define TOSIZE(s) ((size_t)(s)) @@ -3440,7 +3414,7 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const if (msgpack_to_vim(obj, &adtv) == FAIL \ || adtv.v_type != VAR_DICT) { \ semsg(_(READERR(name, \ - "cannot be converted to a VimL dictionary")), \ + "cannot be converted to a Vimscript dictionary")), \ initial_fpos); \ ga_clear(&ad_ga); \ tv_clear(&adtv); \ @@ -3464,7 +3438,7 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const }; \ typval_T aetv; \ if (msgpack_to_vim(obj, &aetv) == FAIL) { \ - semsg(_(READERR(name, "cannot be converted to a VimL list")), \ + semsg(_(READERR(name, "cannot be converted to a Vimscript list")), \ initial_fpos); \ tv_clear(&aetv); \ goto shada_read_next_item_error; \ @@ -3602,7 +3576,6 @@ shada_read_next_item_start: ret = spm_ret; goto shada_read_next_item_error; } - ret = kSDReadStatusMalformed; entry->data = sd_default_values[type_u64].data; switch ((ShadaEntryType)type_u64) { case kSDItemHeader: @@ -3864,7 +3837,7 @@ shada_read_next_item_start: } else if (msgpack_to_vim(unpacked.data.via.array.ptr[1], &(entry->data.global_var.value)) == FAIL) { semsg(_(READERR("variable", "has value that cannot " - "be converted to the VimL value")), initial_fpos); + "be converted to the Vimscript value")), initial_fpos); goto shada_read_next_item_error; } break; @@ -3921,7 +3894,7 @@ shada_read_next_item_start: // XXX: Temporarily reassign `i` because the macros depend on it. const size_t j = i; { - for (i = 0; i < unpacked_2.data.via.map.size; i++) { // -V535 + for (i = 0; i < unpacked_2.data.via.map.size; i++) { CHECK_KEY_IS_STR(unpacked_2, "buffer list entry") INTEGER_KEY(unpacked_2, "buffer list entry", KEY_LNUM, entry->data.buffer_list.buffers[j].pos.lnum) @@ -3988,7 +3961,6 @@ shada_read_next_item_error: #undef BINDUP #undef TOCHAR #undef TOINT -#undef TOLONG #undef TYPED_KEY #undef INT_KEY #undef INTEGER_KEY @@ -4006,12 +3978,11 @@ shada_read_next_item_error: static bool shada_removable(const char *name) FUNC_ATTR_WARN_UNUSED_RESULT { - char *p; char part[MAXPATHL + 1]; bool retval = false; - char *new_name = home_replace_save(NULL, (char *)name); - for (p = p_shada; *p;) { + char *new_name = home_replace_save(NULL, name); + for (char *p = p_shada; *p;) { (void)copy_option_part(&p, part, ARRAY_SIZE(part), ", "); if (part[0] == 'r') { home_replace(NULL, part + 1, NameBuff, MAXPATHL, true); @@ -4034,7 +4005,7 @@ static bool shada_removable(const char *name) /// /// @return number of jumplist entries static inline size_t shada_init_jumps(PossiblyFreedShadaEntry *jumps, - khash_t(bufset) *const removable_bufs) + Set(ptr_t) *const removable_bufs) { // Initialize jump list size_t jumps_size = 0; @@ -4055,7 +4026,7 @@ static inline size_t shada_init_jumps(PossiblyFreedShadaEntry *jumps, ? NULL : buflist_findnr(fm.fmark.fnum)); if (buf != NULL - ? in_bufset(removable_bufs, buf) + ? set_has(ptr_t, removable_bufs, (ptr_t)buf) : fm.fmark.fnum != 0) { continue; } @@ -4110,7 +4081,7 @@ void shada_encode_regs(msgpack_sbuffer *const sbuf) void shada_encode_jumps(msgpack_sbuffer *const sbuf) FUNC_ATTR_NONNULL_ALL { - khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset); + Set(ptr_t) removable_bufs = SET_INIT; find_removable_bufs(&removable_bufs); PossiblyFreedShadaEntry jumps[JUMPLISTSIZE]; size_t jumps_size = shada_init_jumps(jumps, &removable_bufs); @@ -4129,7 +4100,7 @@ void shada_encode_jumps(msgpack_sbuffer *const sbuf) void shada_encode_buflist(msgpack_sbuffer *const sbuf) FUNC_ATTR_NONNULL_ALL { - khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset); + Set(ptr_t) removable_bufs = SET_INIT; find_removable_bufs(&removable_bufs); ShadaEntry buflist_entry = shada_get_buflist(&removable_bufs); msgpack_packer packer; |