]> granicus.if.org Git - vim/commitdiff
patch 8.2.2756: Vim9: blob index and slice not implemented yet v8.2.2756
authorBram Moolenaar <Bram@vim.org>
Sun, 11 Apr 2021 18:26:34 +0000 (20:26 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 11 Apr 2021 18:26:34 +0000 (20:26 +0200)
Problem:    Vim9: blob index and slice not implemented yet.
Solution:   Implement blob index and slice.

src/blob.c
src/eval.c
src/proto/blob.pro
src/testdir/test_vim9_expr.vim
src/version.c
src/vim9.h
src/vim9compile.c
src/vim9execute.c

index 264962e197d93871aa4c0385a13e05bb31a41f65..8d260f172ba961e8965d96466932aa863f259dac 100644 (file)
@@ -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
  */
index 787243ed6568ba388965a83f19289f4451689886..1291b364a93229e1522350c081bf1f5fdae2c5c3 100644 (file)
@@ -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:
index 3bc6625456ecdd4c805b4308601e94d6343a576f..6be7f0bea5115895c05ae2b6174ed4f5b3c9a19a 100644 (file)
@@ -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 : */
index 0e0e34e01e9701e176f1ef07c1b1b56c00cac905..456b42612e1365097c86efd79cd5c3b08be9b1e0 100644 (file)
@@ -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)
 
index d8b39eb2263be4d9784c03bf93bf12f6890440de..0dc382f43b8d9b08e144a7a32b2d2f1795cec203 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2756,
 /**/
     2755,
 /**/
index 0c8a949e87500353aa9d531807c5dd031ff7dd68..c30e597adbde0c8a7ecf11b3b10a8a55aa3c66af 100644 (file)
@@ -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
index 59d1339073da45ec5f741cdb455d5b11e9394ad3..9263659640f0fea090b99bfde89698ba82ac06be 100644 (file)
@@ -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:
index 017d5774efc97613fa14d0264c7da1ae285b0963..94d6f45232daf534e289000312e18230c5e7915b 100644 (file)
@@ -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;