To: vim_dev@googlegroups.com Subject: Patch 9.0.0430 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.0430 Problem: Cannot use repeat() with a blob. Solution: Implement blob repeat. (closes #11090) Files: runtime/doc/builtin.txt, src/errors.h, src/evalfunc.c, src/typval.c, src/proto/typval.pro, src/testdir/test_blob.vim, src/testdir/test_vim9_builtin.vim, src/testdir/test_vim9_func.vim *** ../vim-9.0.0429/runtime/doc/builtin.txt 2022-09-07 21:30:40.139379052 +0100 --- runtime/doc/builtin.txt 2022-09-09 18:21:48.346091765 +0100 *************** *** 471,477 **** remove bytes {idx}-{end} from {blob} remove({dict}, {key}) any remove entry {key} from {dict} rename({from}, {to}) Number rename (move) file from {from} to {to} ! repeat({expr}, {count}) String repeat {expr} {count} times resolve({filename}) String get filename a shortcut points to reverse({list}) List reverse {list} in-place round({expr}) Float round off {expr} --- 471,478 ---- remove bytes {idx}-{end} from {blob} remove({dict}, {key}) any remove entry {key} from {dict} rename({from}, {to}) Number rename (move) file from {from} to {to} ! repeat({expr}, {count}) List/Blob/String ! repeat {expr} {count} times resolve({filename}) String get filename a shortcut points to reverse({list}) List reverse {list} in-place round({expr}) Float round off {expr} *************** *** 7284,7291 **** result. Example: > :let separator = repeat('-', 80) < When {count} is zero or negative the result is empty. ! When {expr} is a |List| the result is {expr} concatenated ! {count} times. Example: > :let longlist = repeat(['a', 'b'], 3) < Results in ['a', 'b', 'a', 'b', 'a', 'b']. --- 7295,7302 ---- result. Example: > :let separator = repeat('-', 80) < When {count} is zero or negative the result is empty. ! When {expr} is a |List| or a |Blob| the result is {expr} ! concatenated {count} times. Example: > :let longlist = repeat(['a', 'b'], 3) < Results in ['a', 'b', 'a', 'b', 'a', 'b']. *** ../vim-9.0.0429/src/errors.h 2022-09-05 21:21:21.135941382 +0100 --- src/errors.h 2022-09-09 18:25:20.473676112 +0100 *************** *** 3329,3332 **** --- 3329,3334 ---- #ifdef FEAT_EVAL EXTERN char e_cannot_use_partial_with_dictionary_for_defer[] INIT(= N_("E1300: Cannot use a partial with dictionary for :defer")); + EXTERN char e_string_number_list_or_blob_required_for_argument_nr[] + INIT(= N_("E1301: String, Number, List or Blob required for argument %d")); #endif *** ../vim-9.0.0429/src/evalfunc.c 2022-09-04 12:29:22.144893115 +0100 --- src/evalfunc.c 2022-09-09 18:29:07.821193375 +0100 *************** *** 872,877 **** --- 872,878 ---- || 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,4405 **** --- 4401,4410 ---- #endif } + /* + * "function()" function + * "funcref()" function + */ static void common_function(typval_T *argvars, typval_T *rettv, int is_funcref) { *************** *** 8399,8416 **** f_repeat(typval_T *argvars, typval_T *rettv) { char_u *p; ! int 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_number_arg(argvars, 1) == FAIL)) return; ! n = (int)tv_get_number(&argvars[1]); if (argvars[0].v_type == VAR_LIST) { if (rettv_list_alloc(rettv) == OK && argvars[0].vval.v_list != NULL) --- 8404,8422 ---- f_repeat(typval_T *argvars, typval_T *rettv) { char_u *p; ! varnumber_T n; int slen; int len; char_u *r; int i; if (in_vim9script() ! && (check_for_string_or_number_or_list_or_blob_arg(argvars, 0) ! == FAIL || check_for_number_arg(argvars, 1) == FAIL)) return; ! 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,8424 **** --- 8425,8459 ---- 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]); *** ../vim-9.0.0429/src/typval.c 2022-09-01 12:22:19.747659165 +0100 --- src/typval.c 2022-09-09 18:21:48.350091758 +0100 *************** *** 792,797 **** --- 792,815 ---- } /* + * Give an error and return FAIL unless "args[idx]" is a string or a number + * or a list or a blob. + */ + int + check_for_string_or_number_or_list_or_blob_arg(typval_T *args, int idx) + { + if (args[idx].v_type != VAR_STRING + && args[idx].v_type != VAR_NUMBER + && args[idx].v_type != VAR_LIST + && args[idx].v_type != VAR_BLOB) + { + semsg(_(e_string_number_list_or_blob_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; + } + + /* * Give an error and return FAIL unless "args[idx]" is a string or a list * or a dict. */ *** ../vim-9.0.0429/src/proto/typval.pro 2022-09-01 12:22:19.747659165 +0100 --- src/proto/typval.pro 2022-09-09 18:38:24.503922543 +0100 *************** *** 42,47 **** --- 42,48 ---- int check_for_string_or_dict_arg(typval_T *args, int idx); int check_for_string_or_number_or_list_arg(typval_T *args, int idx); int check_for_opt_string_or_number_or_list_arg(typval_T *args, int idx); + int check_for_string_or_number_or_list_or_blob_arg(typval_T *args, int idx); int check_for_string_or_list_or_dict_arg(typval_T *args, int idx); int check_for_string_or_func_arg(typval_T *args, int idx); int check_for_list_or_blob_arg(typval_T *args, int idx); *** ../vim-9.0.0429/src/testdir/test_blob.vim 2022-08-14 12:07:06.918862666 +0100 --- src/testdir/test_blob.vim 2022-09-09 18:43:44.291164347 +0100 *************** *** 725,730 **** --- 725,742 ---- call assert_equal(v, string(b)) endfunc + func Test_blob_repeat() + call assert_equal(0z, repeat(0z00, 0)) + call assert_equal(0z00, repeat(0z00, 1)) + call assert_equal(0z0000, repeat(0z00, 2)) + call assert_equal(0z00000000, repeat(0z0000, 2)) + + call assert_equal(0z, repeat(0z12, 0)) + call assert_equal(0z, repeat(0z1234, 0)) + call assert_equal(0z1234, repeat(0z1234, 1)) + call assert_equal(0z12341234, repeat(0z1234, 2)) + endfunc + " Test for blob allocation failure func Test_blob_alloc_failure() " blob variable *** ../vim-9.0.0429/src/testdir/test_vim9_builtin.vim 2022-09-02 15:15:11.067569180 +0100 --- src/testdir/test_vim9_builtin.vim 2022-09-09 18:25:49.801615672 +0100 *************** *** 3329,3340 **** enddef def Test_repeat() ! v9.CheckDefAndScriptFailure(['repeat(1.1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1224: String, Number or List required for argument 1']) ! v9.CheckDefAndScriptFailure(['repeat({a: 10}, 2)'], ['E1013: Argument 1: type mismatch, expected string but got dict<', 'E1224: String, Number or List required for argument 1']) var lines =<< trim END assert_equal('aaa', repeat('a', 3)) assert_equal('111', repeat(1, 3)) assert_equal([1, 1, 1], repeat([1], 3)) var s = '-' s ..= repeat(5, 3) assert_equal('-555', s) --- 3329,3342 ---- enddef def Test_repeat() ! v9.CheckDefAndScriptFailure(['repeat(1.1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1301: String, Number, List or Blob required for argument 1']) ! v9.CheckDefAndScriptFailure(['repeat({a: 10}, 2)'], ['E1013: Argument 1: type mismatch, expected string but got dict<', 'E1301: String, Number, List or Blob required for argument 1']) var lines =<< trim END assert_equal('aaa', repeat('a', 3)) assert_equal('111', repeat(1, 3)) assert_equal([1, 1, 1], repeat([1], 3)) + assert_equal(0z000102000102000102, repeat(0z000102, 3)) + assert_equal(0z000000, repeat(0z00, 3)) var s = '-' s ..= repeat(5, 3) assert_equal('-555', s) *** ../vim-9.0.0429/src/testdir/test_vim9_func.vim 2022-09-03 21:35:50.188158217 +0100 --- src/testdir/test_vim9_func.vim 2022-09-09 18:21:48.350091758 +0100 *************** *** 2534,2539 **** --- 2534,2545 ---- res->assert_equal(3) res = 0 + for n in repeat(0z01, 3)->blob2list() + res += n + endfor + res->assert_equal(3) + + res = 0 for n in add([1, 2], 3) res += n endfor *** ../vim-9.0.0429/src/version.c 2022-09-09 17:38:58.836061268 +0100 --- src/version.c 2022-09-09 18:24:46.401745513 +0100 *************** *** 705,706 **** --- 705,708 ---- { /* Add new patch number below this line */ + /**/ + 430, /**/ -- Have you heard about the new Beowulf cluster? It's so fast, it executes an infinite loop in 6 seconds. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///