0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

patch 8.1.1978: the eval.c file is too big

Problem:    The eval.c file is too big.
Solution:   Move filter() and map() to list.c.
This commit is contained in:
Bram Moolenaar
2019-09-04 14:41:14 +02:00
parent 19c8fe1925
commit 1e1d30048e
6 changed files with 221 additions and 219 deletions

View File

@@ -7135,199 +7135,4 @@ do_string_sub(
return ret;
}
static int
filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
{
typval_T rettv;
typval_T argv[3];
int retval = FAIL;
copy_tv(tv, get_vim_var_tv(VV_VAL));
argv[0] = *get_vim_var_tv(VV_KEY);
argv[1] = *get_vim_var_tv(VV_VAL);
if (eval_expr_typval(expr, argv, 2, &rettv) == FAIL)
goto theend;
if (map)
{
/* map(): replace the list item value */
clear_tv(tv);
rettv.v_lock = 0;
*tv = rettv;
}
else
{
int error = FALSE;
/* filter(): when expr is zero remove the item */
*remp = (tv_get_number_chk(&rettv, &error) == 0);
clear_tv(&rettv);
/* On type error, nothing has been removed; return FAIL to stop the
* loop. The error message was given by tv_get_number_chk(). */
if (error)
goto theend;
}
retval = OK;
theend:
clear_tv(get_vim_var_tv(VV_VAL));
return retval;
}
/*
* Implementation of map() and filter().
*/
void
filter_map(typval_T *argvars, typval_T *rettv, int map)
{
typval_T *expr;
listitem_T *li, *nli;
list_T *l = NULL;
dictitem_T *di;
hashtab_T *ht;
hashitem_T *hi;
dict_T *d = NULL;
blob_T *b = NULL;
int rem;
int todo;
char_u *ermsg = (char_u *)(map ? "map()" : "filter()");
char_u *arg_errmsg = (char_u *)(map ? N_("map() argument")
: N_("filter() argument"));
int save_did_emsg;
int idx = 0;
if (argvars[0].v_type == VAR_BLOB)
{
if ((b = argvars[0].vval.v_blob) == NULL)
return;
}
else if (argvars[0].v_type == VAR_LIST)
{
if ((l = argvars[0].vval.v_list) == NULL
|| (!map && var_check_lock(l->lv_lock, arg_errmsg, TRUE)))
return;
}
else if (argvars[0].v_type == VAR_DICT)
{
if ((d = argvars[0].vval.v_dict) == NULL
|| (!map && var_check_lock(d->dv_lock, arg_errmsg, TRUE)))
return;
}
else
{
semsg(_(e_listdictarg), ermsg);
return;
}
expr = &argvars[1];
/* On type errors, the preceding call has already displayed an error
* message. Avoid a misleading error message for an empty string that
* was not passed as argument. */
if (expr->v_type != VAR_UNKNOWN)
{
typval_T save_val;
typval_T save_key;
prepare_vimvar(VV_VAL, &save_val);
prepare_vimvar(VV_KEY, &save_key);
// We reset "did_emsg" to be able to detect whether an error
// occurred during evaluation of the expression.
save_did_emsg = did_emsg;
did_emsg = FALSE;
if (argvars[0].v_type == VAR_DICT)
{
ht = &d->dv_hashtab;
hash_lock(ht);
todo = (int)ht->ht_used;
for (hi = ht->ht_array; todo > 0; ++hi)
{
if (!HASHITEM_EMPTY(hi))
{
int r;
--todo;
di = HI2DI(hi);
if (map && (var_check_lock(di->di_tv.v_lock,
arg_errmsg, TRUE)
|| var_check_ro(di->di_flags,
arg_errmsg, TRUE)))
break;
set_vim_var_string(VV_KEY, di->di_key, -1);
r = filter_map_one(&di->di_tv, expr, map, &rem);
clear_tv(get_vim_var_tv(VV_KEY));
if (r == FAIL || did_emsg)
break;
if (!map && rem)
{
if (var_check_fixed(di->di_flags, arg_errmsg, TRUE)
|| var_check_ro(di->di_flags, arg_errmsg, TRUE))
break;
dictitem_remove(d, di);
}
}
}
hash_unlock(ht);
}
else if (argvars[0].v_type == VAR_BLOB)
{
int i;
typval_T tv;
// set_vim_var_nr() doesn't set the type
set_vim_var_type(VV_KEY, VAR_NUMBER);
for (i = 0; i < b->bv_ga.ga_len; i++)
{
tv.v_type = VAR_NUMBER;
tv.vval.v_number = blob_get(b, i);
set_vim_var_nr(VV_KEY, idx);
if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg)
break;
if (tv.v_type != VAR_NUMBER)
{
emsg(_(e_invalblob));
break;
}
tv.v_type = VAR_NUMBER;
blob_set(b, i, tv.vval.v_number);
if (!map && rem)
{
char_u *p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
mch_memmove(p + idx, p + i + 1,
(size_t)b->bv_ga.ga_len - i - 1);
--b->bv_ga.ga_len;
--i;
}
}
}
else // argvars[0].v_type == VAR_LIST
{
// set_vim_var_nr() doesn't set the type
set_vim_var_type(VV_KEY, VAR_NUMBER);
for (li = l->lv_first; li != NULL; li = nli)
{
if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
break;
nli = li->li_next;
set_vim_var_nr(VV_KEY, idx);
if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
|| did_emsg)
break;
if (!map && rem)
listitem_remove(l, li);
++idx;
}
}
restore_vimvar(VV_KEY, &save_key);
restore_vimvar(VV_VAL, &save_val);
did_emsg |= save_did_emsg;
}
copy_tv(&argvars[0], rettv);
}
#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */