1+ #include <assert.h>
2+ #include <limits.h>
3+ #include <math.h>
14#include <string.h>
25#include <stdlib.h>
3- #include <assert.h>
46#include "jv_alloc.h"
57#include "jv_private.h"
68
@@ -13,7 +15,7 @@ static double jv_number_get_value_and_consume(jv number) {
1315 return value ;
1416}
1517
16- static int parse_slice (jv j , jv slice , int * pstart , int * pend ) {
18+ static jv parse_slice (jv j , jv slice , int * pstart , int * pend ) {
1719 // Array slices
1820 jv start_jv = jv_object_get (jv_copy (slice ), jv_string ("start" ));
1921 jv end_jv = jv_object_get (slice , jv_string ("end" ));
@@ -27,8 +29,14 @@ static int parse_slice(jv j, jv slice, int* pstart, int* pend) {
2729 } else if (jv_get_kind (j ) == JV_KIND_STRING ) {
2830 len = jv_string_length_codepoints (j );
2931 } else {
32+ /*
33+ * XXX This should be dead code because callers shouldn't call this
34+ * function if `j' is neither an array nor a string.
35+ */
3036 jv_free (j );
31- return 0 ;
37+ jv_free (start_jv );
38+ jv_free (end_jv );
39+ return jv_invalid_with_msg (jv_string ("Only arrays and strings can be sliced" ));
3240 }
3341 if (jv_get_kind (end_jv ) == JV_KIND_NULL ) {
3442 jv_free (end_jv );
@@ -38,29 +46,34 @@ static int parse_slice(jv j, jv slice, int* pstart, int* pend) {
3846 jv_get_kind (end_jv ) != JV_KIND_NUMBER ) {
3947 jv_free (start_jv );
4048 jv_free (end_jv );
41- return 0 ;
42- } else {
43- double dstart = jv_number_value (start_jv );
44- double dend = jv_number_value (end_jv );
45- jv_free (start_jv );
46- jv_free (end_jv );
47- if (dstart < 0 ) dstart += len ;
48- if (dend < 0 ) dend += len ;
49- if (dstart < 0 ) dstart = 0 ;
50- if (dstart > len ) dstart = len ;
51-
52- int start = (int )dstart ;
53- int end = (dend > len ) ? len : (int )dend ;
54- // Ends are exclusive but e.g. 1 < 1.5 so :1.5 should be :2 not :1
55- if (end < dend ) end += 1 ;
56-
57- if (end > len ) end = len ;
58- if (end < start ) end = start ;
59- assert (0 <= start && start <= end && end <= len );
60- * pstart = start ;
61- * pend = end ;
62- return 1 ;
63- }
49+ return jv_invalid_with_msg (jv_string ("Array/string slice indices must be integers" ));
50+ }
51+
52+ double dstart = jv_number_value (start_jv );
53+ double dend = jv_number_value (end_jv );
54+ int start , end ;
55+
56+ jv_free (start_jv );
57+ jv_free (end_jv );
58+ if (isnan (dstart )) dstart = 0 ;
59+ if (dstart < 0 ) dstart += len ;
60+ if (dstart < 0 ) dstart = 0 ;
61+ if (dstart > len ) dstart = len ;
62+ start = dstart > INT_MAX ? INT_MAX : (int )dstart ; // Rounds down
63+
64+ if (isnan (dend )) dend = len ;
65+ if (dend < 0 ) dend += len ;
66+ if (dend < 0 ) dend = start ;
67+ end = dend > INT_MAX ? INT_MAX : (int )dend ;
68+ if (end > len ) end = len ;
69+ if (end < len ) end += end < dend ? 1 : 0 ; // We round start down
70+ // but round end up
71+
72+ if (end < start ) end = start ;
73+ assert (0 <= start && start <= end && end <= len );
74+ * pstart = start ;
75+ * pend = end ;
76+ return jv_true ();
6477}
6578
6679jv jv_get (jv t , jv k ) {
@@ -72,36 +85,44 @@ jv jv_get(jv t, jv k) {
7285 v = jv_null ();
7386 }
7487 } else if (jv_get_kind (t ) == JV_KIND_ARRAY && jv_get_kind (k ) == JV_KIND_NUMBER ) {
75- if (jv_is_integer (k )){
76- int idx = (int )jv_number_value (k );
77- if (idx < 0 )
78- idx += jv_array_length (jv_copy (t ));
79- v = jv_array_get (t , idx );
80- if (!jv_is_valid (v )) {
81- jv_free (v );
82- v = jv_null ();
83- }
84- jv_free (k );
85- } else {
88+ if (jvp_number_is_nan (k )) {
8689 jv_free (t );
87- jv_free (k );
8890 v = jv_null ();
91+ } else {
92+ double didx = jv_number_value (k );
93+ if (jvp_number_is_nan (k )) {
94+ v = jv_null ();
95+ } else {
96+ if (didx < INT_MIN ) didx = INT_MIN ;
97+ if (didx > INT_MAX ) didx = INT_MAX ;
98+ int idx = (int )jv_number_value (k );
99+ if (idx < 0 )
100+ idx += jv_array_length (jv_copy (t ));
101+ v = jv_array_get (t , idx );
102+ if (!jv_is_valid (v )) {
103+ jv_free (v );
104+ v = jv_null ();
105+ }
106+ }
89107 }
108+ jv_free (k );
90109 } else if (jv_get_kind (t ) == JV_KIND_ARRAY && jv_get_kind (k ) == JV_KIND_OBJECT ) {
91110 int start , end ;
92- if (parse_slice (jv_copy (t ), k , & start , & end )) {
111+ jv e = parse_slice (jv_copy (t ), k , & start , & end );
112+ if (jv_get_kind (e ) == JV_KIND_TRUE ) {
93113 v = jv_array_slice (t , start , end );
94114 } else {
95115 jv_free (t );
96- v = jv_invalid_with_msg ( jv_string_fmt ( "Start and end indices of an array slice must be numbers" )) ;
116+ v = e ;
97117 }
98118 } else if (jv_get_kind (t ) == JV_KIND_STRING && jv_get_kind (k ) == JV_KIND_OBJECT ) {
99119 int start , end ;
100- if (parse_slice (jv_copy (t ), k , & start , & end )) {
120+ jv e = parse_slice (jv_copy (t ), k , & start , & end );
121+ if (jv_get_kind (e ) == JV_KIND_TRUE ) {
101122 v = jv_string_slice (t , start , end );
102123 } else {
103- v = jv_invalid_with_msg (jv_string_fmt ("Start and end indices of an string slice must be numbers" ));
104124 jv_free (t );
125+ v = e ;
105126 }
106127 } else if (jv_get_kind (t ) == JV_KIND_ARRAY && jv_get_kind (k ) == JV_KIND_ARRAY ) {
107128 v = jv_array_indexes (t , k );
@@ -146,14 +167,24 @@ jv jv_set(jv t, jv k, jv v) {
146167 t = jv_object_set (t , k , v );
147168 } else if (jv_get_kind (k ) == JV_KIND_NUMBER &&
148169 (jv_get_kind (t ) == JV_KIND_ARRAY || isnull )) {
149- if (isnull ) t = jv_array ();
150- t = jv_array_set (t , (int )jv_number_value (k ), v );
151- jv_free (k );
170+ if (jvp_number_is_nan (k )) {
171+ jv_free (t );
172+ jv_free (k );
173+ t = jv_invalid_with_msg (jv_string ("Cannot set array element at NaN index" ));
174+ } else {
175+ double didx = jv_number_value (k );
176+ if (didx < INT_MIN ) didx = INT_MIN ;
177+ if (didx > INT_MAX ) didx = INT_MAX ;
178+ if (isnull ) t = jv_array ();
179+ t = jv_array_set (t , (int )didx , v );
180+ jv_free (k );
181+ }
152182 } else if (jv_get_kind (k ) == JV_KIND_OBJECT &&
153183 (jv_get_kind (t ) == JV_KIND_ARRAY || isnull )) {
154184 if (isnull ) t = jv_array ();
155185 int start , end ;
156- if (parse_slice (jv_copy (t ), k , & start , & end )) {
186+ jv e = parse_slice (jv_copy (t ), k , & start , & end );
187+ if (jv_get_kind (e ) == JV_KIND_TRUE ) {
157188 if (jv_get_kind (v ) == JV_KIND_ARRAY ) {
158189 int array_len = jv_array_length (jv_copy (t ));
159190 assert (0 <= start && start <= end && end <= array_len );
@@ -185,8 +216,14 @@ jv jv_set(jv t, jv k, jv v) {
185216 } else {
186217 jv_free (t );
187218 jv_free (v );
188- t = jv_invalid_with_msg ( jv_string_fmt ( "Start and end indices of an array slice must be numbers" )) ;
219+ t = e ;
189220 }
221+ } else if (jv_get_kind (k ) == JV_KIND_OBJECT && jv_get_kind (t ) == JV_KIND_STRING ) {
222+ jv_free (t );
223+ jv_free (k );
224+ jv_free (v );
225+ /* Well, why not? We should implement this... */
226+ t = jv_invalid_with_msg (jv_string_fmt ("Cannot update string slices" ));
190227 } else {
191228 jv err = jv_invalid_with_msg (jv_string_fmt ("Cannot update field at %s index of %s" ,
192229 jv_kind_name (jv_get_kind (k )),
@@ -255,13 +292,14 @@ static jv jv_dels(jv t, jv keys) {
255292 }
256293 } else if (jv_get_kind (key ) == JV_KIND_OBJECT ) {
257294 int start , end ;
258- if (parse_slice (jv_copy (t ), key , & start , & end )) {
295+ jv e = parse_slice (jv_copy (t ), key , & start , & end );
296+ if (jv_get_kind (e ) == JV_KIND_TRUE ) {
259297 starts = jv_array_append (starts , jv_number (start ));
260298 ends = jv_array_append (ends , jv_number (end ));
261299 } else {
262300 jv_free (new_array );
263301 jv_free (key );
264- new_array = jv_invalid_with_msg ( jv_string_fmt ( "Start and end indices of an array slice must be numbers" )) ;
302+ new_array = e ;
265303 goto arr_out ;
266304 }
267305 } else {
0 commit comments