Mercurial > vim
comparison src/list.c @ 17970:684a15da9929 v8.1.1981
patch 8.1.1981: the evalfunc.c file is too big
Commit: https://github.com/vim/vim/commit/08c308aeb5e7dfa18fa61f261b0bff79517a4883
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Sep 4 17:48:15 2019 +0200
patch 8.1.1981: the evalfunc.c file is too big
Problem: The evalfunc.c file is too big.
Solution: Move undo functions to undo.c. Move cmdline functions to
ex_getln.c. Move some container functions to list.c.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 04 Sep 2019 18:00:03 +0200 |
parents | 6d4d3bce365d |
children | f41b55f9357c |
comparison
equal
deleted
inserted
replaced
17969:bfc33cda9075 | 17970:684a15da9929 |
---|---|
6 * Do ":help credits" in Vim to see a list of people who contributed. | 6 * Do ":help credits" in Vim to see a list of people who contributed. |
7 * See README.txt for an overview of the Vim source code. | 7 * See README.txt for an overview of the Vim source code. |
8 */ | 8 */ |
9 | 9 |
10 /* | 10 /* |
11 * list.c: List support | 11 * list.c: List support and container (List, Dict, Blob) functions. |
12 */ | 12 */ |
13 | 13 |
14 #include "vim.h" | 14 #include "vim.h" |
15 | 15 |
16 #if defined(FEAT_EVAL) || defined(PROTO) | 16 #if defined(FEAT_EVAL) || defined(PROTO) |
17 | |
18 static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob"); | |
17 | 19 |
18 /* List heads for garbage collection. */ | 20 /* List heads for garbage collection. */ |
19 static list_T *first_list = NULL; /* list of all lists */ | 21 static list_T *first_list = NULL; /* list of all lists */ |
20 | 22 |
21 /* | 23 /* |
1761 f_map(typval_T *argvars, typval_T *rettv) | 1763 f_map(typval_T *argvars, typval_T *rettv) |
1762 { | 1764 { |
1763 filter_map(argvars, rettv, TRUE); | 1765 filter_map(argvars, rettv, TRUE); |
1764 } | 1766 } |
1765 | 1767 |
1768 /* | |
1769 * "add(list, item)" function | |
1770 */ | |
1771 void | |
1772 f_add(typval_T *argvars, typval_T *rettv) | |
1773 { | |
1774 list_T *l; | |
1775 blob_T *b; | |
1776 | |
1777 rettv->vval.v_number = 1; /* Default: Failed */ | |
1778 if (argvars[0].v_type == VAR_LIST) | |
1779 { | |
1780 if ((l = argvars[0].vval.v_list) != NULL | |
1781 && !var_check_lock(l->lv_lock, | |
1782 (char_u *)N_("add() argument"), TRUE) | |
1783 && list_append_tv(l, &argvars[1]) == OK) | |
1784 copy_tv(&argvars[0], rettv); | |
1785 } | |
1786 else if (argvars[0].v_type == VAR_BLOB) | |
1787 { | |
1788 if ((b = argvars[0].vval.v_blob) != NULL | |
1789 && !var_check_lock(b->bv_lock, | |
1790 (char_u *)N_("add() argument"), TRUE)) | |
1791 { | |
1792 int error = FALSE; | |
1793 varnumber_T n = tv_get_number_chk(&argvars[1], &error); | |
1794 | |
1795 if (!error) | |
1796 { | |
1797 ga_append(&b->bv_ga, (int)n); | |
1798 copy_tv(&argvars[0], rettv); | |
1799 } | |
1800 } | |
1801 } | |
1802 else | |
1803 emsg(_(e_listblobreq)); | |
1804 } | |
1805 | |
1806 /* | |
1807 * "count()" function | |
1808 */ | |
1809 void | |
1810 f_count(typval_T *argvars, typval_T *rettv) | |
1811 { | |
1812 long n = 0; | |
1813 int ic = FALSE; | |
1814 int error = FALSE; | |
1815 | |
1816 if (argvars[2].v_type != VAR_UNKNOWN) | |
1817 ic = (int)tv_get_number_chk(&argvars[2], &error); | |
1818 | |
1819 if (argvars[0].v_type == VAR_STRING) | |
1820 { | |
1821 char_u *expr = tv_get_string_chk(&argvars[1]); | |
1822 char_u *p = argvars[0].vval.v_string; | |
1823 char_u *next; | |
1824 | |
1825 if (!error && expr != NULL && *expr != NUL && p != NULL) | |
1826 { | |
1827 if (ic) | |
1828 { | |
1829 size_t len = STRLEN(expr); | |
1830 | |
1831 while (*p != NUL) | |
1832 { | |
1833 if (MB_STRNICMP(p, expr, len) == 0) | |
1834 { | |
1835 ++n; | |
1836 p += len; | |
1837 } | |
1838 else | |
1839 MB_PTR_ADV(p); | |
1840 } | |
1841 } | |
1842 else | |
1843 while ((next = (char_u *)strstr((char *)p, (char *)expr)) | |
1844 != NULL) | |
1845 { | |
1846 ++n; | |
1847 p = next + STRLEN(expr); | |
1848 } | |
1849 } | |
1850 | |
1851 } | |
1852 else if (argvars[0].v_type == VAR_LIST) | |
1853 { | |
1854 listitem_T *li; | |
1855 list_T *l; | |
1856 long idx; | |
1857 | |
1858 if ((l = argvars[0].vval.v_list) != NULL) | |
1859 { | |
1860 li = l->lv_first; | |
1861 if (argvars[2].v_type != VAR_UNKNOWN) | |
1862 { | |
1863 if (argvars[3].v_type != VAR_UNKNOWN) | |
1864 { | |
1865 idx = (long)tv_get_number_chk(&argvars[3], &error); | |
1866 if (!error) | |
1867 { | |
1868 li = list_find(l, idx); | |
1869 if (li == NULL) | |
1870 semsg(_(e_listidx), idx); | |
1871 } | |
1872 } | |
1873 if (error) | |
1874 li = NULL; | |
1875 } | |
1876 | |
1877 for ( ; li != NULL; li = li->li_next) | |
1878 if (tv_equal(&li->li_tv, &argvars[1], ic, FALSE)) | |
1879 ++n; | |
1880 } | |
1881 } | |
1882 else if (argvars[0].v_type == VAR_DICT) | |
1883 { | |
1884 int todo; | |
1885 dict_T *d; | |
1886 hashitem_T *hi; | |
1887 | |
1888 if ((d = argvars[0].vval.v_dict) != NULL) | |
1889 { | |
1890 if (argvars[2].v_type != VAR_UNKNOWN) | |
1891 { | |
1892 if (argvars[3].v_type != VAR_UNKNOWN) | |
1893 emsg(_(e_invarg)); | |
1894 } | |
1895 | |
1896 todo = error ? 0 : (int)d->dv_hashtab.ht_used; | |
1897 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) | |
1898 { | |
1899 if (!HASHITEM_EMPTY(hi)) | |
1900 { | |
1901 --todo; | |
1902 if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic, FALSE)) | |
1903 ++n; | |
1904 } | |
1905 } | |
1906 } | |
1907 } | |
1908 else | |
1909 semsg(_(e_listdictarg), "count()"); | |
1910 rettv->vval.v_number = n; | |
1911 } | |
1912 | |
1913 /* | |
1914 * "extend(list, list [, idx])" function | |
1915 * "extend(dict, dict [, action])" function | |
1916 */ | |
1917 void | |
1918 f_extend(typval_T *argvars, typval_T *rettv) | |
1919 { | |
1920 char_u *arg_errmsg = (char_u *)N_("extend() argument"); | |
1921 | |
1922 if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) | |
1923 { | |
1924 list_T *l1, *l2; | |
1925 listitem_T *item; | |
1926 long before; | |
1927 int error = FALSE; | |
1928 | |
1929 l1 = argvars[0].vval.v_list; | |
1930 l2 = argvars[1].vval.v_list; | |
1931 if (l1 != NULL && !var_check_lock(l1->lv_lock, arg_errmsg, TRUE) | |
1932 && l2 != NULL) | |
1933 { | |
1934 if (argvars[2].v_type != VAR_UNKNOWN) | |
1935 { | |
1936 before = (long)tv_get_number_chk(&argvars[2], &error); | |
1937 if (error) | |
1938 return; /* type error; errmsg already given */ | |
1939 | |
1940 if (before == l1->lv_len) | |
1941 item = NULL; | |
1942 else | |
1943 { | |
1944 item = list_find(l1, before); | |
1945 if (item == NULL) | |
1946 { | |
1947 semsg(_(e_listidx), before); | |
1948 return; | |
1949 } | |
1950 } | |
1951 } | |
1952 else | |
1953 item = NULL; | |
1954 list_extend(l1, l2, item); | |
1955 | |
1956 copy_tv(&argvars[0], rettv); | |
1957 } | |
1958 } | |
1959 else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT) | |
1960 { | |
1961 dict_T *d1, *d2; | |
1962 char_u *action; | |
1963 int i; | |
1964 | |
1965 d1 = argvars[0].vval.v_dict; | |
1966 d2 = argvars[1].vval.v_dict; | |
1967 if (d1 != NULL && !var_check_lock(d1->dv_lock, arg_errmsg, TRUE) | |
1968 && d2 != NULL) | |
1969 { | |
1970 /* Check the third argument. */ | |
1971 if (argvars[2].v_type != VAR_UNKNOWN) | |
1972 { | |
1973 static char *(av[]) = {"keep", "force", "error"}; | |
1974 | |
1975 action = tv_get_string_chk(&argvars[2]); | |
1976 if (action == NULL) | |
1977 return; /* type error; errmsg already given */ | |
1978 for (i = 0; i < 3; ++i) | |
1979 if (STRCMP(action, av[i]) == 0) | |
1980 break; | |
1981 if (i == 3) | |
1982 { | |
1983 semsg(_(e_invarg2), action); | |
1984 return; | |
1985 } | |
1986 } | |
1987 else | |
1988 action = (char_u *)"force"; | |
1989 | |
1990 dict_extend(d1, d2, action); | |
1991 | |
1992 copy_tv(&argvars[0], rettv); | |
1993 } | |
1994 } | |
1995 else | |
1996 semsg(_(e_listdictarg), "extend()"); | |
1997 } | |
1998 | |
1999 /* | |
2000 * "insert()" function | |
2001 */ | |
2002 void | |
2003 f_insert(typval_T *argvars, typval_T *rettv) | |
2004 { | |
2005 long before = 0; | |
2006 listitem_T *item; | |
2007 list_T *l; | |
2008 int error = FALSE; | |
2009 | |
2010 if (argvars[0].v_type == VAR_BLOB) | |
2011 { | |
2012 int val, len; | |
2013 char_u *p; | |
2014 | |
2015 len = blob_len(argvars[0].vval.v_blob); | |
2016 if (argvars[2].v_type != VAR_UNKNOWN) | |
2017 { | |
2018 before = (long)tv_get_number_chk(&argvars[2], &error); | |
2019 if (error) | |
2020 return; // type error; errmsg already given | |
2021 if (before < 0 || before > len) | |
2022 { | |
2023 semsg(_(e_invarg2), tv_get_string(&argvars[2])); | |
2024 return; | |
2025 } | |
2026 } | |
2027 val = tv_get_number_chk(&argvars[1], &error); | |
2028 if (error) | |
2029 return; | |
2030 if (val < 0 || val > 255) | |
2031 { | |
2032 semsg(_(e_invarg2), tv_get_string(&argvars[1])); | |
2033 return; | |
2034 } | |
2035 | |
2036 if (ga_grow(&argvars[0].vval.v_blob->bv_ga, 1) == FAIL) | |
2037 return; | |
2038 p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data; | |
2039 mch_memmove(p + before + 1, p + before, (size_t)len - before); | |
2040 *(p + before) = val; | |
2041 ++argvars[0].vval.v_blob->bv_ga.ga_len; | |
2042 | |
2043 copy_tv(&argvars[0], rettv); | |
2044 } | |
2045 else if (argvars[0].v_type != VAR_LIST) | |
2046 semsg(_(e_listblobarg), "insert()"); | |
2047 else if ((l = argvars[0].vval.v_list) != NULL | |
2048 && !var_check_lock(l->lv_lock, | |
2049 (char_u *)N_("insert() argument"), TRUE)) | |
2050 { | |
2051 if (argvars[2].v_type != VAR_UNKNOWN) | |
2052 before = (long)tv_get_number_chk(&argvars[2], &error); | |
2053 if (error) | |
2054 return; /* type error; errmsg already given */ | |
2055 | |
2056 if (before == l->lv_len) | |
2057 item = NULL; | |
2058 else | |
2059 { | |
2060 item = list_find(l, before); | |
2061 if (item == NULL) | |
2062 { | |
2063 semsg(_(e_listidx), before); | |
2064 l = NULL; | |
2065 } | |
2066 } | |
2067 if (l != NULL) | |
2068 { | |
2069 list_insert_tv(l, &argvars[1], item); | |
2070 copy_tv(&argvars[0], rettv); | |
2071 } | |
2072 } | |
2073 } | |
2074 | |
2075 /* | |
2076 * "remove()" function | |
2077 */ | |
2078 void | |
2079 f_remove(typval_T *argvars, typval_T *rettv) | |
2080 { | |
2081 char_u *arg_errmsg = (char_u *)N_("remove() argument"); | |
2082 | |
2083 if (argvars[0].v_type == VAR_DICT) | |
2084 dict_remove(argvars, rettv, arg_errmsg); | |
2085 else if (argvars[0].v_type == VAR_BLOB) | |
2086 blob_remove(argvars, rettv); | |
2087 else if (argvars[0].v_type == VAR_LIST) | |
2088 list_remove(argvars, rettv, arg_errmsg); | |
2089 else | |
2090 semsg(_(e_listdictblobarg), "remove()"); | |
2091 } | |
2092 | |
2093 /* | |
2094 * "reverse({list})" function | |
2095 */ | |
2096 void | |
2097 f_reverse(typval_T *argvars, typval_T *rettv) | |
2098 { | |
2099 list_T *l; | |
2100 listitem_T *li, *ni; | |
2101 | |
2102 if (argvars[0].v_type == VAR_BLOB) | |
2103 { | |
2104 blob_T *b = argvars[0].vval.v_blob; | |
2105 int i, len = blob_len(b); | |
2106 | |
2107 for (i = 0; i < len / 2; i++) | |
2108 { | |
2109 int tmp = blob_get(b, i); | |
2110 | |
2111 blob_set(b, i, blob_get(b, len - i - 1)); | |
2112 blob_set(b, len - i - 1, tmp); | |
2113 } | |
2114 rettv_blob_set(rettv, b); | |
2115 return; | |
2116 } | |
2117 | |
2118 if (argvars[0].v_type != VAR_LIST) | |
2119 semsg(_(e_listblobarg), "reverse()"); | |
2120 else if ((l = argvars[0].vval.v_list) != NULL | |
2121 && !var_check_lock(l->lv_lock, | |
2122 (char_u *)N_("reverse() argument"), TRUE)) | |
2123 { | |
2124 li = l->lv_last; | |
2125 l->lv_first = l->lv_last = NULL; | |
2126 l->lv_len = 0; | |
2127 while (li != NULL) | |
2128 { | |
2129 ni = li->li_prev; | |
2130 list_append(l, li); | |
2131 li = ni; | |
2132 } | |
2133 rettv_list_set(rettv, l); | |
2134 l->lv_idx = l->lv_len - l->lv_idx - 1; | |
2135 } | |
2136 } | |
2137 | |
1766 #endif // defined(FEAT_EVAL) | 2138 #endif // defined(FEAT_EVAL) |