mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 9.1.0524: the recursive parameter in the *_equal functions can be removed
Problem: the recursive parameter in the *_equal functions can be removed Solution: Remove the recursive parameter in dict_equal(), list_equal() object_equal and tv_equal(). Use a comparison of the static var recursive_cnt == 0 to determine whether or not tv_equal() has been called recursively (Yinzuo Jiang). closes: #15070 Signed-off-by: Yinzuo Jiang <jiangyinzuo@foxmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
parent
e54fd3f7d8
commit
7ccd1a2e85
@ -1222,8 +1222,7 @@ dict_lookup(hashitem_T *hi)
|
|||||||
dict_equal(
|
dict_equal(
|
||||||
dict_T *d1,
|
dict_T *d1,
|
||||||
dict_T *d2,
|
dict_T *d2,
|
||||||
int ic, // ignore case for strings
|
int ic) // ignore case for strings
|
||||||
int recursive) // TRUE when used recursively
|
|
||||||
{
|
{
|
||||||
hashitem_T *hi;
|
hashitem_T *hi;
|
||||||
dictitem_T *item2;
|
dictitem_T *item2;
|
||||||
@ -1247,7 +1246,7 @@ dict_equal(
|
|||||||
item2 = dict_find(d2, hi->hi_key, -1);
|
item2 = dict_find(d2, hi->hi_key, -1);
|
||||||
if (item2 == NULL)
|
if (item2 == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic, recursive))
|
if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
--todo;
|
--todo;
|
||||||
}
|
}
|
||||||
@ -1275,7 +1274,7 @@ dict_count(dict_T *d, typval_T *needle, int ic)
|
|||||||
if (!HASHITEM_EMPTY(hi))
|
if (!HASHITEM_EMPTY(hi))
|
||||||
{
|
{
|
||||||
--todo;
|
--todo;
|
||||||
if (tv_equal(&HI2DI(hi)->di_tv, needle, ic, FALSE))
|
if (tv_equal(&HI2DI(hi)->di_tv, needle, ic))
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7535,7 +7535,7 @@ f_index(typval_T *argvars, typval_T *rettv)
|
|||||||
{
|
{
|
||||||
tv.v_type = VAR_NUMBER;
|
tv.v_type = VAR_NUMBER;
|
||||||
tv.vval.v_number = blob_get(b, idx);
|
tv.vval.v_number = blob_get(b, idx);
|
||||||
if (tv_equal(&tv, &argvars[1], ic, FALSE))
|
if (tv_equal(&tv, &argvars[1], ic))
|
||||||
{
|
{
|
||||||
rettv->vval.v_number = idx;
|
rettv->vval.v_number = idx;
|
||||||
return;
|
return;
|
||||||
@ -7568,7 +7568,7 @@ f_index(typval_T *argvars, typval_T *rettv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for ( ; item != NULL; item = item->li_next, ++idx)
|
for ( ; item != NULL; item = item->li_next, ++idx)
|
||||||
if (tv_equal(&item->li_tv, &argvars[1], ic, FALSE))
|
if (tv_equal(&item->li_tv, &argvars[1], ic))
|
||||||
{
|
{
|
||||||
rettv->vval.v_number = idx;
|
rettv->vval.v_number = idx;
|
||||||
break;
|
break;
|
||||||
|
@ -365,8 +365,7 @@ list_len(list_T *l)
|
|||||||
list_equal(
|
list_equal(
|
||||||
list_T *l1,
|
list_T *l1,
|
||||||
list_T *l2,
|
list_T *l2,
|
||||||
int ic, // ignore case for strings
|
int ic) // ignore case for strings
|
||||||
int recursive) // TRUE when used recursively
|
|
||||||
{
|
{
|
||||||
listitem_T *item1, *item2;
|
listitem_T *item1, *item2;
|
||||||
|
|
||||||
@ -386,7 +385,7 @@ list_equal(
|
|||||||
for (item1 = l1->lv_first, item2 = l2->lv_first;
|
for (item1 = l1->lv_first, item2 = l2->lv_first;
|
||||||
item1 != NULL && item2 != NULL;
|
item1 != NULL && item2 != NULL;
|
||||||
item1 = item1->li_next, item2 = item2->li_next)
|
item1 = item1->li_next, item2 = item2->li_next)
|
||||||
if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive))
|
if (!tv_equal(&item1->li_tv, &item2->li_tv, ic))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
return item1 == NULL && item2 == NULL;
|
return item1 == NULL && item2 == NULL;
|
||||||
}
|
}
|
||||||
@ -2727,7 +2726,7 @@ list_count(list_T *l, typval_T *needle, long idx, int ic)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for ( ; li != NULL; li = li->li_next)
|
for ( ; li != NULL; li = li->li_next)
|
||||||
if (tv_equal(&li->li_tv, needle, ic, FALSE))
|
if (tv_equal(&li->li_tv, needle, ic))
|
||||||
++n;
|
++n;
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
|
@ -40,7 +40,7 @@ int eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal);
|
|||||||
int eval_lit_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
int eval_lit_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||||
void dict_extend(dict_T *d1, dict_T *d2, char_u *action, char *func_name);
|
void dict_extend(dict_T *d1, dict_T *d2, char_u *action, char *func_name);
|
||||||
dictitem_T *dict_lookup(hashitem_T *hi);
|
dictitem_T *dict_lookup(hashitem_T *hi);
|
||||||
int dict_equal(dict_T *d1, dict_T *d2, int ic, int recursive);
|
int dict_equal(dict_T *d1, dict_T *d2, int ic);
|
||||||
long dict_count(dict_T *d, typval_T *needle, int ic);
|
long dict_count(dict_T *d, typval_T *needle, int ic);
|
||||||
void dict_extend_func(typval_T *argvars, type_T *type, char *func_name, char_u *arg_errmsg, int is_new, typval_T *rettv);
|
void dict_extend_func(typval_T *argvars, type_T *type, char *func_name, char_u *arg_errmsg, int is_new, typval_T *rettv);
|
||||||
void dict_filter_map(dict_T *d, filtermap_T filtermap, type_T *argtype, char *func_name, char_u *arg_errmsg, typval_T *expr, typval_T *rettv);
|
void dict_filter_map(dict_T *d, filtermap_T filtermap, type_T *argtype, char *func_name, char_u *arg_errmsg, typval_T *expr, typval_T *rettv);
|
||||||
|
@ -16,7 +16,7 @@ listitem_T *listitem_alloc(void);
|
|||||||
void listitem_free(list_T *l, listitem_T *item);
|
void listitem_free(list_T *l, listitem_T *item);
|
||||||
void listitem_remove(list_T *l, listitem_T *item);
|
void listitem_remove(list_T *l, listitem_T *item);
|
||||||
long list_len(list_T *l);
|
long list_len(list_T *l);
|
||||||
int list_equal(list_T *l1, list_T *l2, int ic, int recursive);
|
int list_equal(list_T *l1, list_T *l2, int ic);
|
||||||
listitem_T *list_find(list_T *l, long n);
|
listitem_T *list_find(list_T *l, long n);
|
||||||
long list_find_nr(list_T *l, long idx, int *errorp);
|
long list_find_nr(list_T *l, long idx, int *errorp);
|
||||||
char_u *list_find_str(list_T *l, long idx);
|
char_u *list_find_str(list_T *l, long idx);
|
||||||
|
@ -75,7 +75,7 @@ int typval_compare_func(typval_T *tv1, typval_T *tv2, exprtype_T type, int ic, i
|
|||||||
int typval_compare_string(typval_T *tv1, typval_T *tv2, exprtype_T type, int ic, int *res);
|
int typval_compare_string(typval_T *tv1, typval_T *tv2, exprtype_T type, int ic, int *res);
|
||||||
char_u *typval_tostring(typval_T *arg, int quotes);
|
char_u *typval_tostring(typval_T *arg, int quotes);
|
||||||
int tv_islocked(typval_T *tv);
|
int tv_islocked(typval_T *tv);
|
||||||
int tv_equal(typval_T *tv1, typval_T *tv2, int ic, int recursive);
|
int tv_equal(typval_T *tv1, typval_T *tv2, int ic);
|
||||||
int eval_option(char_u **arg, typval_T *rettv, int evaluate);
|
int eval_option(char_u **arg, typval_T *rettv, int evaluate);
|
||||||
int eval_number(char_u **arg, typval_T *rettv, int evaluate, int want_string);
|
int eval_number(char_u **arg, typval_T *rettv, int evaluate, int want_string);
|
||||||
int eval_string(char_u **arg, typval_T *rettv, int evaluate, int interpolate);
|
int eval_string(char_u **arg, typval_T *rettv, int evaluate, int interpolate);
|
||||||
|
@ -40,7 +40,7 @@ int is_class_name(char_u *name, typval_T *rettv);
|
|||||||
void protected_method_access_errmsg(char_u *method_name);
|
void protected_method_access_errmsg(char_u *method_name);
|
||||||
int object_empty(object_T *obj);
|
int object_empty(object_T *obj);
|
||||||
int object_len(object_T *obj);
|
int object_len(object_T *obj);
|
||||||
int object_equal(object_T *o1, object_T *o2, int ic, int recursive);
|
int object_equal(object_T *o1, object_T *o2, int ic);
|
||||||
char_u *object2string(object_T *obj, char_u *numbuf, int copyID, int echo_style, int restore_copyID, int composite_val);
|
char_u *object2string(object_T *obj, char_u *numbuf, int copyID, int echo_style, int restore_copyID, int composite_val);
|
||||||
int class_instance_of(class_T *cl, class_T *other_cl);
|
int class_instance_of(class_T *cl, class_T *other_cl);
|
||||||
void f_instanceof(typval_T *argvars, typval_T *rettv);
|
void f_instanceof(typval_T *argvars, typval_T *rettv);
|
||||||
|
@ -1147,6 +1147,19 @@ func Test_listdict_compare()
|
|||||||
call assert_fails('echo {} =~ {}', 'E736:')
|
call assert_fails('echo {} =~ {}', 'E736:')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_recursive_listdict_compare()
|
||||||
|
let l1 = [0, 1]
|
||||||
|
let l1[0] = l1
|
||||||
|
let l2 = [0, 1]
|
||||||
|
let l2[0] = l2
|
||||||
|
call assert_true(l1 == l2)
|
||||||
|
let d1 = {0: 0, 1: 1}
|
||||||
|
let d1[0] = d1
|
||||||
|
let d2 = {0: 0, 1: 1}
|
||||||
|
let d2[0] = d2
|
||||||
|
call assert_true(d1 == d2)
|
||||||
|
endfunc
|
||||||
|
|
||||||
" compare complex recursively linked list and dict
|
" compare complex recursively linked list and dict
|
||||||
func Test_listdict_compare_complex()
|
func Test_listdict_compare_complex()
|
||||||
let lines =<< trim END
|
let lines =<< trim END
|
||||||
|
@ -187,7 +187,7 @@ fill_assert_error(
|
|||||||
{
|
{
|
||||||
item2 = dict_find(got_d, hi->hi_key, -1);
|
item2 = dict_find(got_d, hi->hi_key, -1);
|
||||||
if (item2 == NULL || !tv_equal(&HI2DI(hi)->di_tv,
|
if (item2 == NULL || !tv_equal(&HI2DI(hi)->di_tv,
|
||||||
&item2->di_tv, FALSE, FALSE))
|
&item2->di_tv, FALSE))
|
||||||
{
|
{
|
||||||
// item of exp_d not present in got_d or values differ.
|
// item of exp_d not present in got_d or values differ.
|
||||||
dict_add_tv(exp_tv->vval.v_dict,
|
dict_add_tv(exp_tv->vval.v_dict,
|
||||||
@ -262,7 +262,7 @@ assert_equal_common(typval_T *argvars, assert_type_T atype)
|
|||||||
{
|
{
|
||||||
garray_T ga;
|
garray_T ga;
|
||||||
|
|
||||||
if (tv_equal(&argvars[0], &argvars[1], FALSE, FALSE)
|
if (tv_equal(&argvars[0], &argvars[1], FALSE)
|
||||||
!= (atype == ASSERT_EQUAL))
|
!= (atype == ASSERT_EQUAL))
|
||||||
{
|
{
|
||||||
prepare_assert_error(&ga);
|
prepare_assert_error(&ga);
|
||||||
|
26
src/typval.c
26
src/typval.c
@ -1605,8 +1605,7 @@ typval_compare_list(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = list_equal(tv1->vval.v_list, tv2->vval.v_list,
|
val = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic);
|
||||||
ic, FALSE);
|
|
||||||
if (type == EXPR_NEQUAL)
|
if (type == EXPR_NEQUAL)
|
||||||
val = !val;
|
val = !val;
|
||||||
}
|
}
|
||||||
@ -1750,7 +1749,7 @@ typval_compare_object(
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
*res = object_equal(obj1, obj2, ic, FALSE) ? res_match : !res_match;
|
*res = object_equal(obj1, obj2, ic) ? res_match : !res_match;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1787,7 +1786,7 @@ typval_compare_dict(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, FALSE);
|
val = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic);
|
||||||
if (type == EXPR_NEQUAL)
|
if (type == EXPR_NEQUAL)
|
||||||
val = !val;
|
val = !val;
|
||||||
}
|
}
|
||||||
@ -1826,14 +1825,14 @@ typval_compare_func(
|
|||||||
if (tv1->v_type == VAR_FUNC && tv2->v_type == VAR_FUNC)
|
if (tv1->v_type == VAR_FUNC && tv2->v_type == VAR_FUNC)
|
||||||
// strings are considered the same if their value is
|
// strings are considered the same if their value is
|
||||||
// the same
|
// the same
|
||||||
val = tv_equal(tv1, tv2, ic, FALSE);
|
val = tv_equal(tv1, tv2, ic);
|
||||||
else if (tv1->v_type == VAR_PARTIAL && tv2->v_type == VAR_PARTIAL)
|
else if (tv1->v_type == VAR_PARTIAL && tv2->v_type == VAR_PARTIAL)
|
||||||
val = (tv1->vval.v_partial == tv2->vval.v_partial);
|
val = (tv1->vval.v_partial == tv2->vval.v_partial);
|
||||||
else
|
else
|
||||||
val = FALSE;
|
val = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
val = tv_equal(tv1, tv2, ic, FALSE);
|
val = tv_equal(tv1, tv2, ic);
|
||||||
if (type == EXPR_NEQUAL || type == EXPR_ISNOT)
|
if (type == EXPR_NEQUAL || type == EXPR_ISNOT)
|
||||||
val = !val;
|
val = !val;
|
||||||
*res = val;
|
*res = val;
|
||||||
@ -1988,7 +1987,7 @@ func_equal(
|
|||||||
if (d1 != d2)
|
if (d1 != d2)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else if (!dict_equal(d1, d2, ic, TRUE))
|
else if (!dict_equal(d1, d2, ic))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
// empty list and no list considered the same
|
// empty list and no list considered the same
|
||||||
@ -1998,7 +1997,7 @@ func_equal(
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
for (i = 0; i < a1; ++i)
|
for (i = 0; i < a1; ++i)
|
||||||
if (!tv_equal(tv1->vval.v_partial->pt_argv + i,
|
if (!tv_equal(tv1->vval.v_partial->pt_argv + i,
|
||||||
tv2->vval.v_partial->pt_argv + i, ic, TRUE))
|
tv2->vval.v_partial->pt_argv + i, ic))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -2013,8 +2012,7 @@ func_equal(
|
|||||||
tv_equal(
|
tv_equal(
|
||||||
typval_T *tv1,
|
typval_T *tv1,
|
||||||
typval_T *tv2,
|
typval_T *tv2,
|
||||||
int ic, // ignore case
|
int ic) // ignore case
|
||||||
int recursive) // TRUE when used recursively
|
|
||||||
{
|
{
|
||||||
char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
|
char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
|
||||||
char_u *s1, *s2;
|
char_u *s1, *s2;
|
||||||
@ -2028,7 +2026,7 @@ tv_equal(
|
|||||||
// Reduce the limit every time running into it. That should work fine for
|
// Reduce the limit every time running into it. That should work fine for
|
||||||
// deeply linked structures that are not recursively linked and catch
|
// deeply linked structures that are not recursively linked and catch
|
||||||
// recursiveness quickly.
|
// recursiveness quickly.
|
||||||
if (!recursive)
|
if (recursive_cnt == 0)
|
||||||
tv_equal_recurse_limit = 1000;
|
tv_equal_recurse_limit = 1000;
|
||||||
if (recursive_cnt >= tv_equal_recurse_limit)
|
if (recursive_cnt >= tv_equal_recurse_limit)
|
||||||
{
|
{
|
||||||
@ -2058,13 +2056,13 @@ tv_equal(
|
|||||||
{
|
{
|
||||||
case VAR_LIST:
|
case VAR_LIST:
|
||||||
++recursive_cnt;
|
++recursive_cnt;
|
||||||
r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE);
|
r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic);
|
||||||
--recursive_cnt;
|
--recursive_cnt;
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
case VAR_DICT:
|
case VAR_DICT:
|
||||||
++recursive_cnt;
|
++recursive_cnt;
|
||||||
r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE);
|
r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic);
|
||||||
--recursive_cnt;
|
--recursive_cnt;
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -2100,7 +2098,7 @@ tv_equal(
|
|||||||
|
|
||||||
case VAR_OBJECT:
|
case VAR_OBJECT:
|
||||||
++recursive_cnt;
|
++recursive_cnt;
|
||||||
r = object_equal(tv1->vval.v_object, tv2->vval.v_object, ic, TRUE);
|
r = object_equal(tv1->vval.v_object, tv2->vval.v_object, ic);
|
||||||
--recursive_cnt;
|
--recursive_cnt;
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
524,
|
||||||
/**/
|
/**/
|
||||||
523,
|
523,
|
||||||
/**/
|
/**/
|
||||||
|
@ -3849,8 +3849,7 @@ object_len(object_T *obj)
|
|||||||
object_equal(
|
object_equal(
|
||||||
object_T *o1,
|
object_T *o1,
|
||||||
object_T *o2,
|
object_T *o2,
|
||||||
int ic, // ignore case for strings
|
int ic) // ignore case for strings
|
||||||
int recursive) // TRUE when used recursively
|
|
||||||
{
|
{
|
||||||
class_T *cl1, *cl2;
|
class_T *cl1, *cl2;
|
||||||
|
|
||||||
@ -3866,7 +3865,7 @@ object_equal(
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
for (int i = 0; i < cl1->class_obj_member_count; ++i)
|
for (int i = 0; i < cl1->class_obj_member_count; ++i)
|
||||||
if (!tv_equal((typval_T *)(o1 + 1) + i, (typval_T *)(o2 + 1) + i, ic, recursive))
|
if (!tv_equal((typval_T *)(o1 + 1) + i, (typval_T *)(o2 + 1) + i, ic))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user