comparison src/list.c @ 20766:821925509d8c v8.2.0935

patch 8.2.0935: flattening a list with existing code is slow Commit: https://github.com/vim/vim/commit/077a1e670ad69ef4cefc22103ca6635bd269e764 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Jun 8 20:50:43 2020 +0200 patch 8.2.0935: flattening a list with existing code is slow Problem: Flattening a list with existing code is slow. Solution: Add flatten(). (Mopp, closes https://github.com/vim/vim/issues/3676)
author Bram Moolenaar <Bram@vim.org>
date Mon, 08 Jun 2020 21:00:04 +0200
parents a1e6d9353736
children b366a0fe8296
comparison
equal deleted inserted replaced
20765:ca776ec54a6c 20766:821925509d8c
726 l->lv_u.mat.lv_idx_item = NULL; 726 l->lv_u.mat.lv_idx_item = NULL;
727 } 727 }
728 item->li_prev = ni; 728 item->li_prev = ni;
729 ++l->lv_len; 729 ++l->lv_len;
730 } 730 }
731 }
732
733 /*
734 * Flatten "list" to depth "maxdepth".
735 * It does nothing if "maxdepth" is 0.
736 * Returns FAIL when out of memory.
737 */
738 static int
739 list_flatten(list_T *list, long maxdepth)
740 {
741 listitem_T *item;
742 int n;
743
744 if (maxdepth == 0)
745 return OK;
746 CHECK_LIST_MATERIALIZE(list);
747
748 n = 0;
749 item = list->lv_first;
750 while (item != NULL)
751 {
752 fast_breakcheck();
753 if (got_int)
754 return FAIL;
755
756 if (item->li_tv.v_type == VAR_LIST)
757 {
758 listitem_T *next = item->li_next;
759
760 vimlist_remove(list, item, item);
761 if (list_extend(list, item->li_tv.vval.v_list, next) == FAIL)
762 return FAIL;
763
764 if (item->li_prev == NULL)
765 item = list->lv_first;
766 else
767 item = item->li_prev->li_next;
768
769 if (++n >= maxdepth)
770 {
771 n = 0;
772 item = next;
773 }
774 }
775 else
776 {
777 n = 0;
778 item = item->li_next;
779 }
780 }
781
782 return OK;
783 }
784
785 /*
786 * "flatten(list[, {maxdepth}])" function
787 */
788 void
789 f_flatten(typval_T *argvars, typval_T *rettv)
790 {
791 list_T *l;
792 long maxdepth;
793 int error = FALSE;
794
795 if (argvars[0].v_type != VAR_LIST)
796 {
797 semsg(_(e_listarg), "flatten()");
798 return;
799 }
800
801 if (argvars[1].v_type == VAR_UNKNOWN)
802 maxdepth = 999999;
803 else
804 {
805 maxdepth = (long)tv_get_number_chk(&argvars[1], &error);
806 if (error)
807 return;
808 if (maxdepth < 0)
809 {
810 emsg(_("E900: maxdepth must be non-negative number"));
811 return;
812 }
813 }
814
815 l = argvars[0].vval.v_list;
816 if (l != NULL && !var_check_lock(l->lv_lock,
817 (char_u *)N_("flatten() argument"), TRUE)
818 && list_flatten(l, maxdepth) == OK)
819 copy_tv(&argvars[0], rettv);
731 } 820 }
732 821
733 /* 822 /*
734 * Extend "l1" with "l2". 823 * Extend "l1" with "l2".
735 * If "bef" is NULL append at the end, otherwise insert before this item. 824 * If "bef" is NULL append at the end, otherwise insert before this item.