mirror of
https://github.com/neovim/neovim.git
synced 2025-09-30 23:18:33 +00:00
*: Provide list length when allocating lists
This commit is contained in:
@@ -150,7 +150,7 @@ static inline int json_decoder_pop(ValuesStackItem obj,
|
||||
}
|
||||
obj_di->di_tv = obj.val;
|
||||
} else {
|
||||
list_T *const kv_pair = tv_list_alloc();
|
||||
list_T *const kv_pair = tv_list_alloc(2);
|
||||
tv_list_append_list(last_container.special_val, kv_pair);
|
||||
tv_list_append_owned_tv(kv_pair, key.val);
|
||||
tv_list_append_owned_tv(kv_pair, obj.val);
|
||||
@@ -221,13 +221,18 @@ static inline int json_decoder_pop(ValuesStackItem obj,
|
||||
/// Create a new special dictionary that ought to represent a MAP
|
||||
///
|
||||
/// @param[out] ret_tv Address where new special dictionary is saved.
|
||||
/// @param[in] len Expected number of items to be populated before list
|
||||
/// becomes accessible from VimL. It is still valid to
|
||||
/// underpopulate a list, value only controls how many elements
|
||||
/// will be allocated in advance. @see ListLenSpecials.
|
||||
///
|
||||
/// @return [allocated] list which should contain key-value pairs. Return value
|
||||
/// may be safely ignored.
|
||||
list_T *decode_create_map_special_dict(typval_T *const ret_tv)
|
||||
list_T *decode_create_map_special_dict(typval_T *const ret_tv,
|
||||
const ptrdiff_t len)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
list_T *const list = tv_list_alloc();
|
||||
list_T *const list = tv_list_alloc(len);
|
||||
tv_list_ref(list);
|
||||
create_special_dict(ret_tv, kMPMap, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@@ -263,7 +268,7 @@ typval_T decode_string(const char *const s, const size_t len,
|
||||
? ((s != NULL) && (memchr(s, NUL, len) != NULL))
|
||||
: (bool)hasnul);
|
||||
if (really_hasnul) {
|
||||
list_T *const list = tv_list_alloc();
|
||||
list_T *const list = tv_list_alloc(kListLenMayKnow);
|
||||
tv_list_ref(list);
|
||||
typval_T tv;
|
||||
create_special_dict(&tv, binary ? kMPBinary : kMPString, ((typval_T) {
|
||||
@@ -843,7 +848,7 @@ json_decode_string_cycle_start:
|
||||
break;
|
||||
}
|
||||
case '[': {
|
||||
list_T *list = tv_list_alloc();
|
||||
list_T *list = tv_list_alloc(kListLenMayKnow);
|
||||
tv_list_ref(list);
|
||||
typval_T tv = {
|
||||
.v_type = VAR_LIST,
|
||||
@@ -864,7 +869,7 @@ json_decode_string_cycle_start:
|
||||
list_T *val_list = NULL;
|
||||
if (next_map_special) {
|
||||
next_map_special = false;
|
||||
val_list = decode_create_map_special_dict(&tv);
|
||||
val_list = decode_create_map_special_dict(&tv, kListLenMayKnow);
|
||||
} else {
|
||||
dict_T *dict = tv_dict_alloc();
|
||||
dict->dv_refcount++;
|
||||
@@ -964,7 +969,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
.vval = { .v_number = (varnumber_T) mobj.via.u64 },
|
||||
};
|
||||
} else {
|
||||
list_T *const list = tv_list_alloc();
|
||||
list_T *const list = tv_list_alloc(4);
|
||||
tv_list_ref(list);
|
||||
create_special_dict(rettv, kMPInteger, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@@ -987,7 +992,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
.vval = { .v_number = (varnumber_T) mobj.via.i64 },
|
||||
};
|
||||
} else {
|
||||
list_T *const list = tv_list_alloc();
|
||||
list_T *const list = tv_list_alloc(4);
|
||||
tv_list_ref(list);
|
||||
create_special_dict(rettv, kMPInteger, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@@ -1033,7 +1038,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
break;
|
||||
}
|
||||
case MSGPACK_OBJECT_ARRAY: {
|
||||
list_T *const list = tv_list_alloc();
|
||||
list_T *const list = tv_list_alloc((ptrdiff_t)mobj.via.array.size);
|
||||
tv_list_ref(list);
|
||||
*rettv = (typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@@ -1085,9 +1090,10 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
}
|
||||
break;
|
||||
msgpack_to_vim_generic_map: {}
|
||||
list_T *const list = decode_create_map_special_dict(rettv);
|
||||
list_T *const list = decode_create_map_special_dict(
|
||||
rettv, (ptrdiff_t)mobj.via.map.size);
|
||||
for (size_t i = 0; i < mobj.via.map.size; i++) {
|
||||
list_T *const kv_pair = tv_list_alloc();
|
||||
list_T *const kv_pair = tv_list_alloc(2);
|
||||
tv_list_append_list(list, kv_pair);
|
||||
|
||||
typval_T key_tv = { .v_type = VAR_UNKNOWN };
|
||||
@@ -1107,10 +1113,10 @@ msgpack_to_vim_generic_map: {}
|
||||
break;
|
||||
}
|
||||
case MSGPACK_OBJECT_EXT: {
|
||||
list_T *const list = tv_list_alloc();
|
||||
list_T *const list = tv_list_alloc(2);
|
||||
tv_list_ref(list);
|
||||
tv_list_append_number(list, mobj.via.ext.type);
|
||||
list_T *const ext_val_list = tv_list_alloc();
|
||||
list_T *const ext_val_list = tv_list_alloc(kListLenMayKnow);
|
||||
tv_list_append_list(list, ext_val_list);
|
||||
create_special_dict(rettv, kMPExt, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
|
@@ -132,8 +132,14 @@ void tv_list_watch_fix(list_T *const l, const listitem_T *const item)
|
||||
///
|
||||
/// Caller should take care of the reference count.
|
||||
///
|
||||
/// @param[in] len Expected number of items to be populated before list
|
||||
/// becomes accessible from VimL. It is still valid to
|
||||
/// underpopulate a list, value only controls how many elements
|
||||
/// will be allocated in advance. Currently does nothing.
|
||||
/// @see ListLenSpecials.
|
||||
///
|
||||
/// @return [allocated] new list.
|
||||
list_T *tv_list_alloc(void)
|
||||
list_T *tv_list_alloc(const ptrdiff_t len)
|
||||
FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
list_T *const list = xcalloc(1, sizeof(list_T));
|
||||
@@ -521,7 +527,7 @@ list_T *tv_list_copy(const vimconv_T *const conv, list_T *const orig,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_T *copy = tv_list_alloc();
|
||||
list_T *copy = tv_list_alloc(tv_list_len(orig));
|
||||
tv_list_ref(copy);
|
||||
if (copyID != 0) {
|
||||
// Do this before adding the items, because one of the items may
|
||||
@@ -1817,12 +1823,16 @@ void tv_dict_set_keys_readonly(dict_T *const dict)
|
||||
/// Also sets reference count.
|
||||
///
|
||||
/// @param[out] ret_tv Structure where list is saved.
|
||||
/// @param[in] len Expected number of items to be populated before list
|
||||
/// becomes accessible from VimL. It is still valid to
|
||||
/// underpopulate a list, value only controls how many elements
|
||||
/// will be allocated in advance. @see ListLenSpecials.
|
||||
///
|
||||
/// @return [allocated] pointer to the created list.
|
||||
list_T *tv_list_alloc_ret(typval_T *const ret_tv)
|
||||
list_T *tv_list_alloc_ret(typval_T *const ret_tv, const ptrdiff_t len)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
list_T *const l = tv_list_alloc();
|
||||
list_T *const l = tv_list_alloc(len);
|
||||
ret_tv->vval.v_list = l;
|
||||
ret_tv->v_type = VAR_LIST;
|
||||
ret_tv->v_lock = VAR_UNLOCKED;
|
||||
|
@@ -31,6 +31,25 @@ typedef double float_T;
|
||||
/// Refcount for dict or list that should not be freed
|
||||
enum { DO_NOT_FREE_CNT = (INT_MAX / 2) };
|
||||
|
||||
/// Additional values for tv_list_alloc() len argument
|
||||
enum {
|
||||
/// List length is not known in advance
|
||||
///
|
||||
/// To be used when there is neither a way to know how many elements will be
|
||||
/// needed nor are any educated guesses.
|
||||
kListLenUnknown = -1,
|
||||
/// List length *should* be known, but is actually not
|
||||
///
|
||||
/// All occurrences of this value should be eventually removed. This is for
|
||||
/// the case when the only reason why list length is not known is that it
|
||||
/// would be hard to code without refactoring, but refactoring is needed.
|
||||
kListLenShouldKnow = -2,
|
||||
/// List length may be known in advance, but it requires too much effort
|
||||
///
|
||||
/// To be used when it looks impractical to determine list length.
|
||||
kListLenMayKnow = -3,
|
||||
} ListLenSpecials;
|
||||
|
||||
/// Maximal possible value of varnumber_T variable
|
||||
#define VARNUMBER_MAX INT64_MAX
|
||||
#define UVARNUMBER_MAX UINT64_MAX
|
||||
|
Reference in New Issue
Block a user