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)