comparison src/eval.c @ 23604:1816ea68c022 v8.2.2344

patch 8.2.2344: using inclusive index for slice is not always desired Commit: https://github.com/vim/vim/commit/6601b62943a19d4f8818c3638440663d67a17b6a Author: Bram Moolenaar <Bram@vim.org> Date: Wed Jan 13 21:47:15 2021 +0100 patch 8.2.2344: using inclusive index for slice is not always desired Problem: Using inclusive index for slice is not always desired. Solution: Add the slice() method, which has an exclusive index. (closes #7408)
author Bram Moolenaar <Bram@vim.org>
date Wed, 13 Jan 2021 22:00:04 +0100
parents f4347a61ed38
children b26bbc03126a
comparison
equal deleted inserted replaced
23603:483d395694b0 23604:1816ea68c022
3875 } 3875 }
3876 3876
3877 if (evaluate) 3877 if (evaluate)
3878 { 3878 {
3879 int res = eval_index_inner(rettv, range, 3879 int res = eval_index_inner(rettv, range,
3880 empty1 ? NULL : &var1, empty2 ? NULL : &var2, 3880 empty1 ? NULL : &var1, empty2 ? NULL : &var2, FALSE,
3881 key, keylen, verbose); 3881 key, keylen, verbose);
3882
3882 if (!empty1) 3883 if (!empty1)
3883 clear_tv(&var1); 3884 clear_tv(&var1);
3884 if (range) 3885 if (range)
3885 clear_tv(&var2); 3886 clear_tv(&var2);
3886 return res; 3887 return res;
3936 } 3937 }
3937 return OK; 3938 return OK;
3938 } 3939 }
3939 3940
3940 /* 3941 /*
3942 * slice() function
3943 */
3944 void
3945 f_slice(typval_T *argvars, typval_T *rettv)
3946 {
3947 if (check_can_index(argvars, TRUE, FALSE) == OK)
3948 {
3949 copy_tv(argvars, rettv);
3950 eval_index_inner(rettv, TRUE, argvars + 1,
3951 argvars[2].v_type == VAR_UNKNOWN ? NULL : argvars + 2,
3952 TRUE, NULL, 0, FALSE);
3953 }
3954 }
3955
3956 /*
3941 * Apply index or range to "rettv". 3957 * Apply index or range to "rettv".
3942 * "var1" is the first index, NULL for [:expr]. 3958 * "var1" is the first index, NULL for [:expr].
3943 * "var2" is the second index, NULL for [expr] and [expr: ] 3959 * "var2" is the second index, NULL for [expr] and [expr: ]
3960 * "exclusive" is TRUE for slice(): second index is exclusive, use character
3961 * index for string.
3944 * Alternatively, "key" is not NULL, then key[keylen] is the dict index. 3962 * Alternatively, "key" is not NULL, then key[keylen] is the dict index.
3945 */ 3963 */
3946 int 3964 int
3947 eval_index_inner( 3965 eval_index_inner(
3948 typval_T *rettv, 3966 typval_T *rettv,
3949 int is_range, 3967 int is_range,
3950 typval_T *var1, 3968 typval_T *var1,
3951 typval_T *var2, 3969 typval_T *var2,
3970 int exclusive,
3952 char_u *key, 3971 char_u *key,
3953 int keylen, 3972 int keylen,
3954 int verbose) 3973 int verbose)
3955 { 3974 {
3956 long n1, n2 = 0; 3975 varnumber_T n1, n2 = 0;
3957 long len; 3976 long len;
3958 3977
3959 n1 = 0; 3978 n1 = 0;
3960 if (var1 != NULL && rettv->v_type != VAR_DICT) 3979 if (var1 != NULL && rettv->v_type != VAR_DICT)
3961 n1 = tv_get_number(var1); 3980 n1 = tv_get_number(var1);
3962 3981
3966 { 3985 {
3967 if (verbose) 3986 if (verbose)
3968 emsg(_(e_cannot_slice_dictionary)); 3987 emsg(_(e_cannot_slice_dictionary));
3969 return FAIL; 3988 return FAIL;
3970 } 3989 }
3971 if (var2 == NULL) 3990 if (var2 != NULL)
3972 n2 = -1; 3991 n2 = tv_get_number(var2);
3973 else 3992 else
3974 n2 = tv_get_number(var2); 3993 n2 = VARNUM_MAX;
3975 } 3994 }
3976 3995
3977 switch (rettv->v_type) 3996 switch (rettv->v_type)
3978 { 3997 {
3979 case VAR_UNKNOWN: 3998 case VAR_UNKNOWN:
3992 case VAR_STRING: 4011 case VAR_STRING:
3993 { 4012 {
3994 char_u *s = tv_get_string(rettv); 4013 char_u *s = tv_get_string(rettv);
3995 4014
3996 len = (long)STRLEN(s); 4015 len = (long)STRLEN(s);
3997 if (in_vim9script()) 4016 if (in_vim9script() || exclusive)
3998 { 4017 {
3999 if (is_range) 4018 if (is_range)
4000 s = string_slice(s, n1, n2); 4019 s = string_slice(s, n1, n2, exclusive);
4001 else 4020 else
4002 s = char_from_string(s, n1); 4021 s = char_from_string(s, n1);
4003 } 4022 }
4004 else if (is_range) 4023 else if (is_range)
4005 { 4024 {
4013 } 4032 }
4014 if (n2 < 0) 4033 if (n2 < 0)
4015 n2 = len + n2; 4034 n2 = len + n2;
4016 else if (n2 >= len) 4035 else if (n2 >= len)
4017 n2 = len; 4036 n2 = len;
4037 if (exclusive)
4038 --n2;
4018 if (n1 >= len || n2 < 0 || n1 > n2) 4039 if (n1 >= len || n2 < 0 || n1 > n2)
4019 s = NULL; 4040 s = NULL;
4020 else 4041 else
4021 s = vim_strnsave(s + n1, n2 - n1 + 1); 4042 s = vim_strnsave(s + n1, n2 - n1 + 1);
4022 } 4043 }
4049 n1 = 0; 4070 n1 = 0;
4050 } 4071 }
4051 if (n2 < 0) 4072 if (n2 < 0)
4052 n2 = len + n2; 4073 n2 = len + n2;
4053 else if (n2 >= len) 4074 else if (n2 >= len)
4054 n2 = len - 1; 4075 n2 = len - (exclusive ? 0 : 1);
4076 if (exclusive)
4077 --n2;
4055 if (n1 >= len || n2 < 0 || n1 > n2) 4078 if (n1 >= len || n2 < 0 || n1 > n2)
4056 { 4079 {
4057 clear_tv(rettv); 4080 clear_tv(rettv);
4058 rettv->v_type = VAR_BLOB; 4081 rettv->v_type = VAR_BLOB;
4059 rettv->vval.v_blob = NULL; 4082 rettv->vval.v_blob = NULL;
4101 4124
4102 case VAR_LIST: 4125 case VAR_LIST:
4103 if (var1 == NULL) 4126 if (var1 == NULL)
4104 n1 = 0; 4127 n1 = 0;
4105 if (var2 == NULL) 4128 if (var2 == NULL)
4106 n2 = -1; 4129 n2 = VARNUM_MAX;
4107 if (list_slice_or_index(rettv->vval.v_list, 4130 if (list_slice_or_index(rettv->vval.v_list,
4108 is_range, n1, n2, rettv, verbose) == FAIL) 4131 is_range, n1, n2, exclusive, rettv, verbose) == FAIL)
4109 return FAIL; 4132 return FAIL;
4110 break; 4133 break;
4111 4134
4112 case VAR_DICT: 4135 case VAR_DICT:
4113 { 4136 {