forked from aniani/vim
patch 8.2.2756: Vim9: blob index and slice not implemented yet
Problem: Vim9: blob index and slice not implemented yet. Solution: Implement blob index and slice.
This commit is contained in:
parent
af8ea0d066
commit
cfc3023cb6
77
src/blob.c
77
src/blob.c
@ -259,6 +259,83 @@ failed:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
blob_slice_or_index(
|
||||
blob_T *blob,
|
||||
int is_range,
|
||||
varnumber_T n1,
|
||||
varnumber_T n2,
|
||||
int exclusive,
|
||||
typval_T *rettv)
|
||||
{
|
||||
long len = blob_len(blob);
|
||||
|
||||
if (is_range)
|
||||
{
|
||||
// The resulting variable is a sub-blob. If the indexes
|
||||
// are out of range the result is empty.
|
||||
if (n1 < 0)
|
||||
{
|
||||
n1 = len + n1;
|
||||
if (n1 < 0)
|
||||
n1 = 0;
|
||||
}
|
||||
if (n2 < 0)
|
||||
n2 = len + n2;
|
||||
else if (n2 >= len)
|
||||
n2 = len - (exclusive ? 0 : 1);
|
||||
if (exclusive)
|
||||
--n2;
|
||||
if (n1 >= len || n2 < 0 || n1 > n2)
|
||||
{
|
||||
clear_tv(rettv);
|
||||
rettv->v_type = VAR_BLOB;
|
||||
rettv->vval.v_blob = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
blob_T *new_blob = blob_alloc();
|
||||
long i;
|
||||
|
||||
if (new_blob != NULL)
|
||||
{
|
||||
if (ga_grow(&new_blob->bv_ga, n2 - n1 + 1) == FAIL)
|
||||
{
|
||||
blob_free(new_blob);
|
||||
return FAIL;
|
||||
}
|
||||
new_blob->bv_ga.ga_len = n2 - n1 + 1;
|
||||
for (i = n1; i <= n2; i++)
|
||||
blob_set(new_blob, i - n1, blob_get(blob, i));
|
||||
|
||||
clear_tv(rettv);
|
||||
rettv_blob_set(rettv, new_blob);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The resulting variable is a byte value.
|
||||
// If the index is too big or negative that is an error.
|
||||
if (n1 < 0)
|
||||
n1 = len + n1;
|
||||
if (n1 < len && n1 >= 0)
|
||||
{
|
||||
int v = blob_get(blob, n1);
|
||||
|
||||
clear_tv(rettv);
|
||||
rettv->v_type = VAR_NUMBER;
|
||||
rettv->vval.v_number = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
semsg(_(e_blobidx), n1);
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* "remove({blob})" function
|
||||
*/
|
||||
|
64
src/eval.c
64
src/eval.c
@ -4161,68 +4161,8 @@ eval_index_inner(
|
||||
break;
|
||||
|
||||
case VAR_BLOB:
|
||||
len = blob_len(rettv->vval.v_blob);
|
||||
if (is_range)
|
||||
{
|
||||
// The resulting variable is a sub-blob. If the indexes
|
||||
// are out of range the result is empty.
|
||||
if (n1 < 0)
|
||||
{
|
||||
n1 = len + n1;
|
||||
if (n1 < 0)
|
||||
n1 = 0;
|
||||
}
|
||||
if (n2 < 0)
|
||||
n2 = len + n2;
|
||||
else if (n2 >= len)
|
||||
n2 = len - (exclusive ? 0 : 1);
|
||||
if (exclusive)
|
||||
--n2;
|
||||
if (n1 >= len || n2 < 0 || n1 > n2)
|
||||
{
|
||||
clear_tv(rettv);
|
||||
rettv->v_type = VAR_BLOB;
|
||||
rettv->vval.v_blob = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
blob_T *blob = blob_alloc();
|
||||
long i;
|
||||
|
||||
if (blob != NULL)
|
||||
{
|
||||
if (ga_grow(&blob->bv_ga, n2 - n1 + 1) == FAIL)
|
||||
{
|
||||
blob_free(blob);
|
||||
return FAIL;
|
||||
}
|
||||
blob->bv_ga.ga_len = n2 - n1 + 1;
|
||||
for (i = n1; i <= n2; i++)
|
||||
blob_set(blob, i - n1,
|
||||
blob_get(rettv->vval.v_blob, i));
|
||||
|
||||
clear_tv(rettv);
|
||||
rettv_blob_set(rettv, blob);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The resulting variable is a byte value.
|
||||
// If the index is too big or negative that is an error.
|
||||
if (n1 < 0)
|
||||
n1 = len + n1;
|
||||
if (n1 < len && n1 >= 0)
|
||||
{
|
||||
int v = blob_get(rettv->vval.v_blob, n1);
|
||||
|
||||
clear_tv(rettv);
|
||||
rettv->v_type = VAR_NUMBER;
|
||||
rettv->vval.v_number = v;
|
||||
}
|
||||
else
|
||||
semsg(_(e_blobidx), n1);
|
||||
}
|
||||
blob_slice_or_index(rettv->vval.v_blob, is_range, n1, n2,
|
||||
exclusive, rettv);
|
||||
break;
|
||||
|
||||
case VAR_LIST:
|
||||
|
@ -13,5 +13,6 @@ int read_blob(FILE *fd, blob_T *blob);
|
||||
int write_blob(FILE *fd, blob_T *blob);
|
||||
char_u *blob2string(blob_T *blob, char_u **tofree, char_u *numbuf);
|
||||
blob_T *string2blob(char_u *str);
|
||||
int blob_slice_or_index(blob_T *blob, int is_range, varnumber_T n1, varnumber_T n2, int exclusive, typval_T *rettv);
|
||||
void blob_remove(typval_T *argvars, typval_T *rettv);
|
||||
/* vim: set ft=c : */
|
||||
|
@ -1622,6 +1622,26 @@ def Test_expr7_blob()
|
||||
assert_equal(g:blob_empty, 0z)
|
||||
assert_equal(g:blob_one, 0z01)
|
||||
assert_equal(g:blob_long, 0z0102.0304)
|
||||
|
||||
var testblob = 0z010203
|
||||
assert_equal(0x01, testblob[0])
|
||||
assert_equal(0x02, testblob[1])
|
||||
assert_equal(0x03, testblob[-1])
|
||||
assert_equal(0x02, testblob[-2])
|
||||
|
||||
assert_equal(0z01, testblob[0 : 0])
|
||||
assert_equal(0z0102, testblob[0 : 1])
|
||||
assert_equal(0z010203, testblob[0 : 2])
|
||||
assert_equal(0z010203, testblob[0 : ])
|
||||
assert_equal(0z0203, testblob[1 : ])
|
||||
assert_equal(0z0203, testblob[1 : 2])
|
||||
assert_equal(0z0203, testblob[1 : -1])
|
||||
assert_equal(0z03, testblob[-1 : -1])
|
||||
assert_equal(0z02, testblob[-2 : -2])
|
||||
|
||||
# blob slice accepts out of range
|
||||
assert_equal(0z, testblob[3 : 3])
|
||||
assert_equal(0z, testblob[0 : -4])
|
||||
END
|
||||
CheckDefAndScriptSuccess(lines)
|
||||
|
||||
|
@ -750,6 +750,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2756,
|
||||
/**/
|
||||
2755,
|
||||
/**/
|
||||
|
@ -133,6 +133,8 @@ typedef enum {
|
||||
ISN_LISTAPPEND, // append to a list, like add()
|
||||
ISN_LISTINDEX, // [expr] list index
|
||||
ISN_LISTSLICE, // [expr:expr] list slice
|
||||
ISN_BLOBINDEX, // [expr] blob index
|
||||
ISN_BLOBSLICE, // [expr:expr] blob slice
|
||||
ISN_ANYINDEX, // [expr] runtime index
|
||||
ISN_ANYSLICE, // [expr:expr] runtime slice
|
||||
ISN_SLICE, // drop isn_arg.number items from start of list
|
||||
|
@ -2725,8 +2725,18 @@ compile_member(int is_slice, cctx_T *cctx)
|
||||
}
|
||||
else if (vtype == VAR_BLOB)
|
||||
{
|
||||
emsg("Sorry, blob index and slice not implemented yet");
|
||||
return FAIL;
|
||||
if (is_slice)
|
||||
{
|
||||
*typep = &t_blob;
|
||||
if (generate_instr_drop(cctx, ISN_BLOBSLICE, 2) == FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*typep = &t_number;
|
||||
if (generate_instr_drop(cctx, ISN_BLOBINDEX, 1) == FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
else if (vtype == VAR_LIST || *typep == &t_any)
|
||||
{
|
||||
@ -4088,7 +4098,7 @@ compile_subscript(
|
||||
// list index: list[123]
|
||||
// dict member: dict[key]
|
||||
// string index: text[123]
|
||||
// TODO: blob index
|
||||
// blob index: blob[123]
|
||||
// TODO: more arguments
|
||||
// TODO: recognize list or dict at runtime
|
||||
if (generate_ppconst(cctx, ppconst) == FAIL)
|
||||
@ -9241,6 +9251,8 @@ delete_instr(isn_T *isn)
|
||||
case ISN_ANYSLICE:
|
||||
case ISN_BCALL:
|
||||
case ISN_BLOBAPPEND:
|
||||
case ISN_BLOBINDEX:
|
||||
case ISN_BLOBSLICE:
|
||||
case ISN_CATCH:
|
||||
case ISN_CHECKLEN:
|
||||
case ISN_CHECKNR:
|
||||
|
@ -3415,16 +3415,21 @@ call_def_function(
|
||||
|
||||
case ISN_LISTINDEX:
|
||||
case ISN_LISTSLICE:
|
||||
case ISN_BLOBINDEX:
|
||||
case ISN_BLOBSLICE:
|
||||
{
|
||||
int is_slice = iptr->isn_type == ISN_LISTSLICE;
|
||||
list_T *list;
|
||||
int is_slice = iptr->isn_type == ISN_LISTSLICE
|
||||
|| iptr->isn_type == ISN_BLOBSLICE;
|
||||
int is_blob = iptr->isn_type == ISN_BLOBINDEX
|
||||
|| iptr->isn_type == ISN_BLOBSLICE;
|
||||
varnumber_T n1, n2;
|
||||
typval_T *val_tv;
|
||||
|
||||
// list index: list is at stack-2, index at stack-1
|
||||
// list slice: list is at stack-3, indexes at stack-2 and
|
||||
// stack-1
|
||||
tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
|
||||
list = tv->vval.v_list;
|
||||
// Same for blob.
|
||||
val_tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
|
||||
|
||||
tv = STACK_TV_BOT(-1);
|
||||
n1 = n2 = tv->vval.v_number;
|
||||
@ -3440,9 +3445,18 @@ call_def_function(
|
||||
ectx.ec_stack.ga_len -= is_slice ? 2 : 1;
|
||||
tv = STACK_TV_BOT(-1);
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
if (list_slice_or_index(list, is_slice, n1, n2, FALSE,
|
||||
tv, TRUE) == FAIL)
|
||||
goto on_error;
|
||||
if (is_blob)
|
||||
{
|
||||
if (blob_slice_or_index(val_tv->vval.v_blob, is_slice,
|
||||
n1, n2, FALSE, tv) == FAIL)
|
||||
goto on_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (list_slice_or_index(val_tv->vval.v_list, is_slice,
|
||||
n1, n2, FALSE, tv, TRUE) == FAIL)
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -4688,6 +4702,8 @@ ex_disassemble(exarg_T *eap)
|
||||
case ISN_CONCAT: smsg("%4d CONCAT", current); break;
|
||||
case ISN_STRINDEX: smsg("%4d STRINDEX", current); break;
|
||||
case ISN_STRSLICE: smsg("%4d STRSLICE", current); break;
|
||||
case ISN_BLOBINDEX: smsg("%4d BLOBINDEX", current); break;
|
||||
case ISN_BLOBSLICE: smsg("%4d BLOBSLICE", current); break;
|
||||
case ISN_LISTAPPEND: smsg("%4d LISTAPPEND", current); break;
|
||||
case ISN_BLOBAPPEND: smsg("%4d BLOBAPPEND", current); break;
|
||||
case ISN_LISTINDEX: smsg("%4d LISTINDEX", current); break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user