shada: Do not copy history entries when writing

This commit is contained in:
ZyX 2015-07-19 16:08:19 +03:00
parent 5e7a7fc2da
commit 4bc053facd

View File

@ -258,6 +258,7 @@ struct hm_llist_entry;
/// One entry in sized linked list /// One entry in sized linked list
typedef struct hm_llist_entry { typedef struct hm_llist_entry {
ShadaEntry data; ///< Entry data. ShadaEntry data; ///< Entry data.
bool can_free_entry; ///< True if data can be freed.
struct hm_llist_entry *next; ///< Pointer to next entry or NULL. struct hm_llist_entry *next; ///< Pointer to next entry or NULL.
struct hm_llist_entry *prev; ///< Pointer to previous entry or NULL. struct hm_llist_entry *prev; ///< Pointer to previous entry or NULL.
} HMLListEntry; } HMLListEntry;
@ -384,19 +385,23 @@ static inline void hmll_remove(HMLList *const hmll,
hmll_entry->prev->next = hmll_entry->next; hmll_entry->prev->next = hmll_entry->next;
} }
hmll->num_entries--; hmll->num_entries--;
if (hmll_entry->can_free_entry) {
shada_free_shada_entry(&hmll_entry->data); shada_free_shada_entry(&hmll_entry->data);
} }
}
/// Insert entry to the linked list /// Insert entry to the linked list
/// ///
/// @param[out] hmll List to insert to. /// @param[out] hmll List to insert to.
/// @param[in] hmll_entry Entry to insert after or NULL if it is needed to /// @param[in] hmll_entry Entry to insert after or NULL if it is needed
/// insert at the first entry. /// to insert at the first entry.
/// @param[in] data Data to insert. /// @param[in] data Data to insert.
/// @param[in] can_free_entry True if data can be freed.
static inline void hmll_insert(HMLList *const hmll, static inline void hmll_insert(HMLList *const hmll,
HMLListEntry *hmll_entry, HMLListEntry *hmll_entry,
const ShadaEntry data) const ShadaEntry data,
const bool can_free_entry)
FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_ARG(1)
{ {
if (hmll->num_entries == hmll->size) { if (hmll->num_entries == hmll->size) {
@ -414,6 +419,7 @@ static inline void hmll_insert(HMLList *const hmll,
target_entry = hmll->free_entries[--hmll->free_entries_size]; target_entry = hmll->free_entries[--hmll->free_entries_size];
} }
target_entry->data = data; target_entry->data = data;
target_entry->can_free_entry = can_free_entry;
hmll->num_entries++; hmll->num_entries++;
target_entry->prev = hmll_entry; target_entry->prev = hmll_entry;
if (hmll_entry == NULL) { if (hmll_entry == NULL) {
@ -725,7 +731,13 @@ int shada_read_file(const char *const file, const int flags)
/// Wrapper for hist_iter() function which produces ShadaEntry values /// Wrapper for hist_iter() function which produces ShadaEntry values
/// ///
/// @warning Zeroes original items in process. /// @param[in] iter Current iteration state.
/// @param[in] history_type Type of the history (HIST_*).
/// @param[in] zero If true, then item is removed from instance
/// memory upon reading.
/// @param[out] hist Location where iteration results should be saved.
///
/// @return Next iteration state.
static const void *shada_hist_iter(const void *const iter, static const void *shada_hist_iter(const void *const iter,
const uint8_t history_type, const uint8_t history_type,
const bool zero, const bool zero,
@ -752,18 +764,6 @@ static const void *shada_hist_iter(const void *const iter,
} }
} }
}; };
if (!zero) {
hist->data.history_item.string = xstrdup(hist->data.history_item.string);
if (hist->data.history_item.additional_elements != NULL) {
Object new_array = copy_object(
ARRAY_OBJ(*hist->data.history_item.additional_elements));
hist->data.history_item.additional_elements = xmalloc(
sizeof(*hist->data.history_item.additional_elements));
memcpy(hist->data.history_item.additional_elements,
&new_array.data.array,
sizeof(*hist->data.history_item.additional_elements));
}
}
} }
return ret; return ret;
} }
@ -779,10 +779,11 @@ static const void *shada_hist_iter(const void *const iter,
/// ///
/// @param[in,out] hms_p Ring buffer and associated structures. /// @param[in,out] hms_p Ring buffer and associated structures.
/// @param[in] entry Inserted entry. /// @param[in] entry Inserted entry.
/// @param[in] do_iter Determines whether NeoVim own history should be /// @param[in] do_iter Determines whether NeoVim own history should
/// used. /// be used.
/// @param[in] can_free_entry True if entry can be freed.
static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry, static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry,
const bool no_iter) const bool no_iter, const bool can_free_entry)
{ {
HMLList *const hmll = &hms_p->hmll; HMLList *const hmll = &hms_p->hmll;
HMLL_FORALL(hmll, cur_entry) { HMLL_FORALL(hmll, cur_entry) {
@ -799,14 +800,14 @@ static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry,
if (hms_p->iter == NULL) { if (hms_p->iter == NULL) {
if (hms_p->last_hist_entry.type != kSDItemMissing if (hms_p->last_hist_entry.type != kSDItemMissing
&& hms_p->last_hist_entry.timestamp < entry.timestamp) { && hms_p->last_hist_entry.timestamp < entry.timestamp) {
hms_insert(hms_p, hms_p->last_hist_entry, false); hms_insert(hms_p, hms_p->last_hist_entry, false, hms_p->reading);
hms_p->last_hist_entry.type = kSDItemMissing; hms_p->last_hist_entry.type = kSDItemMissing;
} }
} else { } else {
while (hms_p->iter != NULL while (hms_p->iter != NULL
&& hms_p->last_hist_entry.type != kSDItemMissing && hms_p->last_hist_entry.type != kSDItemMissing
&& hms_p->last_hist_entry.timestamp < entry.timestamp) { && hms_p->last_hist_entry.timestamp < entry.timestamp) {
hms_insert(hms_p, hms_p->last_hist_entry, false); hms_insert(hms_p, hms_p->last_hist_entry, false, hms_p->reading);
hms_p->iter = shada_hist_iter(hms_p->iter, hms_p->history_type, hms_p->iter = shada_hist_iter(hms_p->iter, hms_p->history_type,
hms_p->reading, hms_p->reading,
&(hms_p->last_hist_entry)); &(hms_p->last_hist_entry));
@ -819,7 +820,7 @@ static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry,
break; break;
} }
} }
hmll_insert(hmll, insert_after, entry); hmll_insert(hmll, insert_after, entry, can_free_entry);
} }
/// Initialize the history merger /// Initialize the history merger
@ -854,14 +855,14 @@ static inline void hms_insert_whole_neovim_history(
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
if (hms_p->last_hist_entry.type != kSDItemMissing) { if (hms_p->last_hist_entry.type != kSDItemMissing) {
hms_insert(hms_p, hms_p->last_hist_entry, false); hms_insert(hms_p, hms_p->last_hist_entry, false, hms_p->reading);
} }
while (hms_p->iter != NULL while (hms_p->iter != NULL
&& hms_p->last_hist_entry.type != kSDItemMissing) { && hms_p->last_hist_entry.type != kSDItemMissing) {
hms_p->iter = shada_hist_iter(hms_p->iter, hms_p->history_type, hms_p->iter = shada_hist_iter(hms_p->iter, hms_p->history_type,
hms_p->reading, hms_p->reading,
&(hms_p->last_hist_entry)); &(hms_p->last_hist_entry));
hms_insert(hms_p, hms_p->last_hist_entry, false); hms_insert(hms_p, hms_p->last_hist_entry, false, hms_p->reading);
} }
} }
@ -1077,7 +1078,8 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
shada_free_shada_entry(&cur_entry); shada_free_shada_entry(&cur_entry);
break; break;
} }
hms_insert(hms + cur_entry.data.history_item.histtype, cur_entry, true); hms_insert(hms + cur_entry.data.history_item.histtype, cur_entry, true,
true);
// Do not free shada entry: its allocated memory was saved above. // Do not free shada entry: its allocated memory was saved above.
break; break;
} }