Mercurial > vim
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. |