1 // This file is part of Jiffy released under the MIT license.
2 // See the LICENSE file for more information.
3
4 #include <assert.h>
5 #include <errno.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "erl_nif.h"
11 #include "jiffy.h"
12
13 #define U(c) ((unsigned char) (c))
14 #define ERROR(i, msg) make_error(st, env, msg)
15
16 #define STACK_SIZE_INC 64
17 #define NUM_BUF_LEN 32
18
19 #if WINDOWS || WIN32
20 #define snprintf _snprintf
21 #endif
22
23 enum {
24 st_value=0,
25 st_object,
26 st_array,
27 st_key,
28 st_colon,
29 st_comma,
30 st_done,
31 st_invalid
32 } JsonState;
33
34 enum {
35 nst_init=0,
36 nst_sign,
37 nst_mantissa,
38 nst_frac0,
39 nst_frac1,
40 nst_frac,
41 nst_esign,
42 nst_edigit
43 } JsonNumState;
44
45 typedef struct {
46 ErlNifEnv* env;
47 jiffy_st* atoms;
48
49 ERL_NIF_TERM arg;
50 ErlNifBinary bin;
51
52 size_t bytes_per_red;
53 int is_partial;
54 int return_maps;
55 int return_trailer;
56 int dedupe_keys;
57 int copy_strings;
58 ERL_NIF_TERM null_term;
59
60 unsigned char* p;
61 int i;
62 int len;
63
64 char* st_data;
65 int st_size;
66 int st_top;
67 } Decoder;
68
69 Decoder*
dec_new(ErlNifEnv * env)70 dec_new(ErlNifEnv* env)
71 {
72 jiffy_st* st = (jiffy_st*) enif_priv_data(env);
73 Decoder* d = enif_alloc_resource(st->res_dec, sizeof(Decoder));
74 int i;
75
76 if(d == NULL) {
77 return NULL;
78 }
79
80 d->atoms = st;
81
82 d->bytes_per_red = DEFAULT_BYTES_PER_REDUCTION;
83 d->is_partial = 0;
84 d->return_maps = 0;
85 d->return_trailer = 0;
86 d->dedupe_keys = 0;
87 d->copy_strings = 0;
88 d->null_term = d->atoms->atom_null;
89
90 d->p = NULL;
91 d->len = -1;
92 d->i = 0;
93
94 d->st_data = (char*) enif_alloc(STACK_SIZE_INC);
95 d->st_size = STACK_SIZE_INC;
96 d->st_top = 0;
97
98 for(i = 0; i < d->st_size; i++) {
99 d->st_data[i] = st_invalid;
100 }
101
102 d->st_data[0] = st_value;
103 d->st_top++;
104
105 return d;
106 }
107
108 void
dec_init(Decoder * d,ErlNifEnv * env,ERL_NIF_TERM arg,ErlNifBinary * bin)109 dec_init(Decoder* d, ErlNifEnv* env, ERL_NIF_TERM arg, ErlNifBinary* bin)
110 {
111 d->env = env;
112 d->arg = arg;
113
114 d->p = bin->data;
115 d->len = bin->size;
116 }
117
118 void
dec_destroy(ErlNifEnv * env,void * obj)119 dec_destroy(ErlNifEnv* env, void* obj)
120 {
121 Decoder* d = (Decoder*) obj;
122
123 if(d->st_data != NULL) {
124 enif_free(d->st_data);
125 }
126 }
127
128 ERL_NIF_TERM
dec_error(Decoder * d,const char * atom)129 dec_error(Decoder* d, const char* atom)
130 {
131 ERL_NIF_TERM pos = enif_make_int(d->env, d->i+1);
132 ERL_NIF_TERM msg = make_atom(d->env, atom);
133 ERL_NIF_TERM ret = enif_make_tuple2(d->env, pos, msg);
134 return enif_make_tuple2(d->env, d->atoms->atom_error, ret);
135 }
136
137 char
dec_curr(Decoder * d)138 dec_curr(Decoder* d)
139 {
140 assert(d->st_top > 0);
141 return d->st_data[d->st_top - 1];
142 }
143
144 int
dec_top(Decoder * d)145 dec_top(Decoder* d)
146 {
147 return d->st_top;
148 }
149
150 void
dec_push(Decoder * d,char val)151 dec_push(Decoder* d, char val)
152 {
153 int new_sz;
154 int i;
155
156 if(d->st_top == d->st_size) {
157 new_sz = d->st_size + STACK_SIZE_INC;
158 d->st_data = (char*) enif_realloc(d->st_data, new_sz);
159 d->st_size = new_sz;
160 for(i = d->st_top; i < d->st_size; i++) {
161 d->st_data[i] = st_invalid;
162 }
163 }
164
165 assert(d->st_top < d->st_size);
166 d->st_data[d->st_top++] = val;
167 }
168
169 char
dec_pop(Decoder * d)170 dec_pop(Decoder* d) {
171 char current = st_invalid;
172
173 if (d->st_top > 0) {
174 current = d->st_data[d->st_top - 1];
175 d->st_data[d->st_top - 1] = st_invalid;
176 d->st_top--;
177 }
178
179 return current;
180 }
181
182 void
dec_pop_assert(Decoder * d,char val)183 dec_pop_assert(Decoder* d, char val)
184 {
185 char current = dec_pop(d);
186 assert(current == val && "popped invalid state.");
187 (void)current;
188 }
189
190 int
dec_string(Decoder * d,ERL_NIF_TERM * value)191 dec_string(Decoder* d, ERL_NIF_TERM* value)
192 {
193 int has_escape = 0;
194 int num_escapes = 0;
195 int st;
196 int ulen;
197 int ui;
198 int hi;
199 int lo;
200 char* chrbuf;
201 int chrpos;
202
203 if(d->p[d->i] != '\"') {
204 return 0;
205 }
206 d->i++;
207
208 st = d->i;
209
210 while(d->i < d->len) {
211 if(d->p[d->i] < 0x20) {
212 return 0;
213 } else if(d->p[d->i] == '\"') {
214 d->i++;
215 goto parse;
216 } else if(d->p[d->i] == '\\') {
217 if(d->i+1 >= d->len) {
218 return 0;
219 }
220 has_escape = 1;
221 num_escapes += 1;
222 d->i++;
223 switch(d->p[d->i]) {
224 case '\"':
225 case '\\':
226 case '/':
227 case 'b':
228 case 'f':
229 case 'n':
230 case 'r':
231 case 't':
232 d->i++;
233 break;
234 case 'u':
235 hi = 0;
236 lo = 0;
237 d->i++;
238 if(d->i + 4 >= d->len) {
239 return 0;
240 }
241 hi = int_from_hex(&(d->p[d->i]));
242 if(hi < 0) {
243 return 0;
244 }
245 d->i += 4;
246 if(hi >= 0xD800 && hi < 0xDC00) {
247 if(d->i + 6 >= d->len) {
248 return 0;
249 }
250 if(d->p[d->i++] != '\\') {
251 return 0;
252 } else if(d->p[d->i++] != 'u') {
253 return 0;
254 }
255 lo = int_from_hex(&(d->p[d->i]));
256 if(lo < 0) {
257 return 0;
258 }
259 hi = unicode_from_pair(hi, lo);
260 if(hi < 0) {
261 return 0;
262 }
263 }
264 hi = utf8_len(hi);
265 if(hi < 0) {
266 return 0;
267 }
268 if(lo == 0) {
269 num_escapes += 5 - hi;
270 } else {
271 num_escapes += 11 - hi;
272 }
273 break;
274 default:
275 return 0;
276 }
277 } else if(d->p[d->i] < 0x80) {
278 d->i++;
279 } else {
280 ulen = utf8_validate(&(d->p[d->i]), d->len - d->i);
281 if(ulen < 0) {
282 return 0;
283 }
284 d->i += ulen;
285 }
286 }
287
288 // The goto above ensures that we only
289 // hit this when a string is not terminated
290 // correctly.
291 return 0;
292
293 parse:
294 if(!has_escape && !d->copy_strings) {
295 *value = enif_make_sub_binary(d->env, d->arg, st, (d->i - st - 1));
296 return 1;
297 } else if(!has_escape) {
298 ulen = d->i - 1 - st;
299 chrbuf = (char*) enif_make_new_binary(d->env, ulen, value),
300 memcpy(chrbuf, &(d->p[st]), ulen);
301 return 1;
302 }
303
304 hi = 0;
305 lo = 0;
306
307 ulen = (d->i - 1) - st - num_escapes;
308 chrbuf = (char*) enif_make_new_binary(d->env, ulen, value);
309 chrpos = 0;
310 ui = st;
311 while(ui < d->i - 1) {
312 if(d->p[ui] != '\\') {
313 chrbuf[chrpos++] = d->p[ui++];
314 continue;
315 }
316 ui++;
317 switch(d->p[ui]) {
318 case '\"':
319 case '\\':
320 case '/':
321 chrbuf[chrpos++] = d->p[ui];
322 ui++;
323 break;
324 case 'b':
325 chrbuf[chrpos++] = '\b';
326 ui++;
327 break;
328 case 'f':
329 chrbuf[chrpos++] = '\f';
330 ui++;
331 break;
332 case 'n':
333 chrbuf[chrpos++] = '\n';
334 ui++;
335 break;
336 case 'r':
337 chrbuf[chrpos++] = '\r';
338 ui++;
339 break;
340 case 't':
341 chrbuf[chrpos++] = '\t';
342 ui++;
343 break;
344 case 'u':
345 ui++;
346 hi = int_from_hex(&(d->p[ui]));
347 if(hi < 0) {
348 return 0;
349 }
350 if(hi >= 0xD800 && hi < 0xDC00) {
351 lo = int_from_hex(&(d->p[ui+6]));
352 if(lo < 0) {
353 return 0;
354 }
355 hi = unicode_from_pair(hi, lo);
356 ui += 10;
357 } else {
358 ui += 4;
359 }
360 hi = unicode_to_utf8(hi, (unsigned char*) chrbuf+chrpos);
361 if(hi < 0) {
362 return 0;
363 }
364 chrpos += hi;
365 break;
366 default:
367 return 0;
368 }
369 }
370
371 return 1;
372 }
373
374 int
dec_number(Decoder * d,ERL_NIF_TERM * value)375 dec_number(Decoder* d, ERL_NIF_TERM* value)
376 {
377 ERL_NIF_TERM num_type = d->atoms->atom_error;
378 char state = nst_init;
379 char nbuf[NUM_BUF_LEN];
380 int st = d->i;
381 int has_frac = 0;
382 int has_exp = 0;
383 double dval;
384 long lval;
385
386 while(d->i < d->len) {
387 switch(state) {
388 case nst_init:
389 switch(d->p[d->i]) {
390 case '-':
391 state = nst_sign;
392 d->i++;
393 break;
394 case '0':
395 state = nst_frac0;
396 d->i++;
397 break;
398 case '1':
399 case '2':
400 case '3':
401 case '4':
402 case '5':
403 case '6':
404 case '7':
405 case '8':
406 case '9':
407 state = nst_mantissa;
408 d->i++;
409 break;
410 default:
411 return 0;
412 }
413 break;
414
415 case nst_sign:
416 switch(d->p[d->i]) {
417 case '0':
418 state = nst_frac0;
419 d->i++;
420 break;
421 case '1':
422 case '2':
423 case '3':
424 case '4':
425 case '5':
426 case '6':
427 case '7':
428 case '8':
429 case '9':
430 state = nst_mantissa;
431 d->i++;
432 break;
433 default:
434 return 0;
435 }
436 break;
437
438 case nst_mantissa:
439 switch(d->p[d->i]) {
440 case '.':
441 state = nst_frac1;
442 d->i++;
443 break;
444 case 'e':
445 case 'E':
446 state = nst_esign;
447 d->i++;
448 break;
449 case '0':
450 case '1':
451 case '2':
452 case '3':
453 case '4':
454 case '5':
455 case '6':
456 case '7':
457 case '8':
458 case '9':
459 d->i++;
460 break;
461 default:
462 goto parse;
463 }
464 break;
465
466 case nst_frac0:
467 switch(d->p[d->i]) {
468 case '.':
469 state = nst_frac1;
470 d->i++;
471 break;
472 case 'e':
473 case 'E':
474 state = nst_esign;
475 d->i++;
476 break;
477 default:
478 goto parse;
479 }
480 break;
481
482 case nst_frac1:
483 has_frac = 1;
484 switch(d->p[d->i]) {
485 case '0':
486 case '1':
487 case '2':
488 case '3':
489 case '4':
490 case '5':
491 case '6':
492 case '7':
493 case '8':
494 case '9':
495 state = nst_frac;
496 d->i++;
497 break;
498 default:
499 goto parse;
500 }
501 break;
502
503 case nst_frac:
504 switch(d->p[d->i]) {
505 case 'e':
506 case 'E':
507 state = nst_esign;
508 d->i++;
509 break;
510 case '0':
511 case '1':
512 case '2':
513 case '3':
514 case '4':
515 case '5':
516 case '6':
517 case '7':
518 case '8':
519 case '9':
520 d->i++;
521 break;
522 default:
523 goto parse;
524 }
525 break;
526
527 case nst_esign:
528 has_exp = 1;
529 switch(d->p[d->i]) {
530 case '-':
531 case '+':
532 case '0':
533 case '1':
534 case '2':
535 case '3':
536 case '4':
537 case '5':
538 case '6':
539 case '7':
540 case '8':
541 case '9':
542 state = nst_edigit;
543 d->i++;
544 break;
545 default:
546 return 0;
547 }
548 break;
549
550 case nst_edigit:
551 switch(d->p[d->i]) {
552 case '0':
553 case '1':
554 case '2':
555 case '3':
556 case '4':
557 case '5':
558 case '6':
559 case '7':
560 case '8':
561 case '9':
562 d->i++;
563 break;
564 default:
565 goto parse;
566 }
567 break;
568
569 default:
570 return 0;
571 }
572 }
573
574 parse:
575
576 switch(state) {
577 case nst_init:
578 case nst_sign:
579 case nst_frac1:
580 case nst_esign:
581 return 0;
582 default:
583 break;
584 }
585
586 errno = 0;
587
588 if(d->i - st < NUM_BUF_LEN) {
589 memset(nbuf, 0, NUM_BUF_LEN);
590 memcpy(nbuf, &(d->p[st]), d->i - st);
591
592 if(has_frac || has_exp) {
593 dval = strtod(nbuf, NULL);
594 if(errno != ERANGE) {
595 *value = enif_make_double(d->env, dval);
596 return 1;
597 }
598 } else {
599 lval = strtol(nbuf, NULL, 10);
600 if(errno != ERANGE) {
601 *value = enif_make_int64(d->env, lval);
602 return 1;
603 }
604 }
605 }
606
607 if(!has_frac && !has_exp) {
608 num_type = d->atoms->atom_bignum;
609 } else if(!has_frac && has_exp) {
610 num_type = d->atoms->atom_bignum_e;
611 } else {
612 num_type = d->atoms->atom_bigdbl;
613 }
614
615 d->is_partial = 1;
616 *value = enif_make_sub_binary(d->env, d->arg, st, d->i - st);
617 *value = enif_make_tuple2(d->env, num_type, *value);
618 return 1;
619 }
620
621 ERL_NIF_TERM
make_empty_object(ErlNifEnv * env,int ret_map)622 make_empty_object(ErlNifEnv* env, int ret_map)
623 {
624 #if MAP_TYPE_PRESENT
625 if(ret_map) {
626 return enif_make_new_map(env);
627 }
628 #endif
629
630 return enif_make_tuple1(env, enif_make_list(env, 0));
631 }
632
633 ERL_NIF_TERM
make_array(ErlNifEnv * env,ERL_NIF_TERM list)634 make_array(ErlNifEnv* env, ERL_NIF_TERM list)
635 {
636 ERL_NIF_TERM ret = enif_make_list(env, 0);
637 ERL_NIF_TERM item;
638
639 while(enif_get_list_cell(env, list, &item, &list)) {
640 ret = enif_make_list_cell(env, item, ret);
641 }
642
643 return ret;
644 }
645
646 ERL_NIF_TERM
decode_init(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])647 decode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
648 {
649 Decoder* d;
650 jiffy_st* st = (jiffy_st*) enif_priv_data(env);
651 ERL_NIF_TERM tmp_argv[5];
652 ERL_NIF_TERM opts;
653 ERL_NIF_TERM val;
654
655 if(argc != 2) {
656 return enif_make_badarg(env);
657 }
658
659 d = dec_new(env);
660 if(d == NULL) {
661 return make_error(st, env, "internal_error");
662 }
663
664 tmp_argv[0] = argv[0];
665 tmp_argv[1] = enif_make_resource(env, d);
666 tmp_argv[2] = st->atom_error;
667 tmp_argv[3] = enif_make_list(env, 0);
668 tmp_argv[4] = enif_make_list(env, 0);
669
670 enif_release_resource(d);
671
672 opts = argv[1];
673 if(!enif_is_list(env, opts)) {
674 return enif_make_badarg(env);
675 }
676
677 while(enif_get_list_cell(env, opts, &val, &opts)) {
678 if(get_bytes_per_iter(env, val, &(d->bytes_per_red))) {
679 continue;
680 } else if(get_bytes_per_red(env, val, &(d->bytes_per_red))) {
681 continue;
682 } else if(enif_is_identical(val, d->atoms->atom_return_maps)) {
683 #if MAP_TYPE_PRESENT
684 d->return_maps = 1;
685 #else
686 return enif_make_badarg(env);
687 #endif
688 } else if(enif_is_identical(val, d->atoms->atom_return_trailer)) {
689 d->return_trailer = 1;
690 } else if(enif_is_identical(val, d->atoms->atom_dedupe_keys)) {
691 d->dedupe_keys = 1;
692 } else if(enif_is_identical(val, d->atoms->atom_copy_strings)) {
693 d->copy_strings = 1;
694 } else if(enif_is_identical(val, d->atoms->atom_use_nil)) {
695 d->null_term = d->atoms->atom_nil;
696 } else if(get_null_term(env, val, &(d->null_term))) {
697 continue;
698 } else {
699 return enif_make_badarg(env);
700 }
701 }
702
703 return decode_iter(env, 5, tmp_argv);
704 }
705
706 ERL_NIF_TERM
decode_iter(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])707 decode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
708 {
709 Decoder* d;
710 jiffy_st* st = (jiffy_st*) enif_priv_data(env);
711
712 ErlNifBinary bin;
713
714 ERL_NIF_TERM objs;
715 ERL_NIF_TERM curr;
716 ERL_NIF_TERM val = argv[2];
717 ERL_NIF_TERM trailer;
718 ERL_NIF_TERM ret;
719 ERL_NIF_TERM tmp_argv[5];
720
721 void* res;
722
723 size_t start;
724 size_t bytes_processed = 0;
725
726 if(!enif_inspect_binary(env, argv[0], &bin)) {
727 return enif_make_badarg(env);
728 } else if(!enif_get_resource(env, argv[1], st->res_dec, &res)) {
729 return enif_make_badarg(env);
730 }
731
732 d = (Decoder*) res;
733
734 dec_init(d, env, argv[0], &bin);
735 objs = argv[3];
736 curr = argv[4];
737
738 start = d->i;
739
740 while(d->i < bin.size) {
741 bytes_processed = d->i - start;
742
743 if(should_yield(bytes_processed, d->bytes_per_red)) {
744 assert(enif_is_list(env, objs));
745 assert(enif_is_list(env, curr));
746
747 tmp_argv[0] = argv[0];
748 tmp_argv[1] = argv[1];
749 tmp_argv[2] = val;
750 tmp_argv[3] = objs;
751 tmp_argv[4] = curr;
752
753 bump_used_reds(env, bytes_processed, d->bytes_per_red);
754
755 #if SCHEDULE_NIF_PRESENT
756 return enif_schedule_nif(
757 env,
758 "nif_decode_iter",
759 0,
760 decode_iter,
761 5,
762 tmp_argv
763 );
764 #else
765 return enif_make_tuple2(
766 env,
767 st->atom_iter,
768 enif_make_tuple_from_array(env, tmp_argv, 5)
769 );
770 #endif
771 }
772
773 switch(dec_curr(d)) {
774 case st_value:
775 switch(d->p[d->i]) {
776 case ' ':
777 case '\n':
778 case '\r':
779 case '\t':
780 d->i++;
781 break;
782 case 'n':
783 if(d->i + 3 >= d->len) {
784 ret = dec_error(d, "invalid_literal");
785 goto done;
786 }
787 if(memcmp(&(d->p[d->i]), "null", 4) != 0) {
788 ret = dec_error(d, "invalid_literal");
789 goto done;
790 }
791 val = d->null_term;
792 dec_pop_assert(d, st_value);
793 d->i += 4;
794 break;
795 case 't':
796 if(d->i + 3 >= d->len) {
797 ret = dec_error(d, "invalid_literal");
798 goto done;
799 }
800 if(memcmp(&(d->p[d->i]), "true", 4) != 0) {
801 ret = dec_error(d, "invalid_literal");
802 goto done;
803 }
804 val = d->atoms->atom_true;
805 dec_pop_assert(d, st_value);
806 d->i += 4;
807 break;
808 case 'f':
809 if(d->i + 4 >= bin.size) {
810 ret = dec_error(d, "invalid_literal");
811 goto done;
812 }
813 if(memcmp(&(d->p[d->i]), "false", 5) != 0) {
814 ret = dec_error(d, "invalid_literal");
815 goto done;
816 }
817 val = d->atoms->atom_false;
818 dec_pop_assert(d, st_value);
819 d->i += 5;
820 break;
821 case '\"':
822 if(!dec_string(d, &val)) {
823 ret = dec_error(d, "invalid_string");
824 goto done;
825 }
826 dec_pop_assert(d, st_value);
827 break;
828 case '-':
829 case '0':
830 case '1':
831 case '2':
832 case '3':
833 case '4':
834 case '5':
835 case '6':
836 case '7':
837 case '8':
838 case '9':
839 if(!dec_number(d, &val)) {
840 ret = dec_error(d, "invalid_number");
841 goto done;
842 }
843 dec_pop_assert(d, st_value);
844 break;
845 case '{':
846 dec_push(d, st_object);
847 dec_push(d, st_key);
848 objs = enif_make_list_cell(env, curr, objs);
849 curr = enif_make_list(env, 0);
850 d->i++;
851 break;
852 case '[':
853 dec_push(d, st_array);
854 dec_push(d, st_value);
855 objs = enif_make_list_cell(env, curr, objs);
856 curr = enif_make_list(env, 0);
857 d->i++;
858 break;
859 case ']':
860 if(!enif_is_empty_list(env, curr)) {
861 ret = dec_error(d, "invalid_json");
862 goto done;
863 }
864 dec_pop_assert(d, st_value);
865 if(dec_pop(d) != st_array) {
866 ret = dec_error(d, "invalid_json");
867 goto done;
868 }
869 dec_pop_assert(d, st_value);
870 val = curr; // curr is []
871 if(!enif_get_list_cell(env, objs, &curr, &objs)) {
872 ret = dec_error(d, "internal_error");
873 goto done;
874 }
875 d->i++;
876 break;
877 default:
878 ret = dec_error(d, "invalid_json");
879 goto done;
880 }
881 if(dec_top(d) == 0) {
882 dec_push(d, st_done);
883 } else if(dec_curr(d) != st_value && dec_curr(d) != st_key) {
884 dec_push(d, st_comma);
885 curr = enif_make_list_cell(env, val, curr);
886 }
887 break;
888
889 case st_key:
890 switch(d->p[d->i]) {
891 case ' ':
892 case '\n':
893 case '\r':
894 case '\t':
895 d->i++;
896 break;
897 case '\"':
898 if(!dec_string(d, &val)) {
899 ret = dec_error(d, "invalid_string");
900 goto done;
901 }
902 dec_pop_assert(d, st_key);
903 dec_push(d, st_colon);
904 curr = enif_make_list_cell(env, val, curr);
905 break;
906 case '}':
907 if(!enif_is_empty_list(env, curr)) {
908 ret = dec_error(d, "invalid_json");
909 goto done;
910 }
911 dec_pop_assert(d, st_key);
912 dec_pop_assert(d, st_object);
913 dec_pop_assert(d, st_value);
914 val = make_empty_object(env, d->return_maps);
915 if(!enif_get_list_cell(env, objs, &curr, &objs)) {
916 ret = dec_error(d, "internal_error");
917 goto done;
918 }
919 if(dec_top(d) == 0) {
920 dec_push(d, st_done);
921 } else {
922 dec_push(d, st_comma);
923 curr = enif_make_list_cell(env, val, curr);
924 }
925 d->i++;
926 break;
927 default:
928 ret = dec_error(d, "invalid_json");
929 goto done;
930 }
931 break;
932
933 case st_colon:
934 switch(d->p[d->i]) {
935 case ' ':
936 case '\n':
937 case '\r':
938 case '\t':
939 d->i++;
940 break;
941 case ':':
942 dec_pop_assert(d, st_colon);
943 dec_push(d, st_value);
944 d->i++;
945 break;
946 default:
947 ret = dec_error(d, "invalid_json");
948 goto done;
949 }
950 break;
951
952 case st_comma:
953 switch(d->p[d->i]) {
954 case ' ':
955 case '\n':
956 case '\r':
957 case '\t':
958 d->i++;
959 break;
960 case ',':
961 dec_pop_assert(d, st_comma);
962 switch(dec_curr(d)) {
963 case st_object:
964 dec_push(d, st_key);
965 break;
966 case st_array:
967 dec_push(d, st_value);
968 break;
969 default:
970 ret = dec_error(d, "internal_error");
971 goto done;
972 }
973 d->i++;
974 break;
975 case '}':
976 dec_pop_assert(d, st_comma);
977 if(dec_pop(d) != st_object) {
978 ret = dec_error(d, "invalid_json");
979 goto done;
980 }
981 dec_pop_assert(d, st_value);
982 if(!make_object(env, curr, &val,
983 d->return_maps, d->dedupe_keys)) {
984 ret = dec_error(d, "internal_object_error");
985 goto done;
986 }
987 if(!enif_get_list_cell(env, objs, &curr, &objs)) {
988 ret = dec_error(d, "internal_error");
989 goto done;
990 }
991 if(dec_top(d) > 0) {
992 dec_push(d, st_comma);
993 curr = enif_make_list_cell(env, val, curr);
994 } else {
995 dec_push(d, st_done);
996 }
997 d->i++;
998 break;
999 case ']':
1000 dec_pop_assert(d, st_comma);
1001 if(dec_pop(d) != st_array) {
1002 ret = dec_error(d, "invalid_json");
1003 goto done;
1004 }
1005 dec_pop_assert(d, st_value);
1006 val = make_array(env, curr);
1007 if(!enif_get_list_cell(env, objs, &curr, &objs)) {
1008 ret = dec_error(d, "internal_error");
1009 goto done;
1010 }
1011 if(dec_top(d) > 0) {
1012 dec_push(d, st_comma);
1013 curr = enif_make_list_cell(env, val, curr);
1014 } else {
1015 dec_push(d, st_done);
1016 }
1017 d->i++;
1018 break;
1019 default:
1020 ret = dec_error(d, "invalid_json");
1021 goto done;
1022 }
1023 break;
1024
1025 case st_done:
1026 switch(d->p[d->i]) {
1027 case ' ':
1028 case '\n':
1029 case '\r':
1030 case '\t':
1031 d->i++;
1032 break;
1033 default:
1034 goto decode_done;
1035 }
1036 break;
1037
1038 default:
1039 ret = dec_error(d, "invalid_internal_state");
1040 goto done;
1041 }
1042 }
1043
1044 decode_done:
1045
1046 if(d->i < bin.size && d->return_trailer) {
1047 trailer = enif_make_sub_binary(env, argv[0], d->i, bin.size - d->i);
1048 val = enif_make_tuple3(env, d->atoms->atom_has_trailer, val, trailer);
1049 } else if(d->i < bin.size) {
1050 ret = dec_error(d, "invalid_trailing_data");
1051 goto done;
1052 }
1053
1054 if(dec_pop(d) != st_done) {
1055 ret = dec_error(d, "truncated_json");
1056 } else if(d->is_partial) {
1057 ret = enif_make_tuple2(env, d->atoms->atom_partial, val);
1058 } else {
1059 ret = val;
1060 }
1061
1062 done:
1063 bump_used_reds(env, bytes_processed, d->bytes_per_red);
1064
1065 return ret;
1066 }
1067