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