Skip to content

Commit acf7d73

Browse files
committed
patch 8.2.4627: flatten() does not use maxdepth correctly
Problem: flatten() does not use maxdepth correctly. Solution: Use a recursive implementation. (closes #10020)
1 parent abb6fbd commit acf7d73

File tree

3 files changed

+39
-24
lines changed

3 files changed

+39
-24
lines changed

src/list.c

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -916,59 +916,56 @@ list_assign_range(
916916
}
917917

918918
/*
919-
* Flatten "list" to depth "maxdepth".
919+
* Flatten up to "maxitems" in "list", starting at "first" to depth "maxdepth".
920+
* When "first" is NULL use the first item.
920921
* It does nothing if "maxdepth" is 0.
921922
* Returns FAIL when out of memory.
922923
*/
923924
static void
924-
list_flatten(list_T *list, long maxdepth)
925+
list_flatten(list_T *list, listitem_T *first, long maxitems, long maxdepth)
925926
{
926927
listitem_T *item;
927928
listitem_T *tofree;
928-
int n;
929+
int done = 0;
929930

930931
if (maxdepth == 0)
931932
return;
932933
CHECK_LIST_MATERIALIZE(list);
934+
if (first == NULL)
935+
item = list->lv_first;
936+
else
937+
item = first;
933938

934-
n = 0;
935-
item = list->lv_first;
936-
while (item != NULL)
939+
while (item != NULL && done < maxitems)
937940
{
941+
listitem_T *next = item->li_next;
942+
938943
fast_breakcheck();
939944
if (got_int)
940945
return;
941946

942947
if (item->li_tv.v_type == VAR_LIST)
943948
{
944-
listitem_T *next = item->li_next;
949+
list_T *itemlist = item->li_tv.vval.v_list;
945950

946951
vimlist_remove(list, item, item);
947-
if (list_extend(list, item->li_tv.vval.v_list, next) == FAIL)
952+
if (list_extend(list, itemlist, next) == FAIL)
948953
{
949954
list_free_item(list, item);
950955
return;
951956
}
952957
clear_tv(&item->li_tv);
953958
tofree = item;
954959

955-
if (item->li_prev == NULL)
956-
item = list->lv_first;
957-
else
958-
item = item->li_prev->li_next;
960+
if (maxdepth > 0)
961+
list_flatten(list, item->li_prev == NULL
962+
? list->lv_first : item->li_prev->li_next,
963+
itemlist->lv_len, maxdepth - 1);
959964
list_free_item(list, tofree);
960-
961-
if (++n >= maxdepth)
962-
{
963-
n = 0;
964-
item = next;
965-
}
966-
}
967-
else
968-
{
969-
n = 0;
970-
item = item->li_next;
971965
}
966+
967+
++done;
968+
item = next;
972969
}
973970
}
974971

@@ -1031,7 +1028,7 @@ flatten_common(typval_T *argvars, typval_T *rettv, int make_copy)
10311028
++l->lv_refcount;
10321029
}
10331030

1034-
list_flatten(l, maxdepth);
1031+
list_flatten(l, NULL, l->lv_len, maxdepth);
10351032
}
10361033

10371034
/*

src/testdir/test_flatten.vim

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ func Test_flatten()
7979
call add(y, x) " l:y = [2, [1, [...]]]
8080
call assert_equal([1, 2, 1, 2], flatten(l:x, 2))
8181
call assert_equal([2, l:x], l:y)
82+
83+
let l4 = [ 1, [ 11, [ 101, [ 1001 ] ] ] ]
84+
call assert_equal(l4, flatten(deepcopy(l4), 0))
85+
call assert_equal([1, 11, [101, [1001]]], flatten(deepcopy(l4), 1))
86+
call assert_equal([1, 11, 101, [1001]], flatten(deepcopy(l4), 2))
87+
call assert_equal([1, 11, 101, 1001], flatten(deepcopy(l4), 3))
88+
call assert_equal([1, 11, 101, 1001], flatten(deepcopy(l4), 4))
89+
call assert_equal([1, 11, 101, 1001], flatten(deepcopy(l4)))
8290
endfunc
8391

8492
func Test_flattennew()
@@ -88,6 +96,14 @@ func Test_flattennew()
8896

8997
call assert_equal([1, 2, [3, 4], 5], flattennew(l, 1))
9098
call assert_equal([1, [2, [3, 4]], 5], l)
99+
100+
let l4 = [ 1, [ 11, [ 101, [ 1001 ] ] ] ]
101+
call assert_equal(l4, flatten(deepcopy(l4), 0))
102+
call assert_equal([1, 11, [101, [1001]]], flattennew(l4, 1))
103+
call assert_equal([1, 11, 101, [1001]], flattennew(l4, 2))
104+
call assert_equal([1, 11, 101, 1001], flattennew(l4, 3))
105+
call assert_equal([1, 11, 101, 1001], flattennew(l4, 4))
106+
call assert_equal([1, 11, 101, 1001], flattennew(l4))
91107
endfunc
92108

93109
" vim: shiftwidth=2 sts=2 expandtab

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
4627,
753755
/**/
754756
4626,
755757
/**/

0 commit comments

Comments
 (0)