*: Finish hiding list implementation

This commit is contained in:
ZyX
2017-12-11 10:12:59 +03:00
parent ceb45a0885
commit d46e37cb4c
5 changed files with 187 additions and 100 deletions

View File

@@ -153,6 +153,45 @@ list_T *tv_list_alloc(void)
return list;
}
/// Initialize a static list with 10 items
///
/// @param[out] sl Static list to initialize.
void tv_list_init_static10(staticList10_T *const sl)
FUNC_ATTR_NONNULL_ALL
{
#define SL_SIZE ARRAY_SIZE(sl->sl_items)
list_T *const l = &sl->sl_list;
memset(sl, 0, sizeof(staticList10_T));
l->lv_first = &sl->sl_items[0];
l->lv_last = &sl->sl_items[SL_SIZE - 1];
l->lv_refcount = DO_NOT_FREE_CNT;
tv_list_set_lock(l, VAR_FIXED);
sl->sl_list.lv_len = 10;
sl->sl_items[0].li_prev = NULL;
sl->sl_items[0].li_next = &sl->sl_items[1];
sl->sl_items[SL_SIZE - 1].li_prev = &sl->sl_items[SL_SIZE - 2];
sl->sl_items[SL_SIZE - 1].li_next = NULL;
for (size_t i = 1; i < SL_SIZE - 1; i++) {
listitem_T *const li = &sl->sl_items[i];
li->li_prev = li - 1;
li->li_next = li + 1;
}
#undef SL_SIZE
}
/// Initialize static list with undefined number of elements
///
/// @param[out] l List to initialize.
void tv_list_init_static(list_T *const l)
FUNC_ATTR_NONNULL_ALL
{
memset(l, 0, sizeof(*l));
l->lv_refcount = DO_NOT_FREE_CNT;
}
/// Free items contained in a list
///
/// @param[in,out] l List to clear.
@@ -221,7 +260,7 @@ void tv_list_unref(list_T *const l)
//{{{2 Add/remove
/// Remove items "item" to "item2" from list "l".
/// Remove items "item" to "item2" from list "l"
///
/// @warning Does not free the listitem or the value!
///
@@ -251,6 +290,30 @@ void tv_list_remove_items(list_T *const l, listitem_T *const item,
l->lv_idx_item = NULL;
}
/// Move items "item" to "item2" from list "l" to the end of the list "tgt_l"
///
/// @param[out] l List to move from.
/// @param[in] item First item to move.
/// @param[in] item2 Last item to move.
/// @param[out] tgt_l List to move to.
/// @param[in] cnt Number of items moved.
void tv_list_move_items(list_T *const l, listitem_T *const item,
listitem_T *const item2, list_T *const tgt_l,
const int cnt)
FUNC_ATTR_NONNULL_ALL
{
tv_list_remove_items(l, item, item2);
item->li_prev = tgt_l->lv_last;
item2->li_next = NULL;
if (tgt_l->lv_last == NULL) {
tgt_l->lv_first = item;
} else {
tgt_l->lv_last->li_next = item;
}
tgt_l->lv_last = item2;
tgt_l->lv_len += cnt;
}
/// Insert list item
///
/// @param[out] l List to insert to.
@@ -644,6 +707,31 @@ bool tv_list_equal(list_T *const l1, list_T *const l2, const bool ic,
return true;
}
/// Reverse list in-place
///
/// @param[in,out] l List to reverse.
void tv_list_reverse(list_T *const l)
{
if (tv_list_len(l) <= 1) {
return;
}
#define SWAP(a, b) \
do { \
tmp = a; \
a = b; \
b = tmp; \
} while (0)
listitem_T *tmp;
SWAP(l->lv_first, l->lv_last);
for (listitem_T *li = l->lv_first; li != NULL; li = li->li_next) {
SWAP(li->li_next, li->li_prev);
}
#undef SWAP
l->lv_idx = l->lv_len - l->lv_idx - 1;
}
//{{{2 Indexing/searching
/// Locate item with a given index in a list and return it

View File

@@ -7,6 +7,7 @@
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#include <limits.h>
#include "nvim/types.h"
#include "nvim/hashtab.h"
@@ -27,6 +28,9 @@ typedef uint64_t uvarnumber_T;
/// Type used for VimL VAR_FLOAT values
typedef double float_T;
/// Refcount for dict or list that should not be freed
enum { DO_NOT_FREE_CNT = (INT_MAX / 2) };
/// Maximal possible value of varnumber_T variable
#define VARNUMBER_MAX INT64_MAX
#define UVARNUMBER_MAX UINT64_MAX
@@ -151,12 +155,26 @@ struct listvar_S {
list_T *lv_used_prev; ///< Previous list in used lists list.
};
// Static list with 10 items. Use init_static_list() to initialize.
// Static list with 10 items. Use tv_list_init_static10() to initialize.
typedef struct {
list_T sl_list; // must be first
listitem_T sl_items[10];
} staticList10_T;
#define TV_LIST_STATIC10_INIT { \
.sl_list = { \
.lv_first = NULL, \
.lv_last = NULL, \
.lv_refcount = 0, \
.lv_len = 0, \
.lv_watch = NULL, \
.lv_idx_item = NULL, \
.lv_lock = VAR_FIXED, \
.lv_used_next = NULL, \
.lv_used_prev = NULL, \
}, \
}
// Structure to hold an item of a Dictionary.
// Also used for a variable.
// The key is copied into "di_key" to avoid an extra alloc/free for it.
@@ -330,6 +348,19 @@ static inline void tv_list_set_lock(list_T *const l,
l->lv_lock = lock;
}
/// Set list copyID
///
/// Does not expect NULL list, be careful.
///
/// @param[out] l List to modify.
/// @param[in] copyid New copyID.
static inline void tv_list_set_copyid(list_T *const l,
const int copyid)
FUNC_ATTR_NONNULL_ALL
{
l->lv_copyID = copyid;
}
static inline int tv_list_len(const list_T *const l)
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
@@ -344,6 +375,48 @@ static inline int tv_list_len(const list_T *const l)
return l->lv_len;
}
static inline int tv_list_copyid(const list_T *const l)
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL;
/// Get list copyID
///
/// Does not expect NULL list, be careful.
///
/// @param[in] l List to check.
static inline int tv_list_copyid(const list_T *const l)
{
return l->lv_copyID;
}
static inline list_T *tv_list_latest_copy(const list_T *const l)
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL;
/// Get latest list copy
///
/// Gets lv_copylist field assigned by tv_list_copy() earlier.
///
/// Does not expect NULL list, be careful.
///
/// @param[in] l List to check.
static inline list_T *tv_list_latest_copy(const list_T *const l)
{
return l->lv_copylist;
}
/// Clear the list without freeing anything at all
///
/// For use in sort() which saves items to a separate array and readds them back
/// after sorting via a number of tv_list_append() calls.
///
/// @param[out] l List to clear.
static inline void tv_list_clear(list_T *const l)
{
l->lv_first = NULL;
l->lv_last = NULL;
l->lv_idx_item = NULL;
l->lv_len = 0;
}
static inline int tv_list_uidx(const list_T *const l, int n)
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;

View File

@@ -359,7 +359,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
TYPVAL_ENCODE_CONV_EMPTY_LIST(tv);
break;
}
const int saved_copyID = tv->vval.v_list->lv_copyID;
const int saved_copyID = tv_list_copyid(tv->vval.v_list);
_TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, copyID,
kMPConvList);
TYPVAL_ENCODE_CONV_LIST_START(tv, tv_list_len(tv->vval.v_list));
@@ -515,7 +515,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
if (val_di->di_tv.v_type != VAR_LIST) {
goto _convert_one_value_regular_dict;
}
const int saved_copyID = val_di->di_tv.vval.v_list->lv_copyID;
const int saved_copyID = tv_list_copyid(val_di->di_tv.vval.v_list);
_TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list,
lv_copyID, copyID,
kMPConvList);
@@ -550,7 +550,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
goto _convert_one_value_regular_dict;
}
});
const int saved_copyID = val_di->di_tv.vval.v_list->lv_copyID;
const int saved_copyID = tv_list_copyid(val_di->di_tv.vval.v_list);
_TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_list, lv_copyID, copyID,
kMPConvPairs);
TYPVAL_ENCODE_CONV_DICT_START(tv, TYPVAL_ENCODE_NODICT_VAR,
@@ -694,7 +694,7 @@ typval_encode_stop_converting_one_item:
case kMPConvList: {
if (cur_mpsv->data.l.li == NULL) {
(void)_mp_pop(mpstack);
cur_mpsv->data.l.list->lv_copyID = cur_mpsv->saved_copyID;
tv_list_set_copyid(cur_mpsv->data.l.list, cur_mpsv->saved_copyID);
TYPVAL_ENCODE_CONV_LIST_END(cur_mpsv->tv);
continue;
} else if (cur_mpsv->data.l.li
@@ -709,7 +709,7 @@ typval_encode_stop_converting_one_item:
case kMPConvPairs: {
if (cur_mpsv->data.l.li == NULL) {
(void)_mp_pop(mpstack);
cur_mpsv->data.l.list->lv_copyID = cur_mpsv->saved_copyID;
tv_list_set_copyid(cur_mpsv->data.l.list, cur_mpsv->saved_copyID);
TYPVAL_ENCODE_CONV_DICT_END(cur_mpsv->tv, TYPVAL_ENCODE_NODICT_VAR);
continue;
} else if (cur_mpsv->data.l.li