summaryrefslogtreecommitdiffstats
path: root/src/evalfunc.c
diff options
context:
space:
mode:
authorBakudankun <bakudankun@gmail.com>2022-09-09 18:46:47 +0100
committerBram Moolenaar <Bram@vim.org>2022-09-09 18:46:47 +0100
commit375141e1f80dced9be738568a3418f65813f4a2f (patch)
treebe23086bf0c21bbf564b42298909d856ac6780cf /src/evalfunc.c
parent0adae2da17598669e442ba38547ab18a6c1406de (diff)
patch 9.0.0430: cannot use repeat() with a blobv9.0.0430
Problem: Cannot use repeat() with a blob. Solution: Implement blob repeat. (closes #11090)
Diffstat (limited to 'src/evalfunc.c')
-rw-r--r--src/evalfunc.c41
1 files changed, 38 insertions, 3 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 2c041fa6de..bc0e23e9c8 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -872,6 +872,7 @@ arg_repeat1(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
|| type->tt_type == VAR_UNKNOWN
|| type->tt_type == VAR_STRING
|| type->tt_type == VAR_NUMBER
+ || type->tt_type == VAR_BLOB
|| type->tt_type == VAR_LIST)
return OK;
@@ -4400,6 +4401,10 @@ f_foreground(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
#endif
}
+/*
+ * "function()" function
+ * "funcref()" function
+ */
static void
common_function(typval_T *argvars, typval_T *rettv, int is_funcref)
{
@@ -8399,18 +8404,19 @@ f_rename(typval_T *argvars, typval_T *rettv)
f_repeat(typval_T *argvars, typval_T *rettv)
{
char_u *p;
- int n;
+ varnumber_T n;
int slen;
int len;
char_u *r;
int i;
if (in_vim9script()
- && (check_for_string_or_number_or_list_arg(argvars, 0) == FAIL
+ && (check_for_string_or_number_or_list_or_blob_arg(argvars, 0)
+ == FAIL
|| check_for_number_arg(argvars, 1) == FAIL))
return;
- n = (int)tv_get_number(&argvars[1]);
+ n = tv_get_number(&argvars[1]);
if (argvars[0].v_type == VAR_LIST)
{
if (rettv_list_alloc(rettv) == OK && argvars[0].vval.v_list != NULL)
@@ -8419,6 +8425,35 @@ f_repeat(typval_T *argvars, typval_T *rettv)
argvars[0].vval.v_list, NULL) == FAIL)
break;
}
+ else if (argvars[0].v_type == VAR_BLOB)
+ {
+ if (rettv_blob_alloc(rettv) == FAIL
+ || argvars[0].vval.v_blob == NULL
+ || n <= 0)
+ return;
+
+ slen = argvars[0].vval.v_blob->bv_ga.ga_len;
+ len = (int)slen * n;
+ if (len <= 0)
+ return;
+
+ if (ga_grow(&rettv->vval.v_blob->bv_ga, len) == FAIL)
+ return;
+
+ rettv->vval.v_blob->bv_ga.ga_len = len;
+
+ for (i = 0; i < slen; ++i)
+ if (blob_get(argvars[0].vval.v_blob, i) != 0)
+ break;
+
+ if (i == slen)
+ // No need to copy since all bytes are already zero
+ return;
+
+ for (i = 0; i < n; ++i)
+ blob_set_range(rettv->vval.v_blob,
+ (long)i * slen, ((long)i + 1) * slen - 1, argvars);
+ }
else
{
p = tv_get_string(&argvars[0]);