@port-labs/jq-node-bindings 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/.editorconfig +5 -0
  2. package/.jshintignore +1 -0
  3. package/.jshintrc +23 -0
  4. package/binding.gyp +56 -0
  5. package/configure +26 -0
  6. package/deps/jq/.gitattributes +2 -0
  7. package/deps/jq/.travis.yml +53 -0
  8. package/deps/jq/AUTHORS +73 -0
  9. package/deps/jq/COPYING +70 -0
  10. package/deps/jq/ChangeLog +1349 -0
  11. package/deps/jq/Makefile.am +198 -0
  12. package/deps/jq/NEWS +88 -0
  13. package/deps/jq/README.md +64 -0
  14. package/deps/jq/builtin.c +1684 -0
  15. package/deps/jq/builtin.h +10 -0
  16. package/deps/jq/bytecode.c +161 -0
  17. package/deps/jq/bytecode.h +92 -0
  18. package/deps/jq/compile-ios.sh +102 -0
  19. package/deps/jq/compile.c +1210 -0
  20. package/deps/jq/compile.h +101 -0
  21. package/deps/jq/config/m4/check-math-func.m4 +4 -0
  22. package/deps/jq/config/m4/find-func-no-libs.m4 +8 -0
  23. package/deps/jq/config/m4/find-func-no-libs2.m4 +62 -0
  24. package/deps/jq/config/m4/find-func.m4 +9 -0
  25. package/deps/jq/config/m4/misc.m4 +3 -0
  26. package/deps/jq/configure.ac +221 -0
  27. package/deps/jq/docs/Gemfile +7 -0
  28. package/deps/jq/docs/Gemfile.lock +63 -0
  29. package/deps/jq/docs/README.md +25 -0
  30. package/deps/jq/docs/Rakefile +145 -0
  31. package/deps/jq/docs/content/1.tutorial/default.yml +327 -0
  32. package/deps/jq/docs/content/2.download/default.yml +117 -0
  33. package/deps/jq/docs/content/3.manual/manual.yml +2878 -0
  34. package/deps/jq/docs/content/3.manual/v1.3/manual.yml +1270 -0
  35. package/deps/jq/docs/content/3.manual/v1.4/manual.yml +1672 -0
  36. package/deps/jq/docs/content/index/index.yml +51 -0
  37. package/deps/jq/docs/default_manpage.md +22 -0
  38. package/deps/jq/docs/public/.htaccess +28 -0
  39. package/deps/jq/docs/public/bootstrap/css/bootstrap-responsive.css +1058 -0
  40. package/deps/jq/docs/public/bootstrap/css/bootstrap-responsive.min.css +9 -0
  41. package/deps/jq/docs/public/bootstrap/css/bootstrap.css +5224 -0
  42. package/deps/jq/docs/public/bootstrap/css/bootstrap.min.css +9 -0
  43. package/deps/jq/docs/public/bootstrap/img/glyphicons-halflings-white.png +0 -0
  44. package/deps/jq/docs/public/bootstrap/img/glyphicons-halflings.png +0 -0
  45. package/deps/jq/docs/public/bootstrap/js/bootstrap.js +2027 -0
  46. package/deps/jq/docs/public/bootstrap/js/bootstrap.min.js +6 -0
  47. package/deps/jq/docs/public/css/base.scss +99 -0
  48. package/deps/jq/docs/public/jq.png +0 -0
  49. package/deps/jq/docs/public/robots.txt +2 -0
  50. package/deps/jq/docs/site.yml +18 -0
  51. package/deps/jq/docs/templates/default.liquid +34 -0
  52. package/deps/jq/docs/templates/index.liquid +60 -0
  53. package/deps/jq/docs/templates/manual.liquid +122 -0
  54. package/deps/jq/docs/templates/shared/_footer.liquid +5 -0
  55. package/deps/jq/docs/templates/shared/_head.liquid +12 -0
  56. package/deps/jq/docs/templates/shared/_header.liquid +26 -0
  57. package/deps/jq/exec_stack.h +112 -0
  58. package/deps/jq/execute.c +1155 -0
  59. package/deps/jq/inject_errors.c +112 -0
  60. package/deps/jq/jq.1.default +39 -0
  61. package/deps/jq/jq.1.prebuilt +3075 -0
  62. package/deps/jq/jq.h +60 -0
  63. package/deps/jq/jq.spec +70 -0
  64. package/deps/jq/jq_parser.h +9 -0
  65. package/deps/jq/jq_test.c +346 -0
  66. package/deps/jq/jv.c +1333 -0
  67. package/deps/jq/jv.h +240 -0
  68. package/deps/jq/jv_alloc.c +179 -0
  69. package/deps/jq/jv_alloc.h +27 -0
  70. package/deps/jq/jv_aux.c +619 -0
  71. package/deps/jq/jv_dtoa.c +4275 -0
  72. package/deps/jq/jv_dtoa.h +22 -0
  73. package/deps/jq/jv_file.c +49 -0
  74. package/deps/jq/jv_parse.c +852 -0
  75. package/deps/jq/jv_print.c +348 -0
  76. package/deps/jq/jv_unicode.c +96 -0
  77. package/deps/jq/jv_unicode.h +11 -0
  78. package/deps/jq/jv_utf8_tables.h +37 -0
  79. package/deps/jq/lexer.c +2442 -0
  80. package/deps/jq/lexer.h +362 -0
  81. package/deps/jq/lexer.l +184 -0
  82. package/deps/jq/libm.h +160 -0
  83. package/deps/jq/linker.c +393 -0
  84. package/deps/jq/linker.h +7 -0
  85. package/deps/jq/locfile.c +91 -0
  86. package/deps/jq/locfile.h +29 -0
  87. package/deps/jq/m4/ax_compare_version.m4 +177 -0
  88. package/deps/jq/m4/ax_prog_bison_version.m4 +68 -0
  89. package/deps/jq/main.c +566 -0
  90. package/deps/jq/opcode_list.h +44 -0
  91. package/deps/jq/parser.c +3914 -0
  92. package/deps/jq/parser.h +193 -0
  93. package/deps/jq/parser.y +923 -0
  94. package/deps/jq/scripts/crosscompile +42 -0
  95. package/deps/jq/scripts/gen_utf8_tables.py +32 -0
  96. package/deps/jq/scripts/version +5 -0
  97. package/deps/jq/setup.sh +33 -0
  98. package/deps/jq/tests/jq.test +1235 -0
  99. package/deps/jq/tests/jqtest +5 -0
  100. package/deps/jq/tests/mantest +7 -0
  101. package/deps/jq/tests/modules/.jq +5 -0
  102. package/deps/jq/tests/modules/a.jq +2 -0
  103. package/deps/jq/tests/modules/b/b.jq +2 -0
  104. package/deps/jq/tests/modules/c/c.jq +16 -0
  105. package/deps/jq/tests/modules/c/d.jq +1 -0
  106. package/deps/jq/tests/modules/data.json +4 -0
  107. package/deps/jq/tests/modules/lib/jq/e/e.jq +1 -0
  108. package/deps/jq/tests/modules/lib/jq/f.jq +1 -0
  109. package/deps/jq/tests/modules/syntaxerror/syntaxerror.jq +1 -0
  110. package/deps/jq/tests/modules/test_bind_order.jq +4 -0
  111. package/deps/jq/tests/modules/test_bind_order0.jq +1 -0
  112. package/deps/jq/tests/modules/test_bind_order1.jq +2 -0
  113. package/deps/jq/tests/modules/test_bind_order2.jq +2 -0
  114. package/deps/jq/tests/onig.supp +21 -0
  115. package/deps/jq/tests/onig.test +85 -0
  116. package/deps/jq/tests/onigtest +5 -0
  117. package/deps/jq/tests/setup +36 -0
  118. package/deps/jq/tests/shtest +205 -0
  119. package/deps/jq/tests/torture/input0.json +7 -0
  120. package/deps/jq/util.c +462 -0
  121. package/deps/jq/util.h +64 -0
  122. package/deps/jq.gyp +35 -0
  123. package/index.d.ts +3 -0
  124. package/jest.config.js +10 -0
  125. package/lib/index.js +14 -0
  126. package/package.json +48 -0
  127. package/reports/jest-port-api.xml +35 -0
  128. package/src/binding.cc +177 -0
  129. package/src/binding.h +13 -0
  130. package/test/santiy.test.js +122 -0
  131. package/util/configure.js +27 -0
@@ -0,0 +1,619 @@
1
+ #include <string.h>
2
+ #include <stdlib.h>
3
+ #include <assert.h>
4
+ #include "jv_alloc.h"
5
+
6
+ static int parse_slice(jv j, jv slice, int* pstart, int* pend) {
7
+ // Array slices
8
+ jv start_jv = jv_object_get(jv_copy(slice), jv_string("start"));
9
+ jv end_jv = jv_object_get(slice, jv_string("end"));
10
+ if (jv_get_kind(start_jv) == JV_KIND_NULL) {
11
+ jv_free(start_jv);
12
+ start_jv = jv_number(0);
13
+ }
14
+ int len;
15
+ if (jv_get_kind(j) == JV_KIND_ARRAY) {
16
+ len = jv_array_length(j);
17
+ } else if (jv_get_kind(j) == JV_KIND_STRING) {
18
+ len = jv_string_length_codepoints(j);
19
+ } else {
20
+ jv_free(j);
21
+ return 0;
22
+ }
23
+ if (jv_get_kind(end_jv) == JV_KIND_NULL) {
24
+ jv_free(end_jv);
25
+ end_jv = jv_number(len);
26
+ }
27
+ if (jv_get_kind(start_jv) != JV_KIND_NUMBER ||
28
+ jv_get_kind(end_jv) != JV_KIND_NUMBER) {
29
+ jv_free(start_jv);
30
+ jv_free(end_jv);
31
+ return 0;
32
+ } else {
33
+ double dstart = jv_number_value(start_jv);
34
+ double dend = jv_number_value(end_jv);
35
+ if (dstart < 0) dstart += len;
36
+ if (dend < 0) dend += len;
37
+ if (dstart < 0) dstart = 0;
38
+ if (dstart > len) dstart = len;
39
+
40
+ int start = (int)dstart;
41
+ int end = (dend > len) ? len : (int)dend;
42
+ // Ends are exclusive but e.g. 1 < 1.5 so :1.5 should be :2 not :1
43
+ if(end < dend) end += 1;
44
+
45
+ if (end > len) end = len;
46
+ if (end < start) end = start;
47
+ assert(0 <= start && start <= end && end <= len);
48
+ *pstart = start;
49
+ *pend = end;
50
+ return 1;
51
+ }
52
+ }
53
+
54
+ jv jv_get(jv t, jv k) {
55
+ jv v;
56
+ if (jv_get_kind(t) == JV_KIND_OBJECT && jv_get_kind(k) == JV_KIND_STRING) {
57
+ v = jv_object_get(t, k);
58
+ if (!jv_is_valid(v)) {
59
+ jv_free(v);
60
+ v = jv_null();
61
+ }
62
+ } else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) {
63
+ if(jv_is_integer(k)){
64
+ int idx = (int)jv_number_value(k);
65
+ if (idx < 0)
66
+ idx += jv_array_length(jv_copy(t));
67
+ v = jv_array_get(t, idx);
68
+ if (!jv_is_valid(v)) {
69
+ jv_free(v);
70
+ v = jv_null();
71
+ }
72
+ } else {
73
+ jv_free(t);
74
+ jv_free(k);
75
+ v = jv_null();
76
+ }
77
+ } else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_OBJECT) {
78
+ int start, end;
79
+ if (parse_slice(jv_copy(t), k, &start, &end)) {
80
+ v = jv_array_slice(t, start, end);
81
+ } else {
82
+ jv_free(t);
83
+ v = jv_invalid_with_msg(jv_string_fmt("Start and end indices of an array slice must be numbers"));
84
+ }
85
+ } else if (jv_get_kind(t) == JV_KIND_STRING && jv_get_kind(k) == JV_KIND_OBJECT) {
86
+ int start, end;
87
+ if (parse_slice(jv_copy(t), k, &start, &end)) {
88
+ v = jv_string_slice(t, start, end);
89
+ } else {
90
+ v = jv_invalid_with_msg(jv_string_fmt("Start and end indices of an string slice must be numbers"));
91
+ jv_free(t);
92
+ }
93
+ } else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_ARRAY) {
94
+ v = jv_array_indexes(t, k);
95
+ } else if (jv_get_kind(t) == JV_KIND_NULL &&
96
+ (jv_get_kind(k) == JV_KIND_STRING ||
97
+ jv_get_kind(k) == JV_KIND_NUMBER ||
98
+ jv_get_kind(k) == JV_KIND_OBJECT)) {
99
+ jv_free(t);
100
+ jv_free(k);
101
+ v = jv_null();
102
+ } else {
103
+ /*
104
+ * If k is a short string it's probably from a jq .foo expression or
105
+ * similar, in which case putting it in the invalid msg may help the
106
+ * user. The length 30 is arbitrary.
107
+ */
108
+ if (jv_get_kind(k) == JV_KIND_STRING && jv_string_length_bytes(jv_copy(k)) < 30) {
109
+ v = jv_invalid_with_msg(jv_string_fmt("Cannot index %s with string \"%s\"",
110
+ jv_kind_name(jv_get_kind(t)),
111
+ jv_string_value(k)));
112
+ } else {
113
+ v = jv_invalid_with_msg(jv_string_fmt("Cannot index %s with %s",
114
+ jv_kind_name(jv_get_kind(t)),
115
+ jv_kind_name(jv_get_kind(k))));
116
+ }
117
+ jv_free(t);
118
+ jv_free(k);
119
+ }
120
+ return v;
121
+ }
122
+
123
+ jv jv_set(jv t, jv k, jv v) {
124
+ if (!jv_is_valid(v)) {
125
+ jv_free(t);
126
+ jv_free(k);
127
+ return v;
128
+ }
129
+ int isnull = jv_get_kind(t) == JV_KIND_NULL;
130
+ if (jv_get_kind(k) == JV_KIND_STRING &&
131
+ (jv_get_kind(t) == JV_KIND_OBJECT || isnull)) {
132
+ if (isnull) t = jv_object();
133
+ t = jv_object_set(t, k, v);
134
+ } else if (jv_get_kind(k) == JV_KIND_NUMBER &&
135
+ (jv_get_kind(t) == JV_KIND_ARRAY || isnull)) {
136
+ if (isnull) t = jv_array();
137
+ t = jv_array_set(t, (int)jv_number_value(k), v);
138
+ } else if (jv_get_kind(k) == JV_KIND_OBJECT &&
139
+ (jv_get_kind(t) == JV_KIND_ARRAY || isnull)) {
140
+ if (isnull) t = jv_array();
141
+ int start, end;
142
+ if (parse_slice(jv_copy(t), k, &start, &end)) {
143
+ if (jv_get_kind(v) == JV_KIND_ARRAY) {
144
+ int array_len = jv_array_length(jv_copy(t));
145
+ assert(0 <= start && start <= end && end <= array_len);
146
+ int slice_len = end - start;
147
+ int insert_len = jv_array_length(jv_copy(v));
148
+ if (slice_len < insert_len) {
149
+ // array is growing
150
+ int shift = insert_len - slice_len;
151
+ for (int i = array_len - 1; i >= end; i--) {
152
+ t = jv_array_set(t, i + shift, jv_array_get(jv_copy(t), i));
153
+ }
154
+ } else if (slice_len > insert_len) {
155
+ // array is shrinking
156
+ int shift = slice_len - insert_len;
157
+ for (int i = end; i < array_len; i++) {
158
+ t = jv_array_set(t, i - shift, jv_array_get(jv_copy(t), i));
159
+ }
160
+ t = jv_array_slice(t, 0, array_len - shift);
161
+ }
162
+ for (int i=0; i < insert_len; i++) {
163
+ t = jv_array_set(t, start + i, jv_array_get(jv_copy(v), i));
164
+ }
165
+ jv_free(v);
166
+ } else {
167
+ jv_free(t);
168
+ jv_free(v);
169
+ t = jv_invalid_with_msg(jv_string_fmt("A slice of an array can only be assigned another array"));
170
+ }
171
+ } else {
172
+ jv_free(t);
173
+ jv_free(v);
174
+ t = jv_invalid_with_msg(jv_string_fmt("Start and end indices of an array slice must be numbers"));
175
+ }
176
+ } else {
177
+ jv err = jv_invalid_with_msg(jv_string_fmt("Cannot update field at %s index of %s",
178
+ jv_kind_name(jv_get_kind(k)),
179
+ jv_kind_name(jv_get_kind(t))));
180
+ jv_free(t);
181
+ jv_free(k);
182
+ jv_free(v);
183
+ t = err;
184
+ }
185
+ return t;
186
+ }
187
+
188
+ jv jv_has(jv t, jv k) {
189
+ assert(jv_is_valid(t));
190
+ assert(jv_is_valid(k));
191
+ jv ret;
192
+ if (jv_get_kind(t) == JV_KIND_NULL) {
193
+ jv_free(t);
194
+ jv_free(k);
195
+ ret = jv_false();
196
+ } else if (jv_get_kind(t) == JV_KIND_OBJECT &&
197
+ jv_get_kind(k) == JV_KIND_STRING) {
198
+ jv elem = jv_object_get(t, k);
199
+ ret = jv_bool(jv_is_valid(elem));
200
+ jv_free(elem);
201
+ } else if (jv_get_kind(t) == JV_KIND_ARRAY &&
202
+ jv_get_kind(k) == JV_KIND_NUMBER) {
203
+ jv elem = jv_array_get(t, (int)jv_number_value(k));
204
+ ret = jv_bool(jv_is_valid(elem));
205
+ jv_free(elem);
206
+ } else {
207
+ ret = jv_invalid_with_msg(jv_string_fmt("Cannot check whether %s has a %s key",
208
+ jv_kind_name(jv_get_kind(t)),
209
+ jv_kind_name(jv_get_kind(k))));
210
+ jv_free(t);
211
+ jv_free(k);
212
+ }
213
+ return ret;
214
+ }
215
+
216
+ // assumes keys is a sorted array
217
+ jv jv_dels(jv t, jv keys) {
218
+ assert(jv_get_kind(keys) == JV_KIND_ARRAY);
219
+ assert(jv_is_valid(t));
220
+
221
+ if (jv_get_kind(t) == JV_KIND_NULL || jv_array_length(jv_copy(keys)) == 0) {
222
+ // no change
223
+ } else if (jv_get_kind(t) == JV_KIND_ARRAY) {
224
+ // extract slices, they must be handled differently
225
+ jv orig_keys = keys;
226
+ keys = jv_array();
227
+ jv new_array = jv_array();
228
+ jv starts = jv_array(), ends = jv_array();
229
+ jv_array_foreach(orig_keys, i, key) {
230
+ if (jv_get_kind(key) == JV_KIND_NUMBER) {
231
+ keys = jv_array_append(keys, key);
232
+ } else if (jv_get_kind(key) == JV_KIND_OBJECT) {
233
+ int start, end;
234
+ if (parse_slice(jv_copy(t), key, &start, &end)) {
235
+ starts = jv_array_append(starts, jv_number(start));
236
+ ends = jv_array_append(ends, jv_number(end));
237
+ } else {
238
+ jv_free(new_array);
239
+ new_array = jv_invalid_with_msg(jv_string_fmt("Start and end indices of an array slice must be numbers"));
240
+ goto arr_out;
241
+ }
242
+ } else {
243
+ jv_free(new_array);
244
+ new_array = jv_invalid_with_msg(jv_string_fmt("Cannot delete %s element of array",
245
+ jv_kind_name(jv_get_kind(key))));
246
+ jv_free(key);
247
+ goto arr_out;
248
+ }
249
+ }
250
+
251
+ int kidx = 0;
252
+ jv_array_foreach(t, i, elem) {
253
+ int del = 0;
254
+ while (kidx < jv_array_length(jv_copy(keys))) {
255
+ int delidx = (int)jv_number_value(jv_array_get(jv_copy(keys), kidx));
256
+ if (i == delidx) {
257
+ del = 1;
258
+ }
259
+ if (i < delidx) {
260
+ break;
261
+ }
262
+ kidx++;
263
+ }
264
+ for (int sidx=0; !del && sidx<jv_array_length(jv_copy(starts)); sidx++) {
265
+ if ((int)jv_number_value(jv_array_get(jv_copy(starts), sidx)) <= i &&
266
+ i < (int)jv_number_value(jv_array_get(jv_copy(ends), sidx))) {
267
+ del = 1;
268
+ }
269
+ }
270
+ if (!del)
271
+ new_array = jv_array_append(new_array, elem);
272
+ else
273
+ jv_free(elem);
274
+ }
275
+ arr_out:
276
+ jv_free(starts);
277
+ jv_free(ends);
278
+ jv_free(orig_keys);
279
+ jv_free(t);
280
+ t = new_array;
281
+ } else if (jv_get_kind(t) == JV_KIND_OBJECT) {
282
+ jv_array_foreach(keys, i, k) {
283
+ if (jv_get_kind(k) != JV_KIND_STRING) {
284
+ jv_free(t);
285
+ t = jv_invalid_with_msg(jv_string_fmt("Cannot delete %s field of object",
286
+ jv_kind_name(jv_get_kind(k))));
287
+ jv_free(k);
288
+ break;
289
+ }
290
+ t = jv_object_delete(t, k);
291
+ }
292
+ } else {
293
+ jv err = jv_invalid_with_msg(jv_string_fmt("Cannot delete fields from %s",
294
+ jv_kind_name(jv_get_kind(t))));
295
+ jv_free(t);
296
+ t = err;
297
+ }
298
+ jv_free(keys);
299
+ return t;
300
+ }
301
+
302
+ jv jv_setpath(jv root, jv path, jv value) {
303
+ if (jv_get_kind(path) != JV_KIND_ARRAY) {
304
+ jv_free(value);
305
+ jv_free(root);
306
+ jv_free(path);
307
+ return jv_invalid_with_msg(jv_string("Path must be specified as an array"));
308
+ }
309
+ if (!jv_is_valid(root)){
310
+ jv_free(value);
311
+ jv_free(path);
312
+ return root;
313
+ }
314
+ if (jv_array_length(jv_copy(path)) == 0) {
315
+ jv_free(path);
316
+ jv_free(root);
317
+ return value;
318
+ }
319
+ jv pathcurr = jv_array_get(jv_copy(path), 0);
320
+ jv pathrest = jv_array_slice(path, 1, jv_array_length(jv_copy(path)));
321
+ return jv_set(root, pathcurr,
322
+ jv_setpath(jv_get(jv_copy(root), jv_copy(pathcurr)), pathrest, value));
323
+ }
324
+
325
+ jv jv_getpath(jv root, jv path) {
326
+ if (jv_get_kind(path) != JV_KIND_ARRAY) {
327
+ jv_free(root);
328
+ jv_free(path);
329
+ return jv_invalid_with_msg(jv_string("Path must be specified as an array"));
330
+ }
331
+ if (!jv_is_valid(root)) {
332
+ jv_free(path);
333
+ return root;
334
+ }
335
+ if (jv_array_length(jv_copy(path)) == 0) {
336
+ jv_free(path);
337
+ return root;
338
+ }
339
+ jv pathcurr = jv_array_get(jv_copy(path), 0);
340
+ jv pathrest = jv_array_slice(path, 1, jv_array_length(jv_copy(path)));
341
+ return jv_getpath(jv_get(root, pathcurr), pathrest);
342
+ }
343
+
344
+ // assumes paths is a sorted array of arrays
345
+ static jv delpaths_sorted(jv object, jv paths, int start) {
346
+ jv delkeys = jv_array();
347
+ for (int i=0; i<jv_array_length(jv_copy(paths));) {
348
+ int j = i;
349
+ assert(jv_array_length(jv_array_get(jv_copy(paths), i)) > start);
350
+ int delkey = jv_array_length(jv_array_get(jv_copy(paths), i)) == start + 1;
351
+ jv key = jv_array_get(jv_array_get(jv_copy(paths), i), start);
352
+ while (j < jv_array_length(jv_copy(paths)) &&
353
+ jv_equal(jv_copy(key), jv_array_get(jv_array_get(jv_copy(paths), j), start)))
354
+ j++;
355
+ // if i <= entry < j, then entry starts with key
356
+ if (delkey) {
357
+ // deleting this entire key, we don't care about any more specific deletions
358
+ delkeys = jv_array_append(delkeys, key);
359
+ } else {
360
+ // deleting certain sub-parts of this key
361
+ jv subobject = jv_get(jv_copy(object), jv_copy(key));
362
+ if (!jv_is_valid(subobject)) {
363
+ jv_free(key);
364
+ jv_free(object);
365
+ object = subobject;
366
+ break;
367
+ } else if (jv_get_kind(subobject) == JV_KIND_NULL) {
368
+ jv_free(key);
369
+ jv_free(subobject);
370
+ } else {
371
+ jv newsubobject = delpaths_sorted(subobject, jv_array_slice(jv_copy(paths), i, j), start+1);
372
+ if (!jv_is_valid(newsubobject)) {
373
+ jv_free(key);
374
+ jv_free(object);
375
+ object = newsubobject;
376
+ break;
377
+ }
378
+ object = jv_set(object, key, newsubobject);
379
+ }
380
+ if (!jv_is_valid(object)) break;
381
+ }
382
+ i = j;
383
+ }
384
+ jv_free(paths);
385
+ if (jv_is_valid(object))
386
+ object = jv_dels(object, delkeys);
387
+ else
388
+ jv_free(delkeys);
389
+ return object;
390
+ }
391
+
392
+ jv jv_delpaths(jv object, jv paths) {
393
+ paths = jv_sort(paths, jv_copy(paths));
394
+ jv_array_foreach(paths, i, elem) {
395
+ if (jv_get_kind(elem) != JV_KIND_ARRAY) {
396
+ jv_free(object);
397
+ jv_free(paths);
398
+ jv err = jv_invalid_with_msg(jv_string_fmt("Path must be specified as array, not %s",
399
+ jv_kind_name(jv_get_kind(elem))));
400
+ jv_free(elem);
401
+ return err;
402
+ }
403
+ jv_free(elem);
404
+ }
405
+ if (jv_array_length(jv_copy(paths)) == 0) {
406
+ // nothing is being deleted
407
+ jv_free(paths);
408
+ return object;
409
+ }
410
+ if (jv_array_length(jv_array_get(jv_copy(paths), 0)) == 0) {
411
+ // everything is being deleted
412
+ jv_free(paths);
413
+ jv_free(object);
414
+ return jv_null();
415
+ }
416
+ return delpaths_sorted(object, paths, 0);
417
+ }
418
+
419
+
420
+ static int string_cmp(const void* pa, const void* pb){
421
+ const jv* a = pa;
422
+ const jv* b = pb;
423
+ int lena = jv_string_length_bytes(jv_copy(*a));
424
+ int lenb = jv_string_length_bytes(jv_copy(*b));
425
+ int minlen = lena < lenb ? lena : lenb;
426
+ int r = memcmp(jv_string_value(*a), jv_string_value(*b), minlen);
427
+ if (r == 0) r = lena - lenb;
428
+ return r;
429
+ }
430
+
431
+ jv jv_keys_unsorted(jv x) {
432
+ if (jv_get_kind(x) != JV_KIND_OBJECT)
433
+ return jv_keys(x);
434
+ jv answer = jv_array_sized(jv_object_length(jv_copy(x)));
435
+ jv_object_foreach(x, key, value) {
436
+ answer = jv_array_append(answer, key);
437
+ jv_free(value);
438
+ }
439
+ jv_free(x);
440
+ return answer;
441
+ }
442
+
443
+ jv jv_keys(jv x) {
444
+ if (jv_get_kind(x) == JV_KIND_OBJECT) {
445
+ int nkeys = jv_object_length(jv_copy(x));
446
+ jv* keys = jv_mem_alloc(sizeof(jv) * nkeys);
447
+ int kidx = 0;
448
+ jv_object_foreach(x, key, value) {
449
+ keys[kidx++] = key;
450
+ jv_free(value);
451
+ }
452
+ qsort(keys, nkeys, sizeof(jv), string_cmp);
453
+ jv answer = jv_array_sized(nkeys);
454
+ for (int i = 0; i<nkeys; i++) {
455
+ answer = jv_array_append(answer, keys[i]);
456
+ }
457
+ jv_mem_free(keys);
458
+ jv_free(x);
459
+ return answer;
460
+ } else if (jv_get_kind(x) == JV_KIND_ARRAY) {
461
+ int n = jv_array_length(x);
462
+ jv answer = jv_array();
463
+ for (int i=0; i<n; i++){
464
+ answer = jv_array_set(answer, i, jv_number(i));
465
+ }
466
+ return answer;
467
+ } else {
468
+ assert(0 && "jv_keys passed something neither object nor array");
469
+ return jv_invalid();
470
+ }
471
+ }
472
+
473
+ int jv_cmp(jv a, jv b) {
474
+ if (jv_get_kind(a) != jv_get_kind(b)) {
475
+ int r = (int)jv_get_kind(a) - (int)jv_get_kind(b);
476
+ jv_free(a);
477
+ jv_free(b);
478
+ return r;
479
+ }
480
+ int r = 0;
481
+ switch (jv_get_kind(a)) {
482
+ default:
483
+ assert(0 && "invalid kind passed to jv_cmp");
484
+ case JV_KIND_NULL:
485
+ case JV_KIND_FALSE:
486
+ case JV_KIND_TRUE:
487
+ // there's only one of each of these values
488
+ r = 0;
489
+ break;
490
+
491
+ case JV_KIND_NUMBER: {
492
+ double da = jv_number_value(a), db = jv_number_value(b);
493
+
494
+ // handle NaN as though it were null
495
+ if (da != da) r = jv_cmp(jv_null(), jv_number(db));
496
+ else if (db != db) r = jv_cmp(jv_number(da), jv_null());
497
+ else if (da < db) r = -1;
498
+ else if (da == db) r = 0;
499
+ else r = 1;
500
+ break;
501
+ }
502
+
503
+ case JV_KIND_STRING: {
504
+ r = string_cmp(&a, &b);
505
+ break;
506
+ }
507
+
508
+ case JV_KIND_ARRAY: {
509
+ // Lexical ordering of arrays
510
+ int i = 0;
511
+ while (r == 0) {
512
+ int a_done = i >= jv_array_length(jv_copy(a));
513
+ int b_done = i >= jv_array_length(jv_copy(b));
514
+ if (a_done || b_done) {
515
+ r = b_done - a_done; //suddenly, logic
516
+ break;
517
+ }
518
+ jv xa = jv_array_get(jv_copy(a), i);
519
+ jv xb = jv_array_get(jv_copy(b), i);
520
+ r = jv_cmp(xa, xb);
521
+ i++;
522
+ }
523
+ break;
524
+ }
525
+
526
+ case JV_KIND_OBJECT: {
527
+ jv keys_a = jv_keys(jv_copy(a));
528
+ jv keys_b = jv_keys(jv_copy(b));
529
+ r = jv_cmp(jv_copy(keys_a), keys_b);
530
+ if (r == 0) {
531
+ jv_array_foreach(keys_a, i, key) {
532
+ jv xa = jv_object_get(jv_copy(a), jv_copy(key));
533
+ jv xb = jv_object_get(jv_copy(b), key);
534
+ r = jv_cmp(xa, xb);
535
+ if (r) break;
536
+ }
537
+ }
538
+ jv_free(keys_a);
539
+ break;
540
+ }
541
+ }
542
+
543
+ jv_free(a);
544
+ jv_free(b);
545
+ return r;
546
+ }
547
+
548
+
549
+ struct sort_entry {
550
+ jv object;
551
+ jv key;
552
+ };
553
+
554
+ static int sort_cmp(const void* pa, const void* pb) {
555
+ const struct sort_entry* a = pa;
556
+ const struct sort_entry* b = pb;
557
+ int r = jv_cmp(jv_copy(a->key), jv_copy(b->key));
558
+ // comparing by address if r == 0 makes the sort stable
559
+ return r ? r : (int)(a - b);
560
+ }
561
+
562
+ static struct sort_entry* sort_items(jv objects, jv keys) {
563
+ assert(jv_get_kind(objects) == JV_KIND_ARRAY);
564
+ assert(jv_get_kind(keys) == JV_KIND_ARRAY);
565
+ assert(jv_array_length(jv_copy(objects)) == jv_array_length(jv_copy(keys)));
566
+ int n = jv_array_length(jv_copy(objects));
567
+ struct sort_entry* entries = jv_mem_alloc(sizeof(struct sort_entry) * n);
568
+ for (int i=0; i<n; i++) {
569
+ entries[i].object = jv_array_get(jv_copy(objects), i);
570
+ entries[i].key = jv_array_get(jv_copy(keys), i);
571
+ }
572
+ jv_free(objects);
573
+ jv_free(keys);
574
+ qsort(entries, n, sizeof(struct sort_entry), sort_cmp);
575
+ return entries;
576
+ }
577
+
578
+ jv jv_sort(jv objects, jv keys) {
579
+ assert(jv_get_kind(objects) == JV_KIND_ARRAY);
580
+ assert(jv_get_kind(keys) == JV_KIND_ARRAY);
581
+ assert(jv_array_length(jv_copy(objects)) == jv_array_length(jv_copy(keys)));
582
+ int n = jv_array_length(jv_copy(objects));
583
+ struct sort_entry* entries = sort_items(objects, keys);
584
+ jv ret = jv_array();
585
+ for (int i=0; i<n; i++) {
586
+ jv_free(entries[i].key);
587
+ ret = jv_array_set(ret, i, entries[i].object);
588
+ }
589
+ jv_mem_free(entries);
590
+ return ret;
591
+ }
592
+
593
+ jv jv_group(jv objects, jv keys) {
594
+ assert(jv_get_kind(objects) == JV_KIND_ARRAY);
595
+ assert(jv_get_kind(keys) == JV_KIND_ARRAY);
596
+ assert(jv_array_length(jv_copy(objects)) == jv_array_length(jv_copy(keys)));
597
+ int n = jv_array_length(jv_copy(objects));
598
+ struct sort_entry* entries = sort_items(objects, keys);
599
+ jv ret = jv_array();
600
+ if (n > 0) {
601
+ jv curr_key = entries[0].key;
602
+ jv group = jv_array_append(jv_array(), entries[0].object);
603
+ for (int i = 1; i < n; i++) {
604
+ if (jv_equal(jv_copy(curr_key), jv_copy(entries[i].key))) {
605
+ jv_free(entries[i].key);
606
+ } else {
607
+ jv_free(curr_key);
608
+ curr_key = entries[i].key;
609
+ ret = jv_array_append(ret, group);
610
+ group = jv_array();
611
+ }
612
+ group = jv_array_append(group, entries[i].object);
613
+ }
614
+ jv_free(curr_key);
615
+ ret = jv_array_append(ret, group);
616
+ }
617
+ jv_mem_free(entries);
618
+ return ret;
619
+ }