]> granicus.if.org Git - jq/commitdiff
Delete negative indices in array (fix #954)
authorDavid Tolnay <dtolnay@gmail.com>
Mon, 21 Sep 2015 18:15:25 +0000 (11:15 -0700)
committerDavid Tolnay <dtolnay@gmail.com>
Tue, 22 Sep 2015 03:33:06 +0000 (20:33 -0700)
src/jv_aux.c
tests/jq.test

index 4d48f5779cb2f924ab50533c805626c4614cdc6d..1750013961758af5e45b11ec39a161b260a55b97 100644 (file)
@@ -214,7 +214,7 @@ jv jv_has(jv t, jv k) {
 }
 
 // assumes keys is a sorted array
-jv jv_dels(jv t, jv keys) {
+static jv jv_dels(jv t, jv keys) {
   assert(jv_get_kind(keys) == JV_KIND_ARRAY);
   assert(jv_is_valid(t));
 
@@ -222,13 +222,17 @@ jv jv_dels(jv t, jv keys) {
     // no change
   } else if (jv_get_kind(t) == JV_KIND_ARRAY) {
     // extract slices, they must be handled differently
-    jv orig_keys = keys;
-    keys = jv_array();
+    jv neg_keys = jv_array();
+    jv nonneg_keys = jv_array();
     jv new_array = jv_array();
     jv starts = jv_array(), ends = jv_array();
-    jv_array_foreach(orig_keys, i, key) {
+    jv_array_foreach(keys, i, key) {
       if (jv_get_kind(key) == JV_KIND_NUMBER) {
-        keys = jv_array_append(keys, key);
+        if (jv_number_value(key) < 0) {
+          neg_keys = jv_array_append(neg_keys, key);
+        } else {
+          nonneg_keys = jv_array_append(nonneg_keys, key);
+        }
       } else if (jv_get_kind(key) == JV_KIND_OBJECT) {
         int start, end;
         if (parse_slice(jv_copy(t), key, &start, &end)) {
@@ -248,18 +252,30 @@ jv jv_dels(jv t, jv keys) {
       }
     }
 
-    int kidx = 0;
+    int neg_idx = 0;
+    int nonneg_idx = 0;
+    int len = jv_array_length(jv_copy(t));
     jv_array_foreach(t, i, elem) {
       int del = 0;
-      while (kidx < jv_array_length(jv_copy(keys))) {
-        int delidx = (int)jv_number_value(jv_array_get(jv_copy(keys), kidx));
+      while (neg_idx < jv_array_length(jv_copy(neg_keys))) {
+        int delidx = len + (int)jv_number_value(jv_array_get(jv_copy(neg_keys), neg_idx));
+        if (i == delidx) {
+          del = 1;
+        }
+        if (i < delidx) {
+          break;
+        }
+        neg_idx++;
+      }
+      while (nonneg_idx < jv_array_length(jv_copy(nonneg_keys))) {
+        int delidx = (int)jv_number_value(jv_array_get(jv_copy(nonneg_keys), nonneg_idx));
         if (i == delidx) {
           del = 1;
         }
         if (i < delidx) {
           break;
         }
-        kidx++;
+        nonneg_idx++;
       }
       for (int sidx=0; !del && sidx<jv_array_length(jv_copy(starts)); sidx++) {
         if ((int)jv_number_value(jv_array_get(jv_copy(starts), sidx)) <= i &&
@@ -273,9 +289,10 @@ jv jv_dels(jv t, jv keys) {
         jv_free(elem);
     }
   arr_out:
+    jv_free(neg_keys);
+    jv_free(nonneg_keys);
     jv_free(starts);
     jv_free(ends);
-    jv_free(orig_keys);
     jv_free(t);
     t = new_array;
   } else if (jv_get_kind(t) == JV_KIND_OBJECT) {
index 830d157b31fe057c95936626ff711bc235c65208..6c75192e79a3dad5bdc09aa8a6543cfdafd9b634 100644 (file)
@@ -784,6 +784,10 @@ null
 {"foo": [1,4], "bar": [1]}
 {"bar": [1]}
 
+del(.[1], .[-6], .[2], .[-3:9])
+[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+[0, 3, 5, 6, 9]
+
 #
 # Assignment
 #