diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.c | 38 | ||||
-rw-r--r-- | src/nvim/eval.h | 1 | ||||
-rw-r--r-- | src/nvim/eval/typval.c | 10 | ||||
-rw-r--r-- | src/nvim/testdir/test_blob.vim | 63 |
4 files changed, 97 insertions, 15 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index c3a9c0b9ca..29df1a168f 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -242,6 +242,7 @@ static struct vimvar { VV(VV__NULL_STRING, "_null_string", VAR_STRING, VV_RO), VV(VV__NULL_LIST, "_null_list", VAR_LIST, VV_RO), VV(VV__NULL_DICT, "_null_dict", VAR_DICT, VV_RO), + VV(VV__NULL_BLOB, "_null_blob", VAR_BLOB, VV_RO), VV(VV_LUA, "lua", VAR_PARTIAL, VV_RO), }; #undef VV @@ -2125,8 +2126,8 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, return NULL; } if (rettv != NULL - && !(rettv->v_type == VAR_LIST || rettv->vval.v_list != NULL) - && !(rettv->v_type == VAR_BLOB || rettv->vval.v_blob != NULL)) { + && !(rettv->v_type == VAR_LIST && rettv->vval.v_list != NULL) + && !(rettv->v_type == VAR_BLOB && rettv->vval.v_blob != NULL)) { if (!quiet) { EMSG(_("E709: [:] requires a List or Blob value")); } @@ -2252,15 +2253,24 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, } tv_clear(&var1); - if (lp->ll_n1 < 0 || lp->ll_n1 > tv_blob_len(lp->ll_tv->vval.v_blob)) { + const int bloblen = tv_blob_len(lp->ll_tv->vval.v_blob); + if (lp->ll_n1 < 0 || lp->ll_n1 > bloblen + || (lp->ll_range && lp->ll_n1 == bloblen)) { if (!quiet) { - EMSGN(_(e_listidx), lp->ll_n1); + EMSGN(_(e_blobidx), lp->ll_n1); } + tv_clear(&var2); return NULL; } if (lp->ll_range && !lp->ll_empty2) { lp->ll_n2 = (long)tv_get_number(&var2); tv_clear(&var2); + if (lp->ll_n2 < 0 || lp->ll_n2 >= bloblen || lp->ll_n2 < lp->ll_n1) { + if (!quiet) { + EMSGN(_(e_blobidx), lp->ll_n2); + } + return NULL; + } } lp->ll_blob = lp->ll_tv->vval.v_blob; lp->ll_tv = NULL; @@ -2364,13 +2374,20 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, } if (lp->ll_range && rettv->v_type == VAR_BLOB) { - if (tv_blob_len(rettv->vval.v_blob) != tv_blob_len(lp->ll_blob)) { - EMSG(_("E972: Blob value has more items than target")); + if (lp->ll_empty2) { + lp->ll_n2 = tv_blob_len(lp->ll_blob) - 1; + } + + if (lp->ll_n2 - lp->ll_n1 + 1 != tv_blob_len(rettv->vval.v_blob)) { + EMSG(_("E972: Blob value does not have the right number of bytes")); return; } + if (lp->ll_empty2) { + lp->ll_n2 = tv_blob_len(lp->ll_blob); + } - for (int i = lp->ll_n1; i <= lp->ll_n2; i++) { - tv_blob_set(lp->ll_blob, i, tv_blob_get(rettv->vval.v_blob, i)); + for (int il = lp->ll_n1, ir = 0; il <= lp->ll_n2; il++) { + tv_blob_set(lp->ll_blob, il, tv_blob_get(rettv->vval.v_blob, ir++)); } } else { bool error = false; @@ -2386,9 +2403,8 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, if (lp->ll_n1 == gap->ga_len) { gap->ga_len++; } - } else { - EMSG(_(e_invrange)); } + // error for invalid range was already given in get_lval() } } } else if (op != NULL && *op != '=') { @@ -4591,7 +4607,7 @@ eval_index( case VAR_BLOB: { len = tv_blob_len(rettv->vval.v_blob); if (range) { - // The resulting variable is a substring. If the indexes + // The resulting variable is a sub-blob. If the indexes // are out of range the result is empty. if (n1 < 0) { n1 = len + n1; diff --git a/src/nvim/eval.h b/src/nvim/eval.h index e5a65122f1..2452a0a8c8 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -167,6 +167,7 @@ typedef enum { VV__NULL_STRING, // String with NULL value. For test purposes only. VV__NULL_LIST, // List with NULL value. For test purposes only. VV__NULL_DICT, // Dictionary with NULL value. For test purposes only. + VV__NULL_BLOB, // Blob with NULL value. For test purposes only. VV_LUA, } VimVarIndex; diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 86e43e0819..e689571788 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2174,13 +2174,17 @@ void tv_blob_unref(blob_T *const b) bool tv_blob_equal(const blob_T *const b1, const blob_T *const b2) FUNC_ATTR_WARN_UNUSED_RESULT { - if (b1 == NULL || b2 == NULL) { - return false; + const int len1 = tv_blob_len(b1); + const int len2 = tv_blob_len(b2); + + // empty and NULL are considered the same + if (len1 == 0 && len2 == 0) { + return true; } if (b1 == b2) { return true; } - if (tv_blob_len(b1) != tv_blob_len(b2)) { + if (len1 != len2) { return false; } diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index 412bb69054..df8efbb149 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -21,6 +21,12 @@ func Test_blob_create() call assert_equal(0xDE, get(b, 0)) call assert_equal(0xEF, get(b, 3)) call assert_fails('let x = get(b, 4)') + + call assert_fails('let b = 0z1', 'E973:') + call assert_fails('let b = 0z1x', 'E973:') + call assert_fails('let b = 0z12345', 'E973:') + + call assert_equal(0z, v:_null_blob) endfunc " assignment to a blob @@ -32,6 +38,45 @@ func Test_blob_assign() let bcopy = b[:] call assert_equal(b, bcopy) call assert_false(b is bcopy) + + let b = 0zDEADBEEF + let b2 = b + call assert_true(b is b2) + let b[:] = 0z11223344 + call assert_equal(0z11223344, b) + call assert_equal(0z11223344, b2) + call assert_true(b is b2) + + let b = 0zDEADBEEF + let b[3:] = 0z66 + call assert_equal(0zDEADBE66, b) + let b[:1] = 0z8899 + call assert_equal(0z8899BE66, b) + + call assert_fails('let b[2:3] = 0z112233', 'E972:') + call assert_fails('let b[2:3] = 0z11', 'E972:') + call assert_fails('let b[3:2] = 0z', 'E979:') + + let b = 0zDEADBEEF + let b += 0z99 + call assert_equal(0zDEADBEEF99, b) + + call assert_fails('let b .= 0z33', 'E734:') + call assert_fails('let b .= "xx"', 'E734:') + call assert_fails('let b += "xx"', 'E734:') + call assert_fails('let b[1:1] .= 0z55', 'E734:') +endfunc + +func Test_blob_get_range() + let b = 0z0011223344 + call assert_equal(0z2233, b[2:3]) + call assert_equal(0z223344, b[2:-1]) + call assert_equal(0z00, b[0:-5]) + call assert_equal(0z, b[0:-11]) + call assert_equal(0z44, b[-1:]) + call assert_equal(0z0011223344, b[:]) + call assert_equal(0z0011223344, b[:-1]) + call assert_equal(0z, b[5:6]) endfunc func Test_blob_to_string() @@ -44,8 +89,12 @@ endfunc func Test_blob_compare() let b1 = 0z0011 let b2 = 0z1100 + let b3 = 0z001122 + call assert_true(b1 == b1) call assert_false(b1 == b2) + call assert_false(b1 == b3) call assert_true(b1 != b2) + call assert_true(b1 != b3) call assert_true(b1 == 0z0011) call assert_false(b1 is b2) @@ -65,7 +114,7 @@ func Test_blob_range_assign() let b[1] = 0x11 let b[2] = 0x22 call assert_equal(0z001122, b) - call assert_fails('let b[4] = 0x33') + call assert_fails('let b[4] = 0x33', 'E979:') endfunc func Test_blob_for_loop() @@ -173,4 +222,16 @@ func Test_blob_reverse() call assert_equal(0zDE, reverse(0zDE)) endfunc +func Test_blob_lock() + let b = 0z112233 + lockvar b + call assert_fails('let b = 0z44', 'E741:') + unlockvar b + let b = 0z44 +endfunc + +func Test_blob_sort() + call assert_fails('call sort([1.0, 0z11], "f")', 'E975:') +endfunc + " vim: shiftwidth=2 sts=2 expandtab |