1 #include <stdint.h>
2 #include <stddef.h>
3 #include <assert.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdarg.h>
8 #include <limits.h>
9 #include <math.h>
10
11 #include "jv_alloc.h"
12 #include "jv.h"
13 #include "jv_unicode.h"
14 #include "util.h"
15
16 /*
17 * Internal refcounting helpers
18 */
19
20 typedef struct jv_refcnt {
21 int count;
22 } jv_refcnt;
23
24 static const jv_refcnt JV_REFCNT_INIT = {1};
25
jvp_refcnt_inc(jv_refcnt * c)26 static void jvp_refcnt_inc(jv_refcnt* c) {
27 c->count++;
28 }
29
jvp_refcnt_dec(jv_refcnt * c)30 static int jvp_refcnt_dec(jv_refcnt* c) {
31 c->count--;
32 return c->count == 0;
33 }
34
jvp_refcnt_unshared(jv_refcnt * c)35 static int jvp_refcnt_unshared(jv_refcnt* c) {
36 assert(c->count > 0);
37 return c->count == 1;
38 }
39
40 /*
41 * Simple values (true, false, null)
42 */
43
44 #define KIND_MASK 0xf
45
jv_get_kind(jv x)46 jv_kind jv_get_kind(jv x) {
47 return x.kind_flags & KIND_MASK;
48 }
49
jv_kind_name(jv_kind k)50 const char* jv_kind_name(jv_kind k) {
51 switch (k) {
52 case JV_KIND_INVALID: return "<invalid>";
53 case JV_KIND_NULL: return "null";
54 case JV_KIND_FALSE: return "boolean";
55 case JV_KIND_TRUE: return "boolean";
56 case JV_KIND_NUMBER: return "number";
57 case JV_KIND_STRING: return "string";
58 case JV_KIND_ARRAY: return "array";
59 case JV_KIND_OBJECT: return "object";
60 }
61 assert(0 && "invalid kind");
62 return "<unknown>";
63 }
64
65 static const jv JV_NULL = {JV_KIND_NULL, 0, 0, 0, {0}};
66 static const jv JV_INVALID = {JV_KIND_INVALID, 0, 0, 0, {0}};
67 static const jv JV_FALSE = {JV_KIND_FALSE, 0, 0, 0, {0}};
68 static const jv JV_TRUE = {JV_KIND_TRUE, 0, 0, 0, {0}};
69
jv_true()70 jv jv_true() {
71 return JV_TRUE;
72 }
73
jv_false()74 jv jv_false() {
75 return JV_FALSE;
76 }
77
jv_null()78 jv jv_null() {
79 return JV_NULL;
80 }
81
jv_bool(int x)82 jv jv_bool(int x) {
83 return x ? JV_TRUE : JV_FALSE;
84 }
85
86 /*
87 * Invalid objects, with optional error messages
88 */
89
90 typedef struct {
91 jv_refcnt refcnt;
92 jv errmsg;
93 } jvp_invalid;
94
jv_invalid_with_msg(jv err)95 jv jv_invalid_with_msg(jv err) {
96 if (jv_get_kind(err) == JV_KIND_NULL)
97 return JV_INVALID;
98 jvp_invalid* i = jv_mem_alloc(sizeof(jvp_invalid));
99 i->refcnt = JV_REFCNT_INIT;
100 i->errmsg = err;
101
102 jv x = {JV_KIND_INVALID, 0, 0, 0, {&i->refcnt}};
103 return x;
104 }
105
jv_invalid()106 jv jv_invalid() {
107 return JV_INVALID;
108 }
109
jv_invalid_get_msg(jv inv)110 jv jv_invalid_get_msg(jv inv) {
111 assert(jv_get_kind(inv) == JV_KIND_INVALID);
112 jv x;
113 if (inv.u.ptr == 0)
114 x = jv_null();
115 else
116 x = jv_copy(((jvp_invalid*)inv.u.ptr)->errmsg);
117 jv_free(inv);
118 return x;
119 }
120
jv_invalid_has_msg(jv inv)121 int jv_invalid_has_msg(jv inv) {
122 jv msg = jv_invalid_get_msg(inv);
123 int r = jv_get_kind(msg) != JV_KIND_NULL;
124 jv_free(msg);
125 return r;
126 }
127
jvp_invalid_free(jv x)128 static void jvp_invalid_free(jv x) {
129 assert(jv_get_kind(x) == JV_KIND_INVALID);
130 if (x.u.ptr != 0 && jvp_refcnt_dec(x.u.ptr)) {
131 jv_free(((jvp_invalid*)x.u.ptr)->errmsg);
132 jv_mem_free(x.u.ptr);
133 }
134 }
135
136 /*
137 * Numbers
138 */
139
jv_number(double x)140 jv jv_number(double x) {
141 jv j = {JV_KIND_NUMBER, 0, 0, 0, {.number = x}};
142 return j;
143 }
144
jv_number_value(jv j)145 double jv_number_value(jv j) {
146 assert(jv_get_kind(j) == JV_KIND_NUMBER);
147 return j.u.number;
148 }
149
jv_is_integer(jv j)150 int jv_is_integer(jv j){
151 if(jv_get_kind(j) != JV_KIND_NUMBER){
152 return 0;
153 }
154 double x = jv_number_value(j);
155 if(x != x || x > INT_MAX || x < INT_MIN){
156 return 0;
157 }
158
159 return x == (int)x;
160 }
161
162 /*
163 * Arrays (internal helpers)
164 */
165
166 #define ARRAY_SIZE_ROUND_UP(n) (((n)*3)/2)
167
imax(int a,int b)168 static int imax(int a, int b) {
169 if (a>b) return a;
170 else return b;
171 }
172
173 //FIXME signed vs unsigned
174 typedef struct {
175 jv_refcnt refcnt;
176 int length, alloc_length;
177 jv elements[];
178 } jvp_array;
179
jvp_array_ptr(jv a)180 static jvp_array* jvp_array_ptr(jv a) {
181 assert(jv_get_kind(a) == JV_KIND_ARRAY);
182 return (jvp_array*)a.u.ptr;
183 }
184
jvp_array_alloc(unsigned size)185 static jvp_array* jvp_array_alloc(unsigned size) {
186 jvp_array* a = jv_mem_alloc(sizeof(jvp_array) + sizeof(jv) * size);
187 a->refcnt.count = 1;
188 a->length = 0;
189 a->alloc_length = size;
190 return a;
191 }
192
jvp_array_new(unsigned size)193 static jv jvp_array_new(unsigned size) {
194 jv r = {JV_KIND_ARRAY, 0, 0, 0, {&jvp_array_alloc(size)->refcnt}};
195 return r;
196 }
197
jvp_array_free(jv a)198 static void jvp_array_free(jv a) {
199 assert(jv_get_kind(a) == JV_KIND_ARRAY);
200 if (jvp_refcnt_dec(a.u.ptr)) {
201 jvp_array* array = jvp_array_ptr(a);
202 for (int i=0; i<array->length; i++) {
203 jv_free(array->elements[i]);
204 }
205 jv_mem_free(array);
206 }
207 }
208
jvp_array_length(jv a)209 static int jvp_array_length(jv a) {
210 assert(jv_get_kind(a) == JV_KIND_ARRAY);
211 return a.size;
212 }
213
jvp_array_offset(jv a)214 static int jvp_array_offset(jv a) {
215 assert(jv_get_kind(a) == JV_KIND_ARRAY);
216 return a.offset;
217 }
218
jvp_array_read(jv a,int i)219 static jv* jvp_array_read(jv a, int i) {
220 assert(jv_get_kind(a) == JV_KIND_ARRAY);
221 if (i >= 0 && i < jvp_array_length(a)) {
222 jvp_array* array = jvp_array_ptr(a);
223 assert(i + jvp_array_offset(a) < array->length);
224 return &array->elements[i + jvp_array_offset(a)];
225 } else {
226 return 0;
227 }
228 }
229
jvp_array_write(jv * a,int i)230 static jv* jvp_array_write(jv* a, int i) {
231 assert(i >= 0);
232 jvp_array* array = jvp_array_ptr(*a);
233
234 int pos = i + jvp_array_offset(*a);
235 if (pos < array->alloc_length && jvp_refcnt_unshared(a->u.ptr)) {
236 // use existing array space
237 for (int j = array->length; j <= pos; j++) {
238 array->elements[j] = JV_NULL;
239 }
240 array->length = imax(pos + 1, array->length);
241 a->size = imax(i + 1, a->size);
242 return &array->elements[pos];
243 } else {
244 // allocate a new array
245 int new_length = imax(i + 1, jvp_array_length(*a));
246 jvp_array* new_array = jvp_array_alloc(ARRAY_SIZE_ROUND_UP(new_length));
247 int j;
248 for (j = 0; j < jvp_array_length(*a); j++) {
249 new_array->elements[j] =
250 jv_copy(array->elements[j + jvp_array_offset(*a)]);
251 }
252 for (; j < new_length; j++) {
253 new_array->elements[j] = JV_NULL;
254 }
255 new_array->length = new_length;
256 jvp_array_free(*a);
257 jv new_jv = {JV_KIND_ARRAY, 0, 0, new_length, {&new_array->refcnt}};
258 *a = new_jv;
259 return &new_array->elements[i];
260 }
261 }
262
jvp_array_equal(jv a,jv b)263 static int jvp_array_equal(jv a, jv b) {
264 if (jvp_array_length(a) != jvp_array_length(b))
265 return 0;
266 if (jvp_array_ptr(a) == jvp_array_ptr(b) &&
267 jvp_array_offset(a) == jvp_array_offset(b))
268 return 1;
269 for (int i=0; i<jvp_array_length(a); i++) {
270 if (!jv_equal(jv_copy(*jvp_array_read(a, i)),
271 jv_copy(*jvp_array_read(b, i))))
272 return 0;
273 }
274 return 1;
275 }
276
jvp_clamp_slice_params(int len,int * pstart,int * pend)277 static void jvp_clamp_slice_params(int len, int *pstart, int *pend)
278 {
279 if (*pstart < 0) *pstart = len + *pstart;
280 if (*pend < 0) *pend = len + *pend;
281
282 if (*pstart < 0) *pstart = 0;
283 if (*pstart > len) *pstart = len;
284 if (*pend > len) *pend = len;
285 if (*pend < *pstart) *pend = *pstart;
286 }
287
jvp_array_slice(jv a,int start,int end)288 static jv jvp_array_slice(jv a, int start, int end) {
289 assert(jv_get_kind(a) == JV_KIND_ARRAY);
290 int len = jvp_array_length(a);
291 jvp_clamp_slice_params(len, &start, &end);
292 assert(0 <= start && start <= end && end <= len);
293
294 // FIXME: maybe slice should reallocate if the slice is small enough
295 if (start == end) {
296 jv_free(a);
297 return jv_array();
298 }
299
300 if (a.offset + start >= 1 << (sizeof(a.offset) * CHAR_BIT)) {
301 jv r = jv_array_sized(end - start);
302 for (int i = start; i < end; i++)
303 r = jv_array_append(r, jv_array_get(jv_copy(a), i));
304 jv_free(a);
305 return r;
306 } else {
307 a.offset += start;
308 a.size = end - start;
309 return a;
310 }
311 }
312
313 /*
314 * Arrays (public interface)
315 */
316
jv_array_sized(int n)317 jv jv_array_sized(int n) {
318 return jvp_array_new(n);
319 }
320
jv_array()321 jv jv_array() {
322 return jv_array_sized(16);
323 }
324
jv_array_length(jv j)325 int jv_array_length(jv j) {
326 assert(jv_get_kind(j) == JV_KIND_ARRAY);
327 int len = jvp_array_length(j);
328 jv_free(j);
329 return len;
330 }
331
jv_array_get(jv j,int idx)332 jv jv_array_get(jv j, int idx) {
333 assert(jv_get_kind(j) == JV_KIND_ARRAY);
334 jv* slot = jvp_array_read(j, idx);
335 jv val;
336 if (slot) {
337 val = jv_copy(*slot);
338 } else {
339 val = jv_invalid();
340 }
341 jv_free(j);
342 return val;
343 }
344
jv_array_set(jv j,int idx,jv val)345 jv jv_array_set(jv j, int idx, jv val) {
346 assert(jv_get_kind(j) == JV_KIND_ARRAY);
347
348 if (idx < 0)
349 idx = jvp_array_length(j) + idx;
350 if (idx < 0) {
351 jv_free(j);
352 jv_free(val);
353 return jv_invalid_with_msg(jv_string("Out of bounds negative array index"));
354 }
355 // copy/free of val,j coalesced
356 jv* slot = jvp_array_write(&j, idx);
357 jv_free(*slot);
358 *slot = val;
359 return j;
360 }
361
jv_array_append(jv j,jv val)362 jv jv_array_append(jv j, jv val) {
363 // copy/free of val,j coalesced
364 return jv_array_set(j, jv_array_length(jv_copy(j)), val);
365 }
366
jv_array_concat(jv a,jv b)367 jv jv_array_concat(jv a, jv b) {
368 assert(jv_get_kind(a) == JV_KIND_ARRAY);
369 assert(jv_get_kind(b) == JV_KIND_ARRAY);
370
371 // FIXME: could be faster
372 jv_array_foreach(b, i, elem) {
373 a = jv_array_append(a, elem);
374 }
375 jv_free(b);
376 return a;
377 }
378
jv_array_slice(jv a,int start,int end)379 jv jv_array_slice(jv a, int start, int end) {
380 assert(jv_get_kind(a) == JV_KIND_ARRAY);
381 // copy/free of a coalesced
382 return jvp_array_slice(a, start, end);
383 }
384
jv_array_contains(jv a,jv b)385 int jv_array_contains(jv a, jv b) {
386 int r = 1;
387 jv_array_foreach(b, bi, belem) {
388 int ri = 0;
389 jv_array_foreach(a, ai, aelem) {
390 if (jv_contains(aelem, jv_copy(belem))) {
391 ri = 1;
392 break;
393 }
394 }
395 jv_free(belem);
396 if (!ri) {
397 r = 0;
398 break;
399 }
400 }
401 jv_free(a);
402 jv_free(b);
403 return r;
404 }
405
jv_array_indexes(jv a,jv b)406 jv jv_array_indexes(jv a, jv b) {
407 jv res = jv_array();
408 int idx = -1;
409 jv_array_foreach(a, ai, aelem) {
410 jv_array_foreach(b, bi, belem) {
411 // quieten compiler warnings about aelem not being used... by
412 // using it
413 if ((bi == 0 && !jv_equal(jv_copy(aelem), jv_copy(belem))) ||
414 (bi > 0 && !jv_equal(jv_array_get(jv_copy(a), ai + bi), jv_copy(belem))))
415 idx = -1;
416 else if (bi == 0 && idx == -1)
417 idx = ai;
418 }
419 if (idx > -1)
420 res = jv_array_append(res, jv_number(idx));
421 idx = -1;
422 }
423 jv_free(a);
424 jv_free(b);
425 return res;
426 }
427
428
429 /*
430 * Strings (internal helpers)
431 */
432
433 typedef struct {
434 jv_refcnt refcnt;
435 uint32_t hash;
436 // high 31 bits are length, low bit is a flag
437 // indicating whether hash has been computed.
438 uint32_t length_hashed;
439 uint32_t alloc_length;
440 char data[];
441 } jvp_string;
442
jvp_string_ptr(jv a)443 static jvp_string* jvp_string_ptr(jv a) {
444 assert(jv_get_kind(a) == JV_KIND_STRING);
445 return (jvp_string*)a.u.ptr;
446 }
447
jvp_string_alloc(uint32_t size)448 static jvp_string* jvp_string_alloc(uint32_t size) {
449 jvp_string* s = jv_mem_alloc(sizeof(jvp_string) + size + 1);
450 s->refcnt.count = 1;
451 s->alloc_length = size;
452 return s;
453 }
454
455 /* Copy a UTF8 string, replacing all badly encoded points with U+FFFD */
jvp_string_copy_replace_bad(const char * data,uint32_t length)456 static jv jvp_string_copy_replace_bad(const char* data, uint32_t length) {
457 const char* end = data + length;
458 const char* i = data;
459 const char* cstart;
460
461 uint32_t maxlength = length * 3 + 1; // worst case: all bad bytes, each becomes a 3-byte U+FFFD
462 jvp_string* s = jvp_string_alloc(maxlength);
463 char* out = s->data;
464 int c = 0;
465
466 while ((i = jvp_utf8_next((cstart = i), end, &c))) {
467 if (c == -1) {
468 c = 0xFFFD; // U+FFFD REPLACEMENT CHARACTER
469 }
470 out += jvp_utf8_encode(c, out);
471 assert(out < s->data + maxlength);
472 }
473 length = out - s->data;
474 s->data[length] = 0;
475 s->length_hashed = length << 1;
476 jv r = {JV_KIND_STRING, 0, 0, 0, {&s->refcnt}};
477 return r;
478 }
479
480 /* Assumes valid UTF8 */
jvp_string_new(const char * data,uint32_t length)481 static jv jvp_string_new(const char* data, uint32_t length) {
482 jvp_string* s = jvp_string_alloc(length);
483 s->length_hashed = length << 1;
484 if (data != NULL)
485 memcpy(s->data, data, length);
486 s->data[length] = 0;
487 jv r = {JV_KIND_STRING, 0, 0, 0, {&s->refcnt}};
488 return r;
489 }
490
jvp_string_empty_new(uint32_t length)491 static jv jvp_string_empty_new(uint32_t length) {
492 jvp_string* s = jvp_string_alloc(length);
493 s->length_hashed = 0;
494 memset(s->data, 0, length);
495 jv r = {JV_KIND_STRING, 0, 0, 0, {&s->refcnt}};
496 return r;
497 }
498
499
jvp_string_free(jv js)500 static void jvp_string_free(jv js) {
501 jvp_string* s = jvp_string_ptr(js);
502 if (jvp_refcnt_dec(&s->refcnt)) {
503 jv_mem_free(s);
504 }
505 }
506
jvp_string_length(jvp_string * s)507 static uint32_t jvp_string_length(jvp_string* s) {
508 return s->length_hashed >> 1;
509 }
510
jvp_string_remaining_space(jvp_string * s)511 static uint32_t jvp_string_remaining_space(jvp_string* s) {
512 assert(s->alloc_length >= jvp_string_length(s));
513 uint32_t r = s->alloc_length - jvp_string_length(s);
514 return r;
515 }
516
jvp_string_append(jv string,const char * data,uint32_t len)517 static jv jvp_string_append(jv string, const char* data, uint32_t len) {
518 jvp_string* s = jvp_string_ptr(string);
519 uint32_t currlen = jvp_string_length(s);
520
521 if (jvp_refcnt_unshared(string.u.ptr) &&
522 jvp_string_remaining_space(s) >= len) {
523 // the next string fits at the end of a
524 memcpy(s->data + currlen, data, len);
525 s->data[currlen + len] = 0;
526 s->length_hashed = (currlen + len) << 1;
527 return string;
528 } else {
529 // allocate a bigger buffer and copy
530 uint32_t allocsz = (currlen + len) * 2;
531 if (allocsz < 32) allocsz = 32;
532 jvp_string* news = jvp_string_alloc(allocsz);
533 news->length_hashed = (currlen + len) << 1;
534 memcpy(news->data, s->data, currlen);
535 memcpy(news->data + currlen, data, len);
536 news->data[currlen + len] = 0;
537 jvp_string_free(string);
538 jv r = {JV_KIND_STRING, 0, 0, 0, {&news->refcnt}};
539 return r;
540 }
541 }
542
543 static const uint32_t HASH_SEED = 0x432A9843;
544
rotl32(uint32_t x,int8_t r)545 static uint32_t rotl32 (uint32_t x, int8_t r){
546 return (x << r) | (x >> (32 - r));
547 }
548
jvp_string_hash(jv jstr)549 static uint32_t jvp_string_hash(jv jstr) {
550 jvp_string* str = jvp_string_ptr(jstr);
551 if (str->length_hashed & 1)
552 return str->hash;
553
554 /* The following is based on MurmurHash3.
555 MurmurHash3 was written by Austin Appleby, and is placed
556 in the public domain. */
557
558 const uint8_t* data = (const uint8_t*)str->data;
559 int len = (int)jvp_string_length(str);
560 const int nblocks = len / 4;
561
562 uint32_t h1 = HASH_SEED;
563
564 const uint32_t c1 = 0xcc9e2d51;
565 const uint32_t c2 = 0x1b873593;
566 const uint32_t* blocks = (const uint32_t *)(data + nblocks*4);
567
568 for(int i = -nblocks; i; i++) {
569 uint32_t k1 = blocks[i]; //FIXME: endianness/alignment
570
571 k1 *= c1;
572 k1 = rotl32(k1,15);
573 k1 *= c2;
574
575 h1 ^= k1;
576 h1 = rotl32(h1,13);
577 h1 = h1*5+0xe6546b64;
578 }
579
580 const uint8_t* tail = (const uint8_t*)(data + nblocks*4);
581
582 uint32_t k1 = 0;
583
584 switch(len & 3) {
585 case 3: k1 ^= tail[2] << 16;
586 case 2: k1 ^= tail[1] << 8;
587 case 1: k1 ^= tail[0];
588 k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1;
589 }
590
591 h1 ^= len;
592
593 h1 ^= h1 >> 16;
594 h1 *= 0x85ebca6b;
595 h1 ^= h1 >> 13;
596 h1 *= 0xc2b2ae35;
597 h1 ^= h1 >> 16;
598
599 str->length_hashed |= 1;
600 str->hash = h1;
601
602 return h1;
603 }
604
jvp_string_equal(jv a,jv b)605 static int jvp_string_equal(jv a, jv b) {
606 assert(jv_get_kind(a) == JV_KIND_STRING);
607 assert(jv_get_kind(b) == JV_KIND_STRING);
608 jvp_string* stra = jvp_string_ptr(a);
609 jvp_string* strb = jvp_string_ptr(b);
610 if (jvp_string_length(stra) != jvp_string_length(strb)) return 0;
611 return memcmp(stra->data, strb->data, jvp_string_length(stra)) == 0;
612 }
613
614 /*
615 * Strings (public API)
616 */
617
jv_string_sized(const char * str,int len)618 jv jv_string_sized(const char* str, int len) {
619 return
620 jvp_utf8_is_valid(str, str+len) ?
621 jvp_string_new(str, len) :
622 jvp_string_copy_replace_bad(str, len);
623 }
624
jv_string_empty(int len)625 jv jv_string_empty(int len) {
626 return jvp_string_empty_new(len);
627 }
628
jv_string(const char * str)629 jv jv_string(const char* str) {
630 return jv_string_sized(str, strlen(str));
631 }
632
jv_string_length_bytes(jv j)633 int jv_string_length_bytes(jv j) {
634 assert(jv_get_kind(j) == JV_KIND_STRING);
635 int r = jvp_string_length(jvp_string_ptr(j));
636 jv_free(j);
637 return r;
638 }
639
jv_string_length_codepoints(jv j)640 int jv_string_length_codepoints(jv j) {
641 assert(jv_get_kind(j) == JV_KIND_STRING);
642 const char* i = jv_string_value(j);
643 const char* end = i + jv_string_length_bytes(jv_copy(j));
644 int c = 0, len = 0;
645 while ((i = jvp_utf8_next(i, end, &c))) len++;
646 jv_free(j);
647 return len;
648 }
649
650
jv_string_indexes(jv j,jv k)651 jv jv_string_indexes(jv j, jv k) {
652 assert(jv_get_kind(j) == JV_KIND_STRING);
653 assert(jv_get_kind(k) == JV_KIND_STRING);
654 const char *jstr = jv_string_value(j);
655 const char *idxstr = jv_string_value(k);
656 const char *p;
657 int jlen = jv_string_length_bytes(jv_copy(j));
658 int idxlen = jv_string_length_bytes(jv_copy(k));
659 jv a = jv_array();
660
661 p = jstr;
662 while ((p = _jq_memmem(p, (jstr + jlen) - p, idxstr, idxlen)) != NULL) {
663 a = jv_array_append(a, jv_number(p - jstr));
664 p += idxlen;
665 }
666 jv_free(j);
667 jv_free(k);
668 return a;
669 }
670
jv_string_split(jv j,jv sep)671 jv jv_string_split(jv j, jv sep) {
672 assert(jv_get_kind(j) == JV_KIND_STRING);
673 assert(jv_get_kind(sep) == JV_KIND_STRING);
674 const char *jstr = jv_string_value(j);
675 const char *jend = jstr + jv_string_length_bytes(jv_copy(j));
676 const char *sepstr = jv_string_value(sep);
677 const char *p, *s;
678 int seplen = jv_string_length_bytes(jv_copy(sep));
679 jv a = jv_array();
680
681 assert(jv_get_refcnt(a) == 1);
682
683 if (seplen == 0) {
684 int c;
685 while ((jstr = jvp_utf8_next(jstr, jend, &c)))
686 a = jv_array_append(a, jv_string_append_codepoint(jv_string(""), c));
687 } else {
688 for (p = jstr; p < jend; p = s + seplen) {
689 s = _jq_memmem(p, jend - p, sepstr, seplen);
690 if (s == NULL)
691 s = jend;
692 a = jv_array_append(a, jv_string_sized(p, s - p));
693 // Add an empty string to denote that j ends on a sep
694 if (s + seplen == jend && seplen != 0)
695 a = jv_array_append(a, jv_string(""));
696 }
697 }
698 jv_free(j);
699 jv_free(sep);
700 return a;
701 }
702
jv_string_explode(jv j)703 jv jv_string_explode(jv j) {
704 assert(jv_get_kind(j) == JV_KIND_STRING);
705 const char* i = jv_string_value(j);
706 int len = jv_string_length_bytes(jv_copy(j));
707 const char* end = i + len;
708 jv a = jv_array_sized(len);
709 int c;
710 while ((i = jvp_utf8_next(i, end, &c)))
711 a = jv_array_append(a, jv_number(c));
712 jv_free(j);
713 return a;
714 }
715
jv_string_implode(jv j)716 jv jv_string_implode(jv j) {
717 assert(jv_get_kind(j) == JV_KIND_ARRAY);
718 int len = jv_array_length(jv_copy(j));
719 jv s = jv_string_empty(len);
720 int i;
721
722 assert(len >= 0);
723
724 for (i = 0; i < len; i++) {
725 jv n = jv_array_get(jv_copy(j), i);
726 assert(jv_get_kind(n) == JV_KIND_NUMBER);
727 int nv = jv_number_value(n);
728 if (nv > 0x10FFFF)
729 nv = 0xFFFD; // U+FFFD REPLACEMENT CHARACTER
730 s = jv_string_append_codepoint(s, nv);
731 }
732
733 jv_free(j);
734 return s;
735 }
736
jv_string_hash(jv j)737 unsigned long jv_string_hash(jv j) {
738 assert(jv_get_kind(j) == JV_KIND_STRING);
739 uint32_t hash = jvp_string_hash(j);
740 jv_free(j);
741 return hash;
742 }
743
jv_string_value(jv j)744 const char* jv_string_value(jv j) {
745 assert(jv_get_kind(j) == JV_KIND_STRING);
746 return jvp_string_ptr(j)->data;
747 }
748
jv_string_slice(jv j,int start,int end)749 jv jv_string_slice(jv j, int start, int end) {
750 assert(jv_get_kind(j) == JV_KIND_STRING);
751 const char *s = jv_string_value(j);
752 int len = jv_string_length_bytes(jv_copy(j));
753 int i;
754 const char *p, *e;
755 int c;
756 jv res;
757
758 jvp_clamp_slice_params(len, &start, &end);
759 assert(0 <= start && start <= end && end <= len);
760
761 /* Look for byte offset corresponding to start codepoints */
762 for (p = s, i = 0; i < start; i++) {
763 p = jvp_utf8_next(p, s + len, &c);
764 if (p == NULL) {
765 jv_free(j);
766 return jv_string_empty(16);
767 }
768 if (c == -1) {
769 jv_free(j);
770 return jv_invalid_with_msg(jv_string("Invalid UTF-8 string"));
771 }
772 }
773 /* Look for byte offset corresponding to end codepoints */
774 for (e = p; e != NULL && i < end; i++) {
775 e = jvp_utf8_next(e, s + len, &c);
776 if (e == NULL) {
777 e = s + len;
778 break;
779 }
780 if (c == -1) {
781 jv_free(j);
782 return jv_invalid_with_msg(jv_string("Invalid UTF-8 string"));
783 }
784 }
785
786 /*
787 * NOTE: Ideally we should do here what jvp_array_slice() does instead
788 * of allocating a new string as we do! However, we assume NUL-
789 * terminated strings all over, and in the jv API, so for now we waste
790 * memory like a drunken navy programmer. There's probably nothing we
791 * can do about it.
792 */
793 res = jv_string_sized(p, e - p);
794 jv_free(j);
795 return res;
796 }
797
jv_string_concat(jv a,jv b)798 jv jv_string_concat(jv a, jv b) {
799 a = jvp_string_append(a, jv_string_value(b),
800 jvp_string_length(jvp_string_ptr(b)));
801 jv_free(b);
802 return a;
803 }
804
jv_string_append_buf(jv a,const char * buf,int len)805 jv jv_string_append_buf(jv a, const char* buf, int len) {
806 if (jvp_utf8_is_valid(buf, buf+len)) {
807 a = jvp_string_append(a, buf, len);
808 } else {
809 jv b = jvp_string_copy_replace_bad(buf, len);
810 a = jv_string_concat(a, b);
811 }
812 return a;
813 }
814
jv_string_append_codepoint(jv a,uint32_t c)815 jv jv_string_append_codepoint(jv a, uint32_t c) {
816 char buf[5];
817 int len = jvp_utf8_encode(c, buf);
818 a = jvp_string_append(a, buf, len);
819 return a;
820 }
821
jv_string_append_str(jv a,const char * str)822 jv jv_string_append_str(jv a, const char* str) {
823 return jv_string_append_buf(a, str, strlen(str));
824 }
825
jv_string_vfmt(const char * fmt,va_list ap)826 jv jv_string_vfmt(const char* fmt, va_list ap) {
827 int size = 1024;
828 while (1) {
829 char* buf = jv_mem_alloc(size);
830 va_list ap2;
831 va_copy(ap2, ap);
832 int n = vsnprintf(buf, size, fmt, ap2);
833 va_end(ap2);
834 /*
835 * NOTE: here we support old vsnprintf()s that return -1 because the
836 * buffer is too small.
837 */
838 if (n >= 0 && n < size) {
839 jv ret = jv_string_sized(buf, n);
840 jv_mem_free(buf);
841 return ret;
842 } else {
843 jv_mem_free(buf);
844 size = (n > 0) ? /* standard */ (n * 2) : /* not standard */ (size * 2);
845 }
846 }
847 }
848
jv_string_fmt(const char * fmt,...)849 jv jv_string_fmt(const char* fmt, ...) {
850 va_list args;
851 va_start(args, fmt);
852 jv res = jv_string_vfmt(fmt, args);
853 va_end(args);
854 return res;
855 }
856
857 /*
858 * Objects (internal helpers)
859 */
860
861 struct object_slot {
862 int next; /* next slot with same hash, for collisions */
863 uint32_t hash;
864 jv string;
865 jv value;
866 };
867
868 typedef struct {
869 jv_refcnt refcnt;
870 int next_free;
871 struct object_slot elements[];
872 } jvp_object;
873
874
875 /* warning: nontrivial justification of alignment */
jvp_object_new(int size)876 static jv jvp_object_new(int size) {
877 // Allocates an object of (size) slots and (size*2) hash buckets.
878
879 // size must be a power of two
880 assert(size > 0 && (size & (size - 1)) == 0);
881
882 jvp_object* obj = jv_mem_alloc(sizeof(jvp_object) +
883 sizeof(struct object_slot) * size +
884 sizeof(int) * (size * 2));
885 obj->refcnt.count = 1;
886 for (int i=0; i<size; i++) {
887 obj->elements[i].next = i - 1;
888 obj->elements[i].string = JV_NULL;
889 obj->elements[i].hash = 0;
890 obj->elements[i].value = JV_NULL;
891 }
892 obj->next_free = 0;
893 int* hashbuckets = (int*)(&obj->elements[size]);
894 for (int i=0; i<size*2; i++) {
895 hashbuckets[i] = -1;
896 }
897 jv r = {JV_KIND_OBJECT, 0, 0, size, {&obj->refcnt}};
898 return r;
899 }
900
jvp_object_ptr(jv o)901 static jvp_object* jvp_object_ptr(jv o) {
902 assert(jv_get_kind(o) == JV_KIND_OBJECT);
903 return (jvp_object*)o.u.ptr;
904 }
905
jvp_object_mask(jv o)906 static uint32_t jvp_object_mask(jv o) {
907 assert(jv_get_kind(o) == JV_KIND_OBJECT);
908 return (o.size * 2) - 1;
909 }
910
jvp_object_size(jv o)911 static int jvp_object_size(jv o) {
912 assert(jv_get_kind(o) == JV_KIND_OBJECT);
913 return o.size;
914 }
915
jvp_object_buckets(jv o)916 static int* jvp_object_buckets(jv o) {
917 return (int*)(&jvp_object_ptr(o)->elements[o.size]);
918 }
919
jvp_object_find_bucket(jv object,jv key)920 static int* jvp_object_find_bucket(jv object, jv key) {
921 return jvp_object_buckets(object) + (jvp_object_mask(object) & jvp_string_hash(key));
922 }
923
jvp_object_get_slot(jv object,int slot)924 static struct object_slot* jvp_object_get_slot(jv object, int slot) {
925 assert(slot == -1 || (slot >= 0 && slot < jvp_object_size(object)));
926 if (slot == -1) return 0;
927 else return &jvp_object_ptr(object)->elements[slot];
928 }
929
jvp_object_next_slot(jv object,struct object_slot * slot)930 static struct object_slot* jvp_object_next_slot(jv object, struct object_slot* slot) {
931 return jvp_object_get_slot(object, slot->next);
932 }
933
jvp_object_find_slot(jv object,jv keystr,int * bucket)934 static struct object_slot* jvp_object_find_slot(jv object, jv keystr, int* bucket) {
935 uint32_t hash = jvp_string_hash(keystr);
936 for (struct object_slot* curr = jvp_object_get_slot(object, *bucket);
937 curr;
938 curr = jvp_object_next_slot(object, curr)) {
939 if (curr->hash == hash && jvp_string_equal(keystr, curr->string)) {
940 return curr;
941 }
942 }
943 return 0;
944 }
945
jvp_object_add_slot(jv object,jv key,int * bucket)946 static struct object_slot* jvp_object_add_slot(jv object, jv key, int* bucket) {
947 jvp_object* o = jvp_object_ptr(object);
948 int newslot_idx = o->next_free;
949 if (newslot_idx == jvp_object_size(object)) return 0;
950 struct object_slot* newslot = jvp_object_get_slot(object, newslot_idx);
951 o->next_free++;
952 newslot->next = *bucket;
953 *bucket = newslot_idx;
954 newslot->hash = jvp_string_hash(key);
955 newslot->string = key;
956 return newslot;
957 }
958
jvp_object_read(jv object,jv key)959 static jv* jvp_object_read(jv object, jv key) {
960 assert(jv_get_kind(key) == JV_KIND_STRING);
961 int* bucket = jvp_object_find_bucket(object, key);
962 struct object_slot* slot = jvp_object_find_slot(object, key, bucket);
963 if (slot == 0) return 0;
964 else return &slot->value;
965 }
966
jvp_object_free(jv o)967 static void jvp_object_free(jv o) {
968 assert(jv_get_kind(o) == JV_KIND_OBJECT);
969 if (jvp_refcnt_dec(o.u.ptr)) {
970 for (int i=0; i<jvp_object_size(o); i++) {
971 struct object_slot* slot = jvp_object_get_slot(o, i);
972 if (jv_get_kind(slot->string) != JV_KIND_NULL) {
973 jvp_string_free(slot->string);
974 jv_free(slot->value);
975 }
976 }
977 jv_mem_free(jvp_object_ptr(o));
978 }
979 }
980
jvp_object_rehash(jv object)981 static jv jvp_object_rehash(jv object) {
982 assert(jv_get_kind(object) == JV_KIND_OBJECT);
983 assert(jvp_refcnt_unshared(object.u.ptr));
984 int size = jvp_object_size(object);
985 jv new_object = jvp_object_new(size * 2);
986 for (int i=0; i<size; i++) {
987 struct object_slot* slot = jvp_object_get_slot(object, i);
988 if (jv_get_kind(slot->string) == JV_KIND_NULL) continue;
989 int* new_bucket = jvp_object_find_bucket(new_object, slot->string);
990 assert(!jvp_object_find_slot(new_object, slot->string, new_bucket));
991 struct object_slot* new_slot = jvp_object_add_slot(new_object, slot->string, new_bucket);
992 assert(new_slot);
993 new_slot->value = slot->value;
994 }
995 // references are transported, just drop the old table
996 jv_mem_free(jvp_object_ptr(object));
997 return new_object;
998 }
999
jvp_object_unshare(jv object)1000 static jv jvp_object_unshare(jv object) {
1001 assert(jv_get_kind(object) == JV_KIND_OBJECT);
1002 if (jvp_refcnt_unshared(object.u.ptr))
1003 return object;
1004
1005 jv new_object = jvp_object_new(jvp_object_size(object));
1006 jvp_object_ptr(new_object)->next_free = jvp_object_ptr(object)->next_free;
1007 for (int i=0; i<jvp_object_size(new_object); i++) {
1008 struct object_slot* old_slot = jvp_object_get_slot(object, i);
1009 struct object_slot* new_slot = jvp_object_get_slot(new_object, i);
1010 *new_slot = *old_slot;
1011 if (jv_get_kind(old_slot->string) != JV_KIND_NULL) {
1012 new_slot->string = jv_copy(old_slot->string);
1013 new_slot->value = jv_copy(old_slot->value);
1014 }
1015 }
1016
1017 int* old_buckets = jvp_object_buckets(object);
1018 int* new_buckets = jvp_object_buckets(new_object);
1019 memcpy(new_buckets, old_buckets, sizeof(int) * jvp_object_size(new_object)*2);
1020
1021 jvp_object_free(object);
1022 assert(jvp_refcnt_unshared(new_object.u.ptr));
1023 return new_object;
1024 }
1025
jvp_object_write(jv * object,jv key)1026 static jv* jvp_object_write(jv* object, jv key) {
1027 *object = jvp_object_unshare(*object);
1028 int* bucket = jvp_object_find_bucket(*object, key);
1029 struct object_slot* slot = jvp_object_find_slot(*object, key, bucket);
1030 if (slot) {
1031 // already has the key
1032 jvp_string_free(key);
1033 return &slot->value;
1034 }
1035 slot = jvp_object_add_slot(*object, key, bucket);
1036 if (slot) {
1037 slot->value = jv_invalid();
1038 } else {
1039 *object = jvp_object_rehash(*object);
1040 bucket = jvp_object_find_bucket(*object, key);
1041 assert(!jvp_object_find_slot(*object, key, bucket));
1042 slot = jvp_object_add_slot(*object, key, bucket);
1043 assert(slot);
1044 slot->value = jv_invalid();
1045 }
1046 return &slot->value;
1047 }
1048
jvp_object_delete(jv * object,jv key)1049 static int jvp_object_delete(jv* object, jv key) {
1050 assert(jv_get_kind(key) == JV_KIND_STRING);
1051 *object = jvp_object_unshare(*object);
1052 int* bucket = jvp_object_find_bucket(*object, key);
1053 int* prev_ptr = bucket;
1054 uint32_t hash = jvp_string_hash(key);
1055 for (struct object_slot* curr = jvp_object_get_slot(*object, *bucket);
1056 curr;
1057 curr = jvp_object_next_slot(*object, curr)) {
1058 if (hash == curr->hash && jvp_string_equal(key, curr->string)) {
1059 *prev_ptr = curr->next;
1060 jvp_string_free(curr->string);
1061 curr->string = JV_NULL;
1062 jv_free(curr->value);
1063 return 1;
1064 }
1065 prev_ptr = &curr->next;
1066 }
1067 return 0;
1068 }
1069
jvp_object_length(jv object)1070 static int jvp_object_length(jv object) {
1071 int n = 0;
1072 for (int i=0; i<jvp_object_size(object); i++) {
1073 struct object_slot* slot = jvp_object_get_slot(object, i);
1074 if (jv_get_kind(slot->string) != JV_KIND_NULL) n++;
1075 }
1076 return n;
1077 }
1078
jvp_object_equal(jv o1,jv o2)1079 static int jvp_object_equal(jv o1, jv o2) {
1080 int len2 = jvp_object_length(o2);
1081 int len1 = 0;
1082 for (int i=0; i<jvp_object_size(o1); i++) {
1083 struct object_slot* slot = jvp_object_get_slot(o1, i);
1084 if (jv_get_kind(slot->string) == JV_KIND_NULL) continue;
1085 jv* slot2 = jvp_object_read(o2, slot->string);
1086 if (!slot2) return 0;
1087 // FIXME: do less refcounting here
1088 if (!jv_equal(jv_copy(slot->value), jv_copy(*slot2))) return 0;
1089 len1++;
1090 }
1091 return len1 == len2;
1092 }
1093
1094 /*
1095 * Objects (public interface)
1096 */
1097 #define DEFAULT_OBJECT_SIZE 8
jv_object()1098 jv jv_object() {
1099 return jvp_object_new(8);
1100 }
1101
jv_object_get(jv object,jv key)1102 jv jv_object_get(jv object, jv key) {
1103 assert(jv_get_kind(object) == JV_KIND_OBJECT);
1104 assert(jv_get_kind(key) == JV_KIND_STRING);
1105 jv* slot = jvp_object_read(object, key);
1106 jv val;
1107 if (slot) {
1108 val = jv_copy(*slot);
1109 } else {
1110 val = jv_invalid();
1111 }
1112 jv_free(object);
1113 jv_free(key);
1114 return val;
1115 }
1116
jv_object_has(jv object,jv key)1117 int jv_object_has(jv object, jv key) {
1118 assert(jv_get_kind(object) == JV_KIND_OBJECT);
1119 assert(jv_get_kind(key) == JV_KIND_STRING);
1120 jv* slot = jvp_object_read(object, key);
1121 int res = slot ? 1 : 0;
1122 jv_free(object);
1123 jv_free(key);
1124 return res;
1125 }
1126
jv_object_set(jv object,jv key,jv value)1127 jv jv_object_set(jv object, jv key, jv value) {
1128 assert(jv_get_kind(object) == JV_KIND_OBJECT);
1129 assert(jv_get_kind(key) == JV_KIND_STRING);
1130 // copy/free of object, key, value coalesced
1131 jv* slot = jvp_object_write(&object, key);
1132 jv_free(*slot);
1133 *slot = value;
1134 return object;
1135 }
1136
jv_object_delete(jv object,jv key)1137 jv jv_object_delete(jv object, jv key) {
1138 assert(jv_get_kind(object) == JV_KIND_OBJECT);
1139 assert(jv_get_kind(key) == JV_KIND_STRING);
1140 jvp_object_delete(&object, key);
1141 jv_free(key);
1142 return object;
1143 }
1144
jv_object_length(jv object)1145 int jv_object_length(jv object) {
1146 assert(jv_get_kind(object) == JV_KIND_OBJECT);
1147 int n = jvp_object_length(object);
1148 jv_free(object);
1149 return n;
1150 }
1151
jv_object_merge(jv a,jv b)1152 jv jv_object_merge(jv a, jv b) {
1153 assert(jv_get_kind(a) == JV_KIND_OBJECT);
1154 jv_object_foreach(b, k, v) {
1155 a = jv_object_set(a, k, v);
1156 }
1157 jv_free(b);
1158 return a;
1159 }
1160
jv_object_merge_recursive(jv a,jv b)1161 jv jv_object_merge_recursive(jv a, jv b) {
1162 assert(jv_get_kind(a) == JV_KIND_OBJECT);
1163 assert(jv_get_kind(b) == JV_KIND_OBJECT);
1164
1165 jv_object_foreach(b, k, v) {
1166 jv elem = jv_object_get(jv_copy(a), jv_copy(k));
1167 if (jv_is_valid(elem) &&
1168 jv_get_kind(elem) == JV_KIND_OBJECT &&
1169 jv_get_kind(v) == JV_KIND_OBJECT) {
1170 a = jv_object_set(a, k, jv_object_merge_recursive(elem, v));
1171 } else {
1172 jv_free(elem);
1173 a = jv_object_set(a, k, v);
1174 }
1175 }
1176 jv_free(b);
1177 return a;
1178 }
1179
jv_object_contains(jv a,jv b)1180 int jv_object_contains(jv a, jv b) {
1181 assert(jv_get_kind(a) == JV_KIND_OBJECT);
1182 assert(jv_get_kind(b) == JV_KIND_OBJECT);
1183 int r = 1;
1184
1185 jv_object_foreach(b, key, b_val) {
1186 jv a_val = jv_object_get(jv_copy(a), jv_copy(key));
1187
1188 r = jv_contains(a_val, b_val);
1189 jv_free(key);
1190
1191 if (!r) break;
1192 }
1193
1194 jv_free(a);
1195 jv_free(b);
1196 return r;
1197 }
1198
1199 /*
1200 * Object iteration (internal helpers)
1201 */
1202
1203 enum { ITER_FINISHED = -2 };
1204
jv_object_iter_valid(jv object,int i)1205 int jv_object_iter_valid(jv object, int i) {
1206 return i != ITER_FINISHED;
1207 }
1208
jv_object_iter(jv object)1209 int jv_object_iter(jv object) {
1210 assert(jv_get_kind(object) == JV_KIND_OBJECT);
1211 return jv_object_iter_next(object, -1);
1212 }
1213
jv_object_iter_next(jv object,int iter)1214 int jv_object_iter_next(jv object, int iter) {
1215 assert(jv_get_kind(object) == JV_KIND_OBJECT);
1216 assert(iter != ITER_FINISHED);
1217 struct object_slot* slot;
1218 do {
1219 iter++;
1220 if (iter >= jvp_object_size(object))
1221 return ITER_FINISHED;
1222 slot = jvp_object_get_slot(object, iter);
1223 } while (jv_get_kind(slot->string) == JV_KIND_NULL);
1224 assert(jv_get_kind(jvp_object_get_slot(object,iter)->string)
1225 == JV_KIND_STRING);
1226 return iter;
1227 }
1228
jv_object_iter_key(jv object,int iter)1229 jv jv_object_iter_key(jv object, int iter) {
1230 jv s = jvp_object_get_slot(object, iter)->string;
1231 assert(jv_get_kind(s) == JV_KIND_STRING);
1232 return jv_copy(s);
1233 }
1234
jv_object_iter_value(jv object,int iter)1235 jv jv_object_iter_value(jv object, int iter) {
1236 return jv_copy(jvp_object_get_slot(object, iter)->value);
1237 }
1238
1239 /*
1240 * Memory management
1241 */
jv_copy(jv j)1242 jv jv_copy(jv j) {
1243 if (jv_get_kind(j) == JV_KIND_ARRAY ||
1244 jv_get_kind(j) == JV_KIND_STRING ||
1245 jv_get_kind(j) == JV_KIND_OBJECT ||
1246 (jv_get_kind(j) == JV_KIND_INVALID && j.u.ptr != 0)) {
1247 jvp_refcnt_inc(j.u.ptr);
1248 }
1249 return j;
1250 }
1251
jv_free(jv j)1252 void jv_free(jv j) {
1253 if (jv_get_kind(j) == JV_KIND_ARRAY) {
1254 jvp_array_free(j);
1255 } else if (jv_get_kind(j) == JV_KIND_STRING) {
1256 jvp_string_free(j);
1257 } else if (jv_get_kind(j) == JV_KIND_OBJECT) {
1258 jvp_object_free(j);
1259 } else if (jv_get_kind(j) == JV_KIND_INVALID) {
1260 jvp_invalid_free(j);
1261 }
1262 }
1263
jv_get_refcnt(jv j)1264 int jv_get_refcnt(jv j) {
1265 switch (jv_get_kind(j)) {
1266 case JV_KIND_ARRAY:
1267 case JV_KIND_STRING:
1268 case JV_KIND_OBJECT:
1269 return j.u.ptr->count;
1270 default:
1271 return 1;
1272 }
1273 }
1274
1275 /*
1276 * Higher-level operations
1277 */
1278
jv_equal(jv a,jv b)1279 int jv_equal(jv a, jv b) {
1280 int r;
1281 if (jv_get_kind(a) != jv_get_kind(b)) {
1282 r = 0;
1283 } else if (jv_get_kind(a) == JV_KIND_NUMBER) {
1284 r = jv_number_value(a) == jv_number_value(b);
1285 } else if (a.kind_flags == b.kind_flags &&
1286 a.size == b.size &&
1287 a.u.ptr == b.u.ptr) {
1288 r = 1;
1289 } else {
1290 switch (jv_get_kind(a)) {
1291 case JV_KIND_ARRAY:
1292 r = jvp_array_equal(a, b);
1293 break;
1294 case JV_KIND_STRING:
1295 r = jvp_string_equal(a, b);
1296 break;
1297 case JV_KIND_OBJECT:
1298 r = jvp_object_equal(a, b);
1299 break;
1300 default:
1301 r = 1;
1302 break;
1303 }
1304 }
1305 jv_free(a);
1306 jv_free(b);
1307 return r;
1308 }
1309
jv_identical(jv a,jv b)1310 int jv_identical(jv a, jv b) {
1311 int r;
1312 if (a.kind_flags != b.kind_flags
1313 || a.offset != b.offset
1314 || a.size != b.size) {
1315 r = 0;
1316 } else {
1317 switch (jv_get_kind(a)) {
1318 case JV_KIND_ARRAY:
1319 case JV_KIND_STRING:
1320 case JV_KIND_OBJECT:
1321 r = a.u.ptr == b.u.ptr;
1322 break;
1323 case JV_KIND_NUMBER:
1324 r = memcmp(&a.u.number, &b.u.number, sizeof(a.u.number)) == 0;
1325 break;
1326 default:
1327 r = 1;
1328 break;
1329 }
1330 }
1331 jv_free(a);
1332 jv_free(b);
1333 return r;
1334 }
1335
jv_contains(jv a,jv b)1336 int jv_contains(jv a, jv b) {
1337 int r = 1;
1338 if (jv_get_kind(a) != jv_get_kind(b)) {
1339 r = 0;
1340 } else if (jv_get_kind(a) == JV_KIND_OBJECT) {
1341 r = jv_object_contains(jv_copy(a), jv_copy(b));
1342 } else if (jv_get_kind(a) == JV_KIND_ARRAY) {
1343 r = jv_array_contains(jv_copy(a), jv_copy(b));
1344 } else if (jv_get_kind(a) == JV_KIND_STRING) {
1345 r = strstr(jv_string_value(a), jv_string_value(b)) != 0;
1346 } else {
1347 r = jv_equal(jv_copy(a), jv_copy(b));
1348 }
1349 jv_free(a);
1350 jv_free(b);
1351 return r;
1352 }
1353