diff --git a/jv.c b/jv.c index eea6a290..d1ae8d90 100644 --- a/jv.c +++ b/jv.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "jv_alloc.h" #include "jv.h" @@ -140,6 +141,17 @@ double jv_number_value(jv j) { return j.u.number; } +int jv_is_integer(jv j){ + if(jv_get_kind(j) != JV_KIND_NUMBER){ + return 0; + } + double x = jv_number_value(j); + if(x != x || x > INT_MAX || x < INT_MIN){ + return 0; + } + + return x == (int)x; +} /* * Arrays (internal helpers) diff --git a/jv.h b/jv.h index fc95363b..7e22cb43 100644 --- a/jv.h +++ b/jv.h @@ -60,6 +60,7 @@ jv jv_bool(int); jv jv_number(double); double jv_number_value(jv); +int jv_is_integer(jv); jv jv_array(void); jv jv_array_sized(int); diff --git a/jv_aux.c b/jv_aux.c index 76712aee..ec2aaa18 100644 --- a/jv_aux.c +++ b/jv_aux.c @@ -26,13 +26,18 @@ static int parse_slice(jv j, jv slice, int* pstart, int* pend) { jv_free(end_jv); return 0; } else { - int start = (int)jv_number_value(start_jv); - int end = (int)jv_number_value(end_jv); - if (start < 0) start = len + start; - if (end < 0) end = len + end; + double dstart = jv_number_value(start_jv); + double dend = jv_number_value(end_jv); + if (dstart < 0) dstart += len; + if (dend < 0) dend += len; + if (dstart < 0) dstart = 0; + if (dstart > len) dstart = len; + + int start = (int)dstart; + int end = (dend > len) ? len : (int)dend; + // Ends are exclusive but e.g. 1 < 1.5 so :1.5 should be :2 not :1 + if(end < dend) end += 1; - if (start < 0) start = 0; - if (start > len) start = len; if (end > len) end = len; if (end < start) end = start; assert(0 <= start && start <= end && end <= len); @@ -51,10 +56,15 @@ jv jv_get(jv t, jv k) { v = jv_null(); } } else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) { - // FIXME: don't do lookup for noninteger index - v = jv_array_get(t, (int)jv_number_value(k)); - if (!jv_is_valid(v)) { - jv_free(v); + if(jv_is_integer(k)){ + v = jv_array_get(t, (int)jv_number_value(k)); + if (!jv_is_valid(v)) { + jv_free(v); + v = jv_null(); + } + } else { + jv_free(t); + jv_free(k); v = jv_null(); } } else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_OBJECT) { diff --git a/tests/all.test b/tests/all.test index 785a0e28..259cdf2e 100644 --- a/tests/all.test +++ b/tests/all.test @@ -722,3 +722,11 @@ map(has(2)) keys [42,3,35] [0,1,2] + +[][.] +1000000000000000000 +null + +map([1,2][0:.]) +[-1, 1, 2, 3, 1000000000000000000] +[[1], [1], [1,2], [1,2], [1,2]]