diff options
author | Yegappan Lakshmanan <yegappan@yahoo.com> | 2021-12-22 18:19:26 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-12-22 18:19:26 +0000 |
commit | f973eeb4911de09258e84cb2248dc0f9392824b4 (patch) | |
tree | 81ac7737af13f9eff0d6b69306b7ed6691d23804 /src/list.c | |
parent | 1aeccdb464d81f0af047b399cbad160307a91f7c (diff) | |
download | vim-git-f973eeb4911de09258e84cb2248dc0f9392824b4.tar.gz |
patch 8.2.3871: list.c contains code for dict and blobv8.2.3871
Problem: List.c contains code for dict and blob.
Solution: Refactor to put code where it belongs. (Yegappan Lakshmanan,
closes #9386)
Diffstat (limited to 'src/list.c')
-rw-r--r-- | src/list.c | 969 |
1 files changed, 196 insertions, 773 deletions
diff --git a/src/list.c b/src/list.c index 57a1a5274..61a26a35d 100644 --- a/src/list.c +++ b/src/list.c @@ -314,28 +314,6 @@ listitem_alloc(void) } /* - * Make a typval_T of the first character of "input" and store it in "output". - * Return OK or FAIL. - */ - static int -tv_get_first_char(char_u *input, typval_T *output) -{ - char_u buf[MB_MAXBYTES + 1]; - int len; - - if (input == NULL || output == NULL) - return FAIL; - - len = has_mbyte ? mb_ptr2len(input) : 1; - STRNCPY(buf, input, len); - buf[len] = NUL; - output->v_type = VAR_STRING; - output->vval.v_string = vim_strsave(buf); - - return output->vval.v_string == NULL ? FAIL : OK; -} - -/* * Free a list item, unless it was allocated together with the list itself. * Does not clear the value. Does not notify watchers. */ @@ -876,9 +854,7 @@ list_assign_range( long idx; type_T *member_type = NULL; - /* - * Check whether any of the list items is locked before making any changes. - */ + // Check whether any of the list items is locked before making any changes. idx = idx1; dest_li = first_li; for (src_li = src->lv_first; src_li != NULL && dest_li != NULL; ) @@ -896,9 +872,7 @@ list_assign_range( && dest->lv_type->tt_member != NULL) member_type = dest->lv_type->tt_member; - /* - * Assign the List values to the list items. - */ + // Assign the List values to the list items. idx = idx1; dest_li = first_li; for (src_li = src->lv_first; src_li != NULL; ) @@ -1725,6 +1699,10 @@ f_list2str(typval_T *argvars, typval_T *rettv) rettv->vval.v_string = ga.ga_data; } +/* + * Remove item argvars[1] from List argvars[0]. If argvars[2] is supplied, then + * remove the range of items from argvars[1] to argvars[2] (inclusive). + */ static void list_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg) { @@ -1733,6 +1711,9 @@ list_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg) listitem_T *li; int error = FALSE; long idx; + long end; + int cnt = 0; + list_T *rl; if ((l = argvars[0].vval.v_list) == NULL || value_check_lock(l->lv_lock, arg_errmsg, TRUE)) @@ -1740,75 +1721,76 @@ list_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg) idx = (long)tv_get_number_chk(&argvars[1], &error); if (error) - ; // type error: do nothing, errmsg already given - else if ((item = list_find(l, idx)) == NULL) + return; // type error: do nothing, errmsg already given + + if ((item = list_find(l, idx)) == NULL) + { semsg(_(e_listidx), idx); - else + return; + } + + if (argvars[2].v_type == VAR_UNKNOWN) { - if (argvars[2].v_type == VAR_UNKNOWN) - { - // Remove one item, return its value. - vimlist_remove(l, item, item); - *rettv = item->li_tv; - list_free_item(l, item); - } - else - { - // Remove range of items, return list with values. - long end = (long)tv_get_number_chk(&argvars[2], &error); + // Remove one item, return its value. + vimlist_remove(l, item, item); + *rettv = item->li_tv; + list_free_item(l, item); + return; + } - if (error) - ; // type error: do nothing - else if ((item2 = list_find(l, end)) == NULL) - semsg(_(e_listidx), end); - else - { - int cnt = 0; + // Remove range of items, return list with values. + end = (long)tv_get_number_chk(&argvars[2], &error); + if (error) + return; // type error: do nothing - for (li = item; li != NULL; li = li->li_next) - { - ++cnt; - if (li == item2) - break; - } - if (li == NULL) // didn't find "item2" after "item" - emsg(_(e_invalid_range)); - else - { - vimlist_remove(l, item, item2); - if (rettv_list_alloc(rettv) == OK) - { - list_T *rl = rettv->vval.v_list; - - if (l->lv_with_items > 0) - { - // need to copy the list items and move the value - while (item != NULL) - { - li = listitem_alloc(); - if (li == NULL) - return; - li->li_tv = item->li_tv; - init_tv(&item->li_tv); - list_append(rl, li); - if (item == item2) - break; - item = item->li_next; - } - } - else - { - rl->lv_first = item; - rl->lv_u.mat.lv_last = item2; - item->li_prev = NULL; - item2->li_next = NULL; - rl->lv_len = cnt; - } - } - } - } + if ((item2 = list_find(l, end)) == NULL) + { + semsg(_(e_listidx), end); + return; + } + + for (li = item; li != NULL; li = li->li_next) + { + ++cnt; + if (li == item2) + break; + } + if (li == NULL) // didn't find "item2" after "item" + { + emsg(_(e_invalid_range)); + return; + } + + vimlist_remove(l, item, item2); + if (rettv_list_alloc(rettv) != OK) + return; + + rl = rettv->vval.v_list; + + if (l->lv_with_items > 0) + { + // need to copy the list items and move the value + while (item != NULL) + { + li = listitem_alloc(); + if (li == NULL) + return; + li->li_tv = item->li_tv; + init_tv(&item->li_tv); + list_append(rl, li); + if (item == item2) + break; + item = item->li_next; } } + else + { + rl->lv_first = item; + rl->lv_u.mat.lv_last = item2; + item->li_prev = NULL; + item2->li_next = NULL; + rl->lv_len = cnt; + } } static int item_compare(const void *s1, const void *s2); @@ -2101,8 +2083,8 @@ do_uniq(list_T *l, sortinfo_T *info) } /* - * Parse the optional arguments to sort() and uniq() and return the values in - * 'info'. + * Parse the optional arguments supplied to the sort() or uniq() function and + * return the values in "info". */ static int parse_sort_uniq_args(typval_T *argvars, sortinfo_T *info) @@ -2272,17 +2254,11 @@ f_uniq(typval_T *argvars, typval_T *rettv) do_sort_uniq(argvars, rettv, FALSE); } -typedef enum { - FILTERMAP_FILTER, - FILTERMAP_MAP, - FILTERMAP_MAPNEW -} filtermap_T; - /* * Handle one item for map() and filter(). * Sets v:val to "tv". Caller must set v:key. */ - static int + int filter_map_one( typval_T *tv, // original value typval_T *expr, // callback @@ -2320,254 +2296,11 @@ theend: } /* - * Implementation of map() and filter() for a Dict. + * Implementation of map() and filter() for a List. Apply "expr" to every item + * in List "l" and return the result in "rettv". */ static void -filter_map_dict( - dict_T *d, - filtermap_T filtermap, - type_T *argtype, - char *func_name, - char_u *arg_errmsg, - typval_T *expr, - typval_T *rettv) -{ - int prev_lock; - dict_T *d_ret = NULL; - hashtab_T *ht; - hashitem_T *hi; - dictitem_T *di; - int todo; - int rem; - - if (filtermap == FILTERMAP_MAPNEW) - { - rettv->v_type = VAR_DICT; - rettv->vval.v_dict = NULL; - } - if (d == NULL - || (filtermap == FILTERMAP_FILTER - && value_check_lock(d->dv_lock, arg_errmsg, TRUE))) - return; - - prev_lock = d->dv_lock; - - if (filtermap == FILTERMAP_MAPNEW) - { - if (rettv_dict_alloc(rettv) == FAIL) - return; - d_ret = rettv->vval.v_dict; - } - - if (filtermap != FILTERMAP_FILTER && d->dv_lock == 0) - d->dv_lock = VAR_LOCKED; - ht = &d->dv_hashtab; - hash_lock(ht); - todo = (int)ht->ht_used; - for (hi = ht->ht_array; todo > 0; ++hi) - { - if (!HASHITEM_EMPTY(hi)) - { - int r; - typval_T newtv; - - --todo; - di = HI2DI(hi); - if (filtermap == FILTERMAP_MAP - && (value_check_lock(di->di_tv.v_lock, - arg_errmsg, TRUE) - || var_check_ro(di->di_flags, - arg_errmsg, TRUE))) - break; - set_vim_var_string(VV_KEY, di->di_key, -1); - newtv.v_type = VAR_UNKNOWN; - r = filter_map_one(&di->di_tv, expr, filtermap, - &newtv, &rem); - clear_tv(get_vim_var_tv(VV_KEY)); - if (r == FAIL || did_emsg) - { - clear_tv(&newtv); - break; - } - if (filtermap == FILTERMAP_MAP) - { - if (argtype != NULL && check_typval_arg_type( - argtype->tt_member, &newtv, - func_name, 0) == FAIL) - { - clear_tv(&newtv); - break; - } - // map(): replace the dict item value - clear_tv(&di->di_tv); - newtv.v_lock = 0; - di->di_tv = newtv; - } - else if (filtermap == FILTERMAP_MAPNEW) - { - // mapnew(): add the item value to the new dict - r = dict_add_tv(d_ret, (char *)di->di_key, &newtv); - clear_tv(&newtv); - if (r == FAIL) - break; - } - else if (filtermap == FILTERMAP_FILTER && rem) - { - // filter(false): remove the item from the dict - if (var_check_fixed(di->di_flags, arg_errmsg, TRUE) - || var_check_ro(di->di_flags, arg_errmsg, TRUE)) - break; - dictitem_remove(d, di); - } - } - } - hash_unlock(ht); - d->dv_lock = prev_lock; -} - -/* - * Implementation of map() and filter() for a Blob. - */ - static void -filter_map_blob( - blob_T *blob_arg, - filtermap_T filtermap, - typval_T *expr, - typval_T *rettv) -{ - blob_T *b; - int i; - typval_T tv; - varnumber_T val; - blob_T *b_ret; - int idx = 0; - int rem; - - if (filtermap == FILTERMAP_MAPNEW) - { - rettv->v_type = VAR_BLOB; - rettv->vval.v_blob = NULL; - } - if ((b = blob_arg) == NULL) - return; - - b_ret = b; - if (filtermap == FILTERMAP_MAPNEW) - { - if (blob_copy(b, rettv) == FAIL) - return; - b_ret = rettv->vval.v_blob; - } - - // set_vim_var_nr() doesn't set the type - set_vim_var_type(VV_KEY, VAR_NUMBER); - - for (i = 0; i < b->bv_ga.ga_len; i++) - { - typval_T newtv; - - tv.v_type = VAR_NUMBER; - val = blob_get(b, i); - tv.vval.v_number = val; - set_vim_var_nr(VV_KEY, idx); - if (filter_map_one(&tv, expr, filtermap, &newtv, &rem) == FAIL - || did_emsg) - break; - if (newtv.v_type != VAR_NUMBER && newtv.v_type != VAR_BOOL) - { - clear_tv(&newtv); - emsg(_(e_invalblob)); - break; - } - if (filtermap != FILTERMAP_FILTER) - { - if (newtv.vval.v_number != val) - blob_set(b_ret, i, newtv.vval.v_number); - } - else if (rem) - { - char_u *p = (char_u *)blob_arg->bv_ga.ga_data; - - mch_memmove(p + i, p + i + 1, - (size_t)b->bv_ga.ga_len - i - 1); - --b->bv_ga.ga_len; - --i; - } - ++idx; - } -} - -/* - * Implementation of map() and filter() for a String. - */ - static void -filter_map_string( - char_u *str, - filtermap_T filtermap, - typval_T *expr, - typval_T *rettv) -{ - char_u *p; - typval_T tv; - garray_T ga; - int len = 0; - int idx = 0; - int rem; - - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - - // set_vim_var_nr() doesn't set the type - set_vim_var_type(VV_KEY, VAR_NUMBER); - - ga_init2(&ga, (int)sizeof(char), 80); - for (p = str; *p != NUL; p += len) - { - typval_T newtv; - - if (tv_get_first_char(p, &tv) == FAIL) - break; - len = (int)STRLEN(tv.vval.v_string); - - set_vim_var_nr(VV_KEY, idx); - if (filter_map_one(&tv, expr, filtermap, &newtv, &rem) == FAIL - || did_emsg) - break; - if (did_emsg) - { - clear_tv(&newtv); - clear_tv(&tv); - break; - } - else if (filtermap != FILTERMAP_FILTER) - { - if (newtv.v_type != VAR_STRING) - { - clear_tv(&newtv); - clear_tv(&tv); - emsg(_(e_stringreq)); - break; - } - else - ga_concat(&ga, newtv.vval.v_string); - } - else if (!rem) - ga_concat(&ga, tv.vval.v_string); - - clear_tv(&newtv); - clear_tv(&tv); - - ++idx; - } - ga_append(&ga, NUL); - rettv->vval.v_string = ga.ga_data; -} - -/* - * Implementation of map() and filter() for a List. - */ - static void -filter_map_list( +list_filter_map( list_T *l, filtermap_T filtermap, type_T *argtype, @@ -2775,15 +2508,15 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap) did_emsg = FALSE; if (argvars[0].v_type == VAR_DICT) - filter_map_dict(argvars[0].vval.v_dict, filtermap, type, func_name, + dict_filter_map(argvars[0].vval.v_dict, filtermap, type, func_name, arg_errmsg, expr, rettv); else if (argvars[0].v_type == VAR_BLOB) - filter_map_blob(argvars[0].vval.v_blob, filtermap, expr, rettv); + blob_filter_map(argvars[0].vval.v_blob, filtermap, expr, rettv); else if (argvars[0].v_type == VAR_STRING) - filter_map_string(tv_get_string(&argvars[0]), filtermap, expr, + string_filter_map(tv_get_string(&argvars[0]), filtermap, expr, rettv); else // argvars[0].v_type == VAR_LIST - filter_map_list(argvars[0].vval.v_list, filtermap, type, func_name, + list_filter_map(argvars[0].vval.v_list, filtermap, type, func_name, arg_errmsg, expr, rettv); restore_vimvar(VV_KEY, &save_key); @@ -2827,6 +2560,27 @@ f_mapnew(typval_T *argvars, typval_T *rettv) /* * "add(list, item)" function */ + static void +list_add(typval_T *argvars, typval_T *rettv) +{ + list_T *l = argvars[0].vval.v_list; + + if (l == NULL) + { + if (in_vim9script()) + emsg(_(e_cannot_add_to_null_list)); + } + else if (!value_check_lock(l->lv_lock, + (char_u *)N_("add() argument"), TRUE) + && list_append_tv(l, &argvars[1]) == OK) + { + copy_tv(&argvars[0], rettv); + } +} + +/* + * "add(object, item)" function + */ void f_add(typval_T *argvars, typval_T *rettv) { @@ -2839,92 +2593,19 @@ f_add(typval_T *argvars, typval_T *rettv) return; if (argvars[0].v_type == VAR_LIST) - { - list_T *l = argvars[0].vval.v_list; - - if (l == NULL) - { - if (in_vim9script()) - emsg(_(e_cannot_add_to_null_list)); - } - else if (!value_check_lock(l->lv_lock, - (char_u *)N_("add() argument"), TRUE) - && list_append_tv(l, &argvars[1]) == OK) - { - copy_tv(&argvars[0], rettv); - } - } + list_add(argvars, rettv); else if (argvars[0].v_type == VAR_BLOB) - { - blob_T *b = argvars[0].vval.v_blob; - - if (b == NULL) - { - if (in_vim9script()) - emsg(_(e_cannot_add_to_null_blob)); - } - else if (!value_check_lock(b->bv_lock, - (char_u *)N_("add() argument"), TRUE)) - { - int error = FALSE; - varnumber_T n = tv_get_number_chk(&argvars[1], &error); - - if (!error) - { - ga_append(&b->bv_ga, (int)n); - copy_tv(&argvars[0], rettv); - } - } - } + blob_add(argvars, rettv); else emsg(_(e_listblobreq)); } /* - * Count the number of times "needle" occurs in string "haystack". Case is - * ignored if "ic" is TRUE. - */ - static long -count_string(char_u *haystack, char_u *needle, int ic) -{ - long n = 0; - char_u *p = haystack; - char_u *next; - - if (p == NULL || needle == NULL || *needle == NUL) - return 0; - - if (ic) - { - size_t len = STRLEN(needle); - - while (*p != NUL) - { - if (MB_STRNICMP(p, needle, len) == 0) - { - ++n; - p += len; - } - else - MB_PTR_ADV(p); - } - } - else - while ((next = (char_u *)strstr((char *)p, (char *)needle)) != NULL) - { - ++n; - p = next + STRLEN(needle); - } - - return n; -} - -/* * Count the number of times item "needle" occurs in List "l" starting at index * "idx". Case is ignored if "ic" is TRUE. */ static long -count_list(list_T *l, typval_T *needle, long idx, int ic) +list_count(list_T *l, typval_T *needle, long idx, int ic) { long n = 0; listitem_T *li; @@ -2952,34 +2633,6 @@ count_list(list_T *l, typval_T *needle, long idx, int ic) } /* - * Count the number of times item "needle" occurs in Dict "d". Case is ignored - * if "ic" is TRUE. - */ - static long -count_dict(dict_T *d, typval_T *needle, int ic) -{ - int todo; - hashitem_T *hi; - long n = 0; - - if (d == NULL) - return 0; - - todo = (int)d->dv_hashtab.ht_used; - for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) - { - if (!HASHITEM_EMPTY(hi)) - { - --todo; - if (tv_equal(&HI2DI(hi)->di_tv, needle, ic, FALSE)) - ++n; - } - } - - return n; -} - -/* * "count()" function */ void @@ -3000,7 +2653,7 @@ f_count(typval_T *argvars, typval_T *rettv) ic = (int)tv_get_bool_chk(&argvars[2], &error); if (!error && argvars[0].v_type == VAR_STRING) - n = count_string(argvars[0].vval.v_string, + n = string_count(argvars[0].vval.v_string, tv_get_string_chk(&argvars[1]), ic); else if (!error && argvars[0].v_type == VAR_LIST) { @@ -3010,7 +2663,7 @@ f_count(typval_T *argvars, typval_T *rettv) && argvars[3].v_type != VAR_UNKNOWN) idx = (long)tv_get_number_chk(&argvars[3], &error); if (!error) - n = count_list(argvars[0].vval.v_list, &argvars[1], idx, ic); + n = list_count(argvars[0].vval.v_list, &argvars[1], idx, ic); } else if (!error && argvars[0].v_type == VAR_DICT) { @@ -3018,7 +2671,7 @@ f_count(typval_T *argvars, typval_T *rettv) && argvars[3].v_type != VAR_UNKNOWN) emsg(_(e_invarg)); else - n = count_dict(argvars[0].vval.v_dict, &argvars[1], ic); + n = dict_count(argvars[0].vval.v_dict, &argvars[1], ic); } else semsg(_(e_listdictarg), "count()"); @@ -3031,7 +2684,7 @@ f_count(typval_T *argvars, typval_T *rettv) * extendnew(). */ static void -extend_list( +list_extend_func( typval_T *argvars, type_T *type, char *func_name, @@ -3098,76 +2751,6 @@ extend_list( } /* - * extend() a Dict. Append Dict argvars[1] to Dict argvars[0] and return the - * resulting Dict in "rettv". "is_new" is TRUE for extendnew(). - */ - static void -extend_dict( - typval_T *argvars, - type_T *type, - char *func_name, - char_u *arg_errmsg, - int is_new, - typval_T *rettv) -{ - dict_T *d1, *d2; - char_u *action; - int i; - - d1 = argvars[0].vval.v_dict; - if (d1 == NULL) - { - emsg(_(e_cannot_extend_null_dict)); - return; - } - d2 = argvars[1].vval.v_dict; - if ((is_new || !value_check_lock(d1->dv_lock, arg_errmsg, TRUE)) - && d2 != NULL) - { - if (is_new) - { - d1 = dict_copy(d1, FALSE, get_copyID()); - if (d1 == NULL) - return; - } - - // Check the third argument. - if (argvars[2].v_type != VAR_UNKNOWN) - { - static char *(av[]) = {"keep", "force", "error"}; - - action = tv_get_string_chk(&argvars[2]); - if (action == NULL) - return; - for (i = 0; i < 3; ++i) - if (STRCMP(action, av[i]) == 0) - break; - if (i == 3) - { - semsg(_(e_invarg2), action); - return; - } - } - else - action = (char_u *)"force"; - - if (type != NULL && check_typval_arg_type(type, &argvars[1], - func_name, 2) == FAIL) - return; - dict_extend(d1, d2, action, func_name); - - if (is_new) - { - rettv->v_type = VAR_DICT; - rettv->vval.v_dict = d1; - rettv->v_lock = FALSE; - } - else - copy_tv(&argvars[0], rettv); - } -} - -/* * "extend()" or "extendnew()" function. "is_new" is TRUE for extendnew(). */ static void @@ -3185,9 +2768,9 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new) } if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) - extend_list(argvars, type, func_name, arg_errmsg, is_new, rettv); + list_extend_func(argvars, type, func_name, arg_errmsg, is_new, rettv); else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT) - extend_dict(argvars, type, func_name, arg_errmsg, is_new, rettv); + dict_extend_func(argvars, type, func_name, arg_errmsg, is_new, rettv); else semsg(_(e_listdictarg), func_name); @@ -3219,16 +2802,53 @@ f_extendnew(typval_T *argvars, typval_T *rettv) extend(argvars, rettv, errmsg, TRUE); } + static void +list_insert_func(typval_T *argvars, typval_T *rettv) +{ + list_T *l = argvars[0].vval.v_list; + long before = 0; + listitem_T *item; + int error = FALSE; + + if (l == NULL) + { + if (in_vim9script()) + emsg(_(e_cannot_add_to_null_list)); + return; + } + + if (value_check_lock(l->lv_lock, (char_u *)N_("insert() argument"), TRUE)) + return; + + if (argvars[2].v_type != VAR_UNKNOWN) + before = (long)tv_get_number_chk(&argvars[2], &error); + if (error) + return; // type error; errmsg already given + + if (before == l->lv_len) + item = NULL; + else + { + item = list_find(l, before); + if (item == NULL) + { + semsg(_(e_listidx), before); + l = NULL; + } + } + if (l != NULL) + { + (void)list_insert_tv(l, &argvars[1], item); + copy_tv(&argvars[0], rettv); + } +} + /* * "insert()" function */ void f_insert(typval_T *argvars, typval_T *rettv) { - long before = 0; - listitem_T *item; - int error = FALSE; - if (in_vim9script() && (check_for_list_or_blob_arg(argvars, 0) == FAIL || (argvars[0].v_type == VAR_BLOB @@ -3237,88 +2857,11 @@ f_insert(typval_T *argvars, typval_T *rettv) return; if (argvars[0].v_type == VAR_BLOB) - { - blob_T *b = argvars[0].vval.v_blob; - - if (b == NULL) - { - if (in_vim9script()) - emsg(_(e_cannot_add_to_null_blob)); - } - else if (!value_check_lock(b->bv_lock, - (char_u *)N_("insert() argument"), TRUE)) - { - int val, len; - char_u *p; - - len = blob_len(b); - if (argvars[2].v_type != VAR_UNKNOWN) - { - before = (long)tv_get_number_chk(&argvars[2], &error); - if (error) - return; // type error; errmsg already given - if (before < 0 || before > len) - { - semsg(_(e_invarg2), tv_get_string(&argvars[2])); - return; - } - } - val = tv_get_number_chk(&argvars[1], &error); - if (error) - return; - if (val < 0 || val > 255) - { - semsg(_(e_invarg2), tv_get_string(&argvars[1])); - return; - } - - if (ga_grow(&b->bv_ga, 1) == FAIL) - return; - p = (char_u *)b->bv_ga.ga_data; - mch_memmove(p + before + 1, p + before, (size_t)len - before); - *(p + before) = val; - ++b->bv_ga.ga_len; - - copy_tv(&argvars[0], rettv); - } - } + blob_insert_func(argvars, rettv); else if (argvars[0].v_type != VAR_LIST) semsg(_(e_listblobarg), "insert()"); else - { - list_T *l = argvars[0].vval.v_list; - - if (l == NULL) - { - if (in_vim9script()) - emsg(_(e_cannot_add_to_null_list)); - } - else if (!value_check_lock(l->lv_lock, - (char_u *)N_("insert() argument"), TRUE)) - { - if (argvars[2].v_type != VAR_UNKNOWN) - before = (long)tv_get_number_chk(&argvars[2], &error); - if (error) - return; // type error; errmsg already given - - if (before == l->lv_len) - item = NULL; - else - { - item = list_find(l, before); - if (item == NULL) - { - semsg(_(e_listidx), before); - l = NULL; - } - } - if (l != NULL) - { - (void)list_insert_tv(l, &argvars[1], item); - copy_tv(&argvars[0], rettv); - } - } - } + list_insert_func(argvars, rettv); } /* @@ -3349,66 +2892,54 @@ f_remove(typval_T *argvars, typval_T *rettv) semsg(_(e_listdictblobarg), "remove()"); } + static void +list_reverse(list_T *l, typval_T *rettv) +{ + listitem_T *li, *ni; + + rettv_list_set(rettv, l); + if (l != NULL + && !value_check_lock(l->lv_lock, + (char_u *)N_("reverse() argument"), TRUE)) + { + if (l->lv_first == &range_list_item) + { + varnumber_T new_start = l->lv_u.nonmat.lv_start + + (l->lv_len - 1) * l->lv_u.nonmat.lv_stride; + l->lv_u.nonmat.lv_end = new_start + - (l->lv_u.nonmat.lv_end - l->lv_u.nonmat.lv_start); + l->lv_u.nonmat.lv_start = new_start; + l->lv_u.nonmat.lv_stride = -l->lv_u.nonmat.lv_stride; + return; + } + li = l->lv_u.mat.lv_last; + l->lv_first = l->lv_u.mat.lv_last = NULL; + l->lv_len = 0; + while (li != NULL) + { + ni = li->li_prev; + list_append(l, li); + li = ni; + } + l->lv_u.mat.lv_idx = l->lv_len - l->lv_u.mat.lv_idx - 1; + } +} + /* * "reverse({list})" function */ void f_reverse(typval_T *argvars, typval_T *rettv) { - list_T *l; - listitem_T *li, *ni; - if (in_vim9script() && check_for_list_or_blob_arg(argvars, 0) == FAIL) return; if (argvars[0].v_type == VAR_BLOB) - { - blob_T *b = argvars[0].vval.v_blob; - int i, len = blob_len(b); - - for (i = 0; i < len / 2; i++) - { - int tmp = blob_get(b, i); - - blob_set(b, i, blob_get(b, len - i - 1)); - blob_set(b, len - i - 1, tmp); - } - rettv_blob_set(rettv, b); - return; - } - - if (argvars[0].v_type != VAR_LIST) + blob_reverse(argvars[0].vval.v_blob, rettv); + else if (argvars[0].v_type != VAR_LIST) semsg(_(e_listblobarg), "reverse()"); else - { - l = argvars[0].vval.v_list; - rettv_list_set(rettv, l); - if (l != NULL - && !value_check_lock(l->lv_lock, - (char_u *)N_("reverse() argument"), TRUE)) - { - if (l->lv_first == &range_list_item) - { - varnumber_T new_start = l->lv_u.nonmat.lv_start - + (l->lv_len - 1) * l->lv_u.nonmat.lv_stride; - l->lv_u.nonmat.lv_end = new_start - - (l->lv_u.nonmat.lv_end - l->lv_u.nonmat.lv_start); - l->lv_u.nonmat.lv_start = new_start; - l->lv_u.nonmat.lv_stride = -l->lv_u.nonmat.lv_stride; - return; - } - li = l->lv_u.mat.lv_last; - l->lv_first = l->lv_u.mat.lv_last = NULL; - l->lv_len = 0; - while (li != NULL) - { - ni = li->li_prev; - list_append(l, li); - li = ni; - } - l->lv_u.mat.lv_idx = l->lv_len - l->lv_u.mat.lv_idx - 1; - } - } + list_reverse(argvars[0].vval.v_list, rettv); } /* @@ -3417,7 +2948,7 @@ f_reverse(typval_T *argvars, typval_T *rettv) * in 'rettv'. */ static void -reduce_list( +list_reduce( typval_T *argvars, char_u *func_name, funcexe_T *funcexe, @@ -3471,114 +3002,6 @@ reduce_list( } /* - * reduce() String argvars[0] using the function 'funcname' with arguments in - * 'funcexe' starting with the initial value argvars[2] and return the result - * in 'rettv'. - */ - static void -reduce_string( - typval_T *argvars, - char_u *func_name, - funcexe_T *funcexe, - typval_T *rettv) -{ - char_u *p = tv_get_string(&argvars[0]); - int len; - typval_T argv[3]; - int r; - int called_emsg_start = called_emsg; - - if (argvars[2].v_type == VAR_UNKNOWN) - { - if (*p == NUL) - { - semsg(_(e_reduceempty), "String"); - return; - } - if (tv_get_first_char(p, rettv) == FAIL) - return; - p += STRLEN(rettv->vval.v_string); - } - else if (argvars[2].v_type != VAR_STRING) - { - semsg(_(e_string_expected_for_argument_nr), 3); - return; - } - else - copy_tv(&argvars[2], rettv); - - for ( ; *p != NUL; p += len) - { - argv[0] = *rettv; - if (tv_get_first_char(p, &argv[1]) == FAIL) - break; - len = (int)STRLEN(argv[1].vval.v_string); - r = call_func(func_name, -1, rettv, 2, argv, funcexe); - clear_tv(&argv[0]); - clear_tv(&argv[1]); - if (r == FAIL || called_emsg != called_emsg_start) - return; - } -} - -/* - * reduce() Blob argvars[0] using the function 'funcname' with arguments in - * 'funcexe' starting with the initial value argvars[2] and return the result - * in 'rettv'. - */ - static void -reduce_blob( - typval_T *argvars, - char_u *func_name, - funcexe_T *funcexe, - typval_T *rettv) -{ - blob_T *b = argvars[0].vval.v_blob; - int called_emsg_start = called_emsg; - int r; - typval_T initial; - typval_T argv[3]; - int i; - - if (argvars[2].v_type == VAR_UNKNOWN) - { - if (b == NULL || b->bv_ga.ga_len == 0) - { - semsg(_(e_reduceempty), "Blob"); - return; - } - initial.v_type = VAR_NUMBER; - initial.vval.v_number = blob_get(b, 0); - i = 1; - } - else if (argvars[2].v_type != VAR_NUMBER) - { - emsg(_(e_number_expected)); - return; - } - else - { - initial = argvars[2]; - i = 0; - } - - copy_tv(&initial, rettv); - if (b == NULL) - return; - - for ( ; i < b->bv_ga.ga_len; i++) - { - argv[0] = *rettv; - argv[1].v_type = VAR_NUMBER; - argv[1].vval.v_number = blob_get(b, i); - r = call_func(func_name, -1, rettv, 2, argv, funcexe); - clear_tv(&argv[0]); - if (r == FAIL || called_emsg != called_emsg_start) - return; - } -} - -/* * "reduce(list, { accumulator, element -> value } [, initial])" function * "reduce(blob, { accumulator, element -> value } [, initial])" * "reduce(string, { accumulator, element -> value } [, initial])" @@ -3622,11 +3045,11 @@ f_reduce(typval_T *argvars, typval_T *rettv) funcexe.fe_partial = partial; if (argvars[0].v_type == VAR_LIST) - reduce_list(argvars, func_name, &funcexe, rettv); + list_reduce(argvars, func_name, &funcexe, rettv); else if (argvars[0].v_type == VAR_STRING) - reduce_string(argvars, func_name, &funcexe, rettv); + string_reduce(argvars, func_name, &funcexe, rettv); else - reduce_blob(argvars, func_name, &funcexe, rettv); + blob_reduce(argvars, func_name, &funcexe, rettv); } #endif // defined(FEAT_EVAL) |