1 /*
2  * Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
3  *
4  * Jansson is free software; you can redistribute it and/or modify
5  * it under the terms of the MIT license. See LICENSE for details.
6  */
7 /**
8  * License: MIT
9  */
10 module jansson_d.load;
11 
12 
13 package:
14 
15 private static import core.stdc.errno;
16 private static import core.stdc.stdio;
17 private static import core.stdc.stdlib;
18 private static import core.stdc.string;
19 private static import core.sys.posix.unistd;
20 private static import jansson_d.jansson;
21 private static import jansson_d.jansson_config;
22 private static import jansson_d.jansson_private;
23 private static import jansson_d.strbuffer;
24 private static import jansson_d.utf;
25 private static import jansson_d.value;
26 
27 enum STREAM_STATE_OK = 0;
28 enum STREAM_STATE_EOF = -1;
29 enum STREAM_STATE_ERROR = -2;
30 
31 enum TOKEN_INVALID = -1;
32 enum TOKEN_EOF = 0;
33 enum TOKEN_STRING = 256;
34 enum TOKEN_INTEGER = 257;
35 enum TOKEN_REAL = 258;
36 enum TOKEN_TRUE = 259;
37 enum TOKEN_FALSE = 260;
38 enum TOKEN_NULL = 261;
39 
40 /* Locale independent versions of isxxx() functions */
41 private template l_isupper(string c)
42 {
43 	enum l_isupper = "(('A' <= (c)) && ((c) <= 'Z'))";
44 }
45 
46 private template l_islower(string c)
47 {
48 	enum l_islower = "(('a' <= (c)) && ((c) <= 'z'))";
49 }
50 
51 private template l_isalpha(string c)
52 {
53 	enum l_isalpha = "((mixin (jansson_d.load.l_isupper!(\"" ~ c ~ "\"))) || (mixin (jansson_d.load.l_islower!(\"" ~ c ~ "\"))))";
54 }
55 
56 private template l_isdigit(string c)
57 {
58 	enum l_isdigit = "(('0' <= (c)) && ((c) <= '9'))";
59 }
60 
61 private template l_isxdigit(string c)
62 {
63 	enum l_isxdigit = "((mixin (jansson_d.load.l_isdigit!(\"" ~ c ~ "\"))) || (('A' <= (c)) && ((c) <= 'F')) || (('a' <= (c)) && ((c) <= 'f')))";
64 }
65 
66 /*
67  * Read one byte from stream, convert to ubyte, then int, and
68  * return. return EOF on end of file. This corresponds to the
69  * behaviour of fgetc().
70  */
71 alias get_func = extern (C) nothrow @nogc @live int function(scope void* data);
72 
73 struct stream_t
74 {
75 	.get_func get;
76 	void* data;
77 	char[5] buffer = '\0';
78 	size_t buffer_pos;
79 	int state;
80 	int line;
81 	int column;
82 	int last_column;
83 	size_t position;
84 }
85 
86 struct lex_t
87 {
88 	.stream_t stream;
89 	jansson_d.strbuffer.strbuffer_t saved_text;
90 	size_t flags;
91 	size_t depth;
92 	int token;
93 
94 	union value_
95 	{
96 		struct string__
97 		{
98 			char* val;
99 			size_t len;
100 		}
101 
102 		string__ string_;
103 		jansson_d.jansson.json_int_t integer;
104 		double real_;
105 	}
106 
107 	value_ value;
108 }
109 
110 private template stream_to_lex(string stream)
111 {
112 	enum stream_to_lex = "(mixin (jansson_d.jansson_private.container_of!(\"" ~ stream ~ "\", \"jansson_d.load.lex_t\", \"stream\")))";
113 }
114 
115 /* error reporting */
116 nothrow @trusted @nogc @live
117 private void error_set(F ...)(scope jansson_d.jansson.json_error_t* error, scope const .lex_t* lex, jansson_d.jansson.json_error_code_t code, scope const char* msg, F f)
118 
119 	do
120 	{
121 		char[jansson_d.jansson.JSON_ERROR_TEXT_LENGTH] msg_text = void;
122 		char[jansson_d.jansson.JSON_ERROR_TEXT_LENGTH] msg_with_context = void;
123 
124 		int line = -1;
125 		int col = -1;
126 		size_t pos = 0;
127 		const (char)* result = &(msg_text[0]);
128 
129 		if (error == null) {
130 			return;
131 		}
132 
133 		static if (f.length != 0) {
134 			jansson_d.jansson_private.snprintf(&(msg_text[0]), msg_text.length, msg, f[0 .. $]);
135 		} else {
136 			jansson_d.jansson_private.snprintf(&(msg_text[0]), msg_text.length, msg);
137 		}
138 
139 		msg_text[msg_text.length - 1] = '\0';
140 
141 		if (lex != null) {
142 			const char* saved_text = jansson_d.strbuffer.strbuffer_value(&lex.saved_text);
143 
144 			line = lex.stream.line;
145 			col = lex.stream.column;
146 			pos = lex.stream.position;
147 
148 			if ((saved_text != null) && (saved_text[0])) {
149 				if (lex.saved_text.length_ <= 20) {
150 					jansson_d.jansson_private.snprintf(&(msg_with_context[0]), msg_with_context.length, "%s near '%s'", &(msg_text[0]), saved_text);
151 					msg_with_context[msg_with_context.length - 1] = '\0';
152 					result = &(msg_with_context[0]);
153 				}
154 			} else {
155 				if (code == jansson_d.jansson.json_error_code_t.json_error_invalid_syntax) {
156 					/* More specific error code for premature end of file. */
157 					code = jansson_d.jansson.json_error_code_t.json_error_premature_end_of_input;
158 				}
159 
160 				if (lex.stream.state == .STREAM_STATE_ERROR) {
161 					/* No context for UTF-8 decoding errors */
162 					result = &(msg_text[0]);
163 				} else {
164 					jansson_d.jansson_private.snprintf(&(msg_with_context[0]), msg_with_context.length, "%s near end of file", &(msg_text[0]));
165 					msg_with_context[msg_with_context.length - 1] = '\0';
166 					result = &(msg_with_context[0]);
167 				}
168 			}
169 		}
170 
171 		jansson_d.jansson_private.jsonp_error_set(error, line, col, pos, code, "%s", result);
172 	}
173 
174 /* lexical analyzer */
175 
176 pure nothrow @trusted @nogc @live
177 private void stream_init(scope .stream_t* stream, .get_func get, scope void* data)
178 
179 	in
180 	{
181 		assert(stream != null);
182 	}
183 
184 	do
185 	{
186 		stream.get = get;
187 		stream.data = data;
188 		stream.buffer[0] = '\0';
189 		stream.buffer_pos = 0;
190 
191 		stream.state = .STREAM_STATE_OK;
192 		stream.line = 1;
193 		stream.column = 0;
194 		stream.position = 0;
195 	}
196 
197 nothrow @nogc @live
198 private int stream_get(scope .stream_t* stream, scope jansson_d.jansson.json_error_t* error)
199 
200 	in
201 	{
202 		assert(stream != null);
203 	}
204 
205 	do
206 	{
207 		if (stream.state != .STREAM_STATE_OK) {
208 			return stream.state;
209 		}
210 
211 		int c = void;
212 
213 		if (!stream.buffer[stream.buffer_pos]) {
214 			assert(stream.get != null);
215 			c = stream.get(stream.data);
216 
217 			if (c == core.stdc.stdio.EOF) {
218 				stream.state = .STREAM_STATE_EOF;
219 
220 				return .STREAM_STATE_EOF;
221 			}
222 
223 			stream.buffer[0] = cast(char)(c);
224 			stream.buffer_pos = 0;
225 
226 			if ((0x80 <= c) && (c <= 0xFF)) {
227 				/* multi-byte UTF-8 sequence */
228 
229 				size_t count = jansson_d.utf.utf8_check_first(cast(char)(c));
230 
231 				if (count == 0) {
232 					goto out_;
233 				}
234 
235 				assert(count >= 2);
236 
237 				for (size_t i = 1; i < count; i++) {
238 					stream.buffer[i] = cast(char)(stream.get(stream.data));
239 				}
240 
241 				if (!jansson_d.utf.utf8_check_full(&(stream.buffer[0]), count, null)) {
242 					goto out_;
243 				}
244 
245 				stream.buffer[count] = '\0';
246 			} else {
247 				stream.buffer[1] = '\0';
248 			}
249 		}
250 
251 		c = stream.buffer[stream.buffer_pos++];
252 
253 		stream.position++;
254 
255 		if (c == '\n') {
256 			stream.line++;
257 			stream.last_column = stream.column;
258 			stream.column = 0;
259 		} else if (jansson_d.utf.utf8_check_first(cast(char)(c))) {
260 			/*
261 			 * track the Unicode character column, so increment only if
262 			 * this is the first character of a UTF-8 sequence
263 			 */
264 			stream.column++;
265 		}
266 
267 		return c;
268 
269 	out_:
270 		stream.state = .STREAM_STATE_ERROR;
271 		.error_set(error, mixin (.stream_to_lex!("stream")), jansson_d.jansson.json_error_code_t.json_error_invalid_utf8, "unable to decode byte 0x%x", c);
272 
273 		return .STREAM_STATE_ERROR;
274 	}
275 
276 pure nothrow @trusted @nogc @live
277 private void stream_unget(scope .stream_t* stream, int c)
278 
279 	in
280 	{
281 		assert(stream != null);
282 	}
283 
284 	do
285 	{
286 		if ((c == .STREAM_STATE_EOF) || (c == .STREAM_STATE_ERROR)) {
287 			return;
288 		}
289 
290 		stream.position--;
291 
292 		if (c == '\n') {
293 			stream.line--;
294 			stream.column = stream.last_column;
295 		} else if (jansson_d.utf.utf8_check_first(cast(char)(c))) {
296 			stream.column--;
297 		}
298 
299 		assert(stream.buffer_pos > 0);
300 		stream.buffer_pos--;
301 		assert(stream.buffer[stream.buffer_pos] == c);
302 	}
303 
304 nothrow @nogc @live
305 private int lex_get(scope .lex_t* lex, scope jansson_d.jansson.json_error_t* error)
306 
307 	in
308 	{
309 		assert(lex != null);
310 	}
311 
312 	do
313 	{
314 		return .stream_get(&lex.stream, error);
315 	}
316 
317 nothrow @trusted @nogc
318 private void lex_save(scope .lex_t* lex, int c)
319 
320 	in
321 	{
322 		assert(lex != null);
323 	}
324 
325 	do
326 	{
327 		jansson_d.strbuffer.strbuffer_append_byte(&lex.saved_text, cast(char)(c));
328 	}
329 
330 nothrow @nogc @live
331 private int lex_get_save(scope .lex_t* lex, scope jansson_d.jansson.json_error_t* error)
332 
333 	in
334 	{
335 		assert(lex != null);
336 	}
337 
338 	do
339 	{
340 		int c = .stream_get(&lex.stream, error);
341 
342 		if ((c != .STREAM_STATE_EOF) && (c != .STREAM_STATE_ERROR)) {
343 			.lex_save(lex, c);
344 		}
345 
346 		return c;
347 	}
348 
349 pure nothrow @trusted @nogc @live
350 private void lex_unget(scope .lex_t* lex, int c)
351 
352 	in
353 	{
354 		assert(lex != null);
355 	}
356 
357 	do
358 	{
359 		.stream_unget(&lex.stream, c);
360 	}
361 
362 pure nothrow @trusted @nogc @live
363 private void lex_unget_unsave(scope .lex_t* lex, int c)
364 
365 	in
366 	{
367 		assert(lex != null);
368 	}
369 
370 	do
371 	{
372 		if ((c != .STREAM_STATE_EOF) && (c != .STREAM_STATE_ERROR)) {
373 			/*
374 			 * Since we treat warnings as errors, when assertions are turned
375 			 * off the "d" variable would be set but never used. Which is
376 			 * treated as an error by GCC.
377 			 */
378 			//#if !defined(NDEBUG)
379 				//char d;
380 			//#endif
381 
382 			.stream_unget(&lex.stream, c);
383 
384 			version (NDEBUG) {
385 				jansson_d.strbuffer.strbuffer_pop(&lex.saved_text);
386 			} else {
387 				char d = jansson_d.strbuffer.strbuffer_pop(&lex.saved_text);
388 			}
389 
390 			//assert(c == d);
391 		}
392 	}
393 
394 nothrow @trusted @nogc
395 private void lex_save_cached(scope .lex_t* lex)
396 
397 	in
398 	{
399 		assert(lex != null);
400 	}
401 
402 	do
403 	{
404 		while (lex.stream.buffer[lex.stream.buffer_pos] != '\0') {
405 			.lex_save(lex, lex.stream.buffer[lex.stream.buffer_pos]);
406 			lex.stream.buffer_pos++;
407 			lex.stream.position++;
408 		}
409 	}
410 
411 nothrow @trusted @nogc
412 private void lex_free_string(scope .lex_t* lex)
413 
414 	in
415 	{
416 		assert(lex != null);
417 	}
418 
419 	do
420 	{
421 		jansson_d.jansson_private.jsonp_free(lex.value.string_.val);
422 		lex.value.string_.val = null;
423 		lex.value.string_.len = 0;
424 	}
425 
426 /* assumes that str points to 'u' plus at least 4 valid hex digits */
427 pure nothrow @trusted @nogc @live
428 private int decode_unicode_escape(scope const char* str)
429 
430 	in
431 	{
432 		assert(str != null);
433 		assert(str[0] == 'u');
434 	}
435 
436 	do
437 	{
438 		int value = 0;
439 
440 		for (size_t i = 1; i <= 4; i++) {
441 			char c = str[i];
442 			value <<= 4;
443 
444 			if (mixin (.l_isdigit!("c"))) {
445 				value += c - '0';
446 			} else if (mixin (.l_islower!("c"))) {
447 				value += c - 'a' + 10;
448 			} else if (mixin (.l_isupper!("c"))) {
449 				value += c - 'A' + 10;
450 			} else {
451 				return -1;
452 			}
453 		}
454 
455 		return value;
456 	}
457 
458 nothrow @nogc @live
459 private void lex_scan_string(scope .lex_t* lex, scope jansson_d.jansson.json_error_t* error)
460 
461 	in
462 	{
463 		assert(lex != null);
464 	}
465 
466 	do
467 	{
468 		char* t = void;
469 		const (char)* p = void;
470 
471 		lex.value.string_.val = null;
472 		lex.token = .TOKEN_INVALID;
473 
474 		int c = .lex_get_save(lex, error);
475 
476 		while (c != '"') {
477 			if (c == .STREAM_STATE_ERROR) {
478 				goto out_;
479 			} else if (c == .STREAM_STATE_EOF) {
480 				.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_premature_end_of_input, "premature end of input");
481 
482 				goto out_;
483 			} else if ((0 <= c) && (c <= 0x1F)) {
484 				/* control character */
485 				.lex_unget_unsave(lex, c);
486 
487 				if (c == '\n') {
488 					.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "unexpected newline");
489 				} else {
490 					.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "control character 0x%x", c);
491 				}
492 
493 				goto out_;
494 			} else if (c == '\\') {
495 				c = .lex_get_save(lex, error);
496 
497 				if (c == 'u') {
498 					c = .lex_get_save(lex, error);
499 
500 					for (size_t i = 0; i < 4; i++) {
501 						if (!mixin (.l_isxdigit!("c"))) {
502 							.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid escape");
503 
504 							goto out_;
505 						}
506 
507 						c = .lex_get_save(lex, error);
508 					}
509 				} else if ((c == '"') || (c == '\\') || (c == '/') || (c == 'b') || (c == 'f') || (c == 'n') || (c == 'r') || (c == 't')) {
510 					c = .lex_get_save(lex, error);
511 				} else {
512 					.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid escape");
513 
514 					goto out_;
515 				}
516 			} else {
517 				c = .lex_get_save(lex, error);
518 			}
519 		}
520 
521 		/*
522 		 * the actual value is at most of the same length as the source
523 		 *    string_, because:
524 		 *      - shortcut escapes (e.g. "\t") (length 2) are converted to 1 byte
525 		 *      - a single \uXXXX escape (length 6) is converted to at most 3 bytes
526 		 *      - two \uXXXX escapes (length 12) forming an UTF-16 surrogate pair
527 		 *        are converted to 4 bytes
528 		 */
529 		t = cast(char*)(jansson_d.jansson_private.jsonp_malloc(lex.saved_text.length_ + 1));
530 
531 		if (t == null) {
532 			/* this is not very nice, since TOKEN_INVALID is returned */
533 			goto out_;
534 		}
535 
536 		lex.value.string_.val = t;
537 
538 		/* + 1 to skip the " */
539 		assert(jansson_d.strbuffer.strbuffer_value(&lex.saved_text) != null);
540 		p = jansson_d.strbuffer.strbuffer_value(&lex.saved_text) + 1;
541 
542 		while (*p != '"') {
543 			if (*p == '\\') {
544 				p++;
545 
546 				if (*p == 'u') {
547 					int value = .decode_unicode_escape(p);
548 
549 					if (value < 0) {
550 						.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid Unicode escape '%.6s'", p - 1);
551 
552 						goto out_;
553 					}
554 
555 					p += 5;
556 
557 					if ((0xD800 <= value) && (value <= 0xDBFF)) {
558 						/* surrogate pair */
559 						if ((*p == '\\') && (*(p + 1) == 'u')) {
560 							int value2 = .decode_unicode_escape(++p);
561 
562 							if (value2 < 0) {
563 								.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid Unicode escape '%.6s'", p - 1);
564 
565 								goto out_;
566 							}
567 
568 							p += 5;
569 
570 							if ((0xDC00 <= value2) && (value2 <= 0xDFFF)) {
571 								/* valid second surrogate */
572 								value = ((value - 0xD800) << 10) + (value2 - 0xDC00) + 0x010000;
573 							} else {
574 								/* invalid second surrogate */
575 								.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid Unicode '\\u%04X\\u%04X'", value, value2);
576 
577 								goto out_;
578 							}
579 						} else {
580 							/* no second surrogate */
581 							.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid Unicode '\\u%04X'", value);
582 
583 							goto out_;
584 						}
585 					} else if ((0xDC00 <= value) && (value <= 0xDFFF)) {
586 						.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid Unicode '\\u%04X'", value);
587 
588 						goto out_;
589 					}
590 
591 					size_t length_ = void;
592 
593 					if (jansson_d.utf.utf8_encode(value, t, &length_)) {
594 						assert(0);
595 					}
596 
597 					t += length_;
598 				} else {
599 					switch (*p) {
600 						case '"':
601 						case '\\':
602 						case '/':
603 							*t = *p;
604 
605 							break;
606 
607 						case 'b':
608 							*t = '\b';
609 
610 							break;
611 
612 						case 'f':
613 							*t = '\f';
614 
615 							break;
616 
617 						case 'n':
618 							*t = '\n';
619 
620 							break;
621 
622 						case 'r':
623 							*t = '\r';
624 
625 							break;
626 
627 						case 't':
628 							*t = '\t';
629 
630 							break;
631 
632 						default:
633 							assert(0);
634 					}
635 
636 					t++;
637 					p++;
638 				}
639 			} else {
640 				*(t++) = *(p++);
641 			}
642 		}
643 
644 		*t = '\0';
645 		lex.value.string_.len = t - lex.value.string_.val;
646 		lex.token = .TOKEN_STRING;
647 
648 		return;
649 
650 	out_:
651 		.lex_free_string(lex);
652 	}
653 
654 /* disabled if using cmake */
655 version (JANSSON_USING_CMAKE) {
656 } else {
657 	static if (jansson_d.jansson_config.JSON_INTEGER_IS_LONG_LONG) {
658 		static if (__traits(compiles, core.stdc.stdlib._strtoi64)) {
659 			private alias json_strtoint = core.stdc.stdlib._strtoi64;
660 		} else {
661 			private alias json_strtoint = core.stdc.stdlib.strtoll;
662 		}
663 	} else {
664 		private alias json_strtoint = core.stdc.stdlib.strtol;
665 	}
666 }
667 
668 nothrow @nogc @live
669 private int lex_scan_number(scope .lex_t* lex, int c, scope jansson_d.jansson.json_error_t* error)
670 
671 	in
672 	{
673 		assert(lex != null);
674 	}
675 
676 	do
677 	{
678 		lex.token = .TOKEN_INVALID;
679 
680 		if (c == '-') {
681 			c = .lex_get_save(lex, error);
682 		}
683 
684 		if (c == '0') {
685 			c = .lex_get_save(lex, error);
686 
687 			if (mixin (.l_isdigit!("c"))) {
688 				.lex_unget_unsave(lex, c);
689 
690 				return -1;
691 			}
692 		} else if (mixin (.l_isdigit!("c"))) {
693 			do {
694 				c = .lex_get_save(lex, error);
695 			} while (mixin (.l_isdigit!("c")));
696 		} else {
697 			.lex_unget_unsave(lex, c);
698 
699 			return -1;
700 		}
701 
702 		if ((!(lex.flags & jansson_d.jansson.JSON_DECODE_INT_AS_REAL)) && (c != '.') && (c != 'E') && (c != 'e')) {
703 			.lex_unget_unsave(lex, c);
704 
705 			const char* saved_text = jansson_d.strbuffer.strbuffer_value(&lex.saved_text);
706 
707 			core.stdc.errno.errno = 0;
708 			const (char)* end = null;
709 			jansson_d.jansson.json_int_t intval = .json_strtoint(saved_text, &end, 10);
710 
711 			if (core.stdc.errno.errno == core.stdc.errno.ERANGE) {
712 				if (intval < 0) {
713 					.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_numeric_overflow, "too big negative integer");
714 				} else {
715 					.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_numeric_overflow, "too big integer");
716 				}
717 
718 				return -1;
719 			}
720 
721 			assert(end == (saved_text + lex.saved_text.length_));
722 
723 			lex.token = .TOKEN_INTEGER;
724 			lex.value.integer = intval;
725 
726 			return 0;
727 		}
728 
729 		if (c == '.') {
730 			c = .lex_get(lex, error);
731 
732 			if (!mixin (.l_isdigit!("c"))) {
733 				.lex_unget(lex, c);
734 
735 				return -1;
736 			}
737 
738 			.lex_save(lex, c);
739 
740 			do {
741 				c = .lex_get_save(lex, error);
742 			} while (mixin (.l_isdigit!("c")));
743 		}
744 
745 		if ((c == 'E') || (c == 'e')) {
746 			c = .lex_get_save(lex, error);
747 
748 			if ((c == '+') || (c == '-')) {
749 				c = .lex_get_save(lex, error);
750 			}
751 
752 			if (!mixin (.l_isdigit!("c"))) {
753 				.lex_unget_unsave(lex, c);
754 
755 				return -1;
756 			}
757 
758 			do {
759 				c = .lex_get_save(lex, error);
760 			} while (mixin (.l_isdigit!("c")));
761 		}
762 
763 		.lex_unget_unsave(lex, c);
764 
765 		double doubleval = void;
766 
767 		if (!jansson_d.jansson_private.jsonp_strtod(&lex.saved_text, &doubleval)) {
768 			.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_numeric_overflow, "real number overflow");
769 
770 			return -1;
771 		}
772 
773 		lex.token = .TOKEN_REAL;
774 		lex.value.real_ = doubleval;
775 
776 		return 0;
777 	}
778 
779 nothrow @trusted @nogc
780 private int lex_scan(scope .lex_t* lex, scope jansson_d.jansson.json_error_t* error)
781 
782 	in
783 	{
784 		assert(lex != null);
785 	}
786 
787 	do
788 	{
789 		jansson_d.strbuffer.strbuffer_clear(&lex.saved_text);
790 
791 		if (lex.token == .TOKEN_STRING) {
792 			.lex_free_string(lex);
793 		}
794 
795 		int c = void;
796 
797 		do {
798 			c = .lex_get(lex, error);
799 		} while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'));
800 
801 		if (c == .STREAM_STATE_EOF) {
802 			lex.token = .TOKEN_EOF;
803 
804 			goto out_;
805 		}
806 
807 		if (c == .STREAM_STATE_ERROR) {
808 			lex.token = .TOKEN_INVALID;
809 
810 			goto out_;
811 		}
812 
813 		.lex_save(lex, c);
814 
815 		if ((c == '{') || (c == '}') || (c == '[') || (c == ']') || (c == ':') || (c == ',')) {
816 			lex.token = c;
817 		} else if (c == '"') {
818 			.lex_scan_string(lex, error);
819 		} else if ((mixin (.l_isdigit!("c"))) || (c == '-')) {
820 			if (.lex_scan_number(lex, c, error)) {
821 				goto out_;
822 			}
823 		} else if (mixin (.l_isalpha!("c"))) {
824 			/* eat up the whole identifier for clearer error messages */
825 
826 			do {
827 				c = .lex_get_save(lex, error);
828 			} while (mixin (.l_isalpha!("c")));
829 
830 			.lex_unget_unsave(lex, c);
831 
832 			const char* saved_text = jansson_d.strbuffer.strbuffer_value(&lex.saved_text);
833 
834 			if (core.stdc..string.strcmp(saved_text, "true") == 0) {
835 				lex.token = .TOKEN_TRUE;
836 			} else if (core.stdc..string.strcmp(saved_text, "false") == 0) {
837 				lex.token = .TOKEN_FALSE;
838 			} else if (core.stdc..string.strcmp(saved_text, "null") == 0) {
839 				lex.token = .TOKEN_NULL;
840 			} else {
841 				lex.token = .TOKEN_INVALID;
842 			}
843 		} else {
844 			/*
845 			 * save the rest of the input UTF-8 sequence to get an error
846 			 * message of valid UTF-8
847 			 */
848 			.lex_save_cached(lex);
849 			lex.token = .TOKEN_INVALID;
850 		}
851 
852 	out_:
853 		return lex.token;
854 	}
855 
856 pure nothrow @trusted @nogc @live
857 private char* lex_steal_string(scope .lex_t* lex, scope size_t* out_len)
858 
859 	in
860 	{
861 		assert(lex != null);
862 		assert(out_len != null);
863 	}
864 
865 	do
866 	{
867 		char* result = null;
868 
869 		if (lex.token == .TOKEN_STRING) {
870 			result = lex.value.string_.val;
871 			*out_len = lex.value.string_.len;
872 			lex.value.string_.val = null;
873 			lex.value.string_.len = 0;
874 		}
875 
876 		return result;
877 	}
878 
879 nothrow @trusted @nogc
880 private int lex_init(scope .lex_t* lex, .get_func get, size_t flags, scope void* data)
881 
882 	in
883 	{
884 		assert(lex != null);
885 	}
886 
887 	do
888 	{
889 		.stream_init(&lex.stream, get, data);
890 
891 		if (jansson_d.strbuffer.strbuffer_init(&lex.saved_text)) {
892 			return -1;
893 		}
894 
895 		lex.flags = flags;
896 		lex.token = .TOKEN_INVALID;
897 
898 		return 0;
899 	}
900 
901 nothrow @trusted @nogc
902 private void lex_close(scope .lex_t* lex)
903 
904 	in
905 	{
906 		assert(lex != null);
907 	}
908 
909 	do
910 	{
911 		if (lex.token == .TOKEN_STRING) {
912 			.lex_free_string(lex);
913 		}
914 
915 		jansson_d.strbuffer.strbuffer_close(&lex.saved_text);
916 	}
917 
918 /* parser */
919 
920 nothrow @trusted @nogc
921 private jansson_d.jansson.json_t* parse_object(scope lex_t* lex, size_t flags, scope jansson_d.jansson.json_error_t* error)
922 
923 	in
924 	{
925 		assert(lex != null);
926 	}
927 
928 	do
929 	{
930 		jansson_d.jansson.json_t* object = jansson_d.value.json_object();
931 
932 		if (object == null) {
933 			return null;
934 		}
935 
936 		.lex_scan(lex, error);
937 
938 		if (lex.token == '}') {
939 			return object;
940 		}
941 
942 		while (true) {
943 			if (lex.token != .TOKEN_STRING) {
944 				.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "string or '}' expected");
945 
946 				goto error_;
947 			}
948 
949 			size_t len = void;
950 			char* key = .lex_steal_string(lex, &len);
951 
952 			if (key == null) {
953 				return null;
954 			}
955 
956 			if (core.stdc..string.memchr(key, '\0', len)) {
957 				jansson_d.jansson_private.jsonp_free(key);
958 				.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_null_byte_in_key, "NUL byte in object key not supported");
959 
960 				goto error_;
961 			}
962 
963 			if (flags & jansson_d.jansson.JSON_REJECT_DUPLICATES) {
964 				if (jansson_d.value.json_object_getn(object, key, len)) {
965 					jansson_d.jansson_private.jsonp_free(key);
966 					.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_duplicate_key, "duplicate object key");
967 
968 					goto error_;
969 				}
970 			}
971 
972 			.lex_scan(lex, error);
973 
974 			if (lex.token != ':') {
975 				jansson_d.jansson_private.jsonp_free(key);
976 				.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "':' expected");
977 
978 				goto error_;
979 			}
980 
981 			.lex_scan(lex, error);
982 			jansson_d.jansson.json_t* value = .parse_value(lex, flags, error);
983 
984 			if (value == null) {
985 				jansson_d.jansson_private.jsonp_free(key);
986 
987 				goto error_;
988 			}
989 
990 			if (jansson_d.value.json_object_setn_new_nocheck(object, key, len, value)) {
991 				jansson_d.jansson_private.jsonp_free(key);
992 
993 				goto error_;
994 			}
995 
996 			jansson_d.jansson_private.jsonp_free(key);
997 
998 			.lex_scan(lex, error);
999 
1000 			if (lex.token != ',') {
1001 				break;
1002 			}
1003 
1004 			.lex_scan(lex, error);
1005 		}
1006 
1007 		if (lex.token != '}') {
1008 			.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "'}' expected");
1009 
1010 			goto error_;
1011 		}
1012 
1013 		return object;
1014 
1015 	error_:
1016 		jansson_d.jansson.json_decref(object);
1017 
1018 		return null;
1019 	}
1020 
1021 nothrow @trusted @nogc
1022 private jansson_d.jansson.json_t* parse_array(scope .lex_t* lex, size_t flags, scope jansson_d.jansson.json_error_t* error)
1023 
1024 	in
1025 	{
1026 		assert(lex != null);
1027 	}
1028 
1029 	do
1030 	{
1031 		jansson_d.jansson.json_t* array = jansson_d.value.json_array();
1032 
1033 		if (array == null) {
1034 			return null;
1035 		}
1036 
1037 		.lex_scan(lex, error);
1038 
1039 		if (lex.token == ']') {
1040 			return array;
1041 		}
1042 
1043 		while (lex.token) {
1044 			jansson_d.jansson.json_t* elem = .parse_value(lex, flags, error);
1045 
1046 			if (elem == null) {
1047 				goto error_;
1048 			}
1049 
1050 			if (jansson_d.value.json_array_append_new(array, elem)) {
1051 				goto error_;
1052 			}
1053 
1054 			.lex_scan(lex, error);
1055 
1056 			if (lex.token != ',') {
1057 				break;
1058 			}
1059 
1060 			.lex_scan(lex, error);
1061 		}
1062 
1063 		if (lex.token != ']') {
1064 			.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "']' expected");
1065 
1066 			goto error_;
1067 		}
1068 
1069 		return array;
1070 
1071 	error_:
1072 		jansson_d.jansson.json_decref(array);
1073 
1074 		return null;
1075 	}
1076 
1077 nothrow @trusted @nogc
1078 private jansson_d.jansson.json_t* parse_value(scope .lex_t* lex, size_t flags, scope jansson_d.jansson.json_error_t* error)
1079 
1080 	in
1081 	{
1082 		assert(lex != null);
1083 	}
1084 
1085 	do
1086 	{
1087 		lex.depth++;
1088 
1089 		if (lex.depth > jansson_d.jansson_config.JSON_PARSER_MAX_DEPTH) {
1090 			.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_stack_overflow, "maximum parsing depth reached");
1091 
1092 			return null;
1093 		}
1094 
1095 		jansson_d.jansson.json_t* json = null;
1096 
1097 		switch (lex.token) {
1098 			case .TOKEN_STRING:
1099 				const char* value = lex.value.string_.val;
1100 				size_t len = lex.value.string_.len;
1101 
1102 				if (!(flags & jansson_d.jansson.JSON_ALLOW_NUL)) {
1103 					if (core.stdc..string.memchr(value, '\0', len)) {
1104 						.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_null_character, "\\u0000 is not allowed without JSON_ALLOW_NUL");
1105 
1106 						return null;
1107 					}
1108 				}
1109 
1110 				json = jansson_d.jansson_private.jsonp_stringn_nocheck_own(value, len);
1111 				lex.value.string_.val = null;
1112 				lex.value.string_.len = 0;
1113 
1114 				break;
1115 
1116 			case .TOKEN_INTEGER:
1117 				json = jansson_d.value.json_integer(lex.value.integer);
1118 
1119 				break;
1120 
1121 			case .TOKEN_REAL:
1122 				json = jansson_d.value.json_real(lex.value.real_);
1123 
1124 				break;
1125 
1126 			case .TOKEN_TRUE:
1127 				json = jansson_d.value.json_true();
1128 
1129 				break;
1130 
1131 			case .TOKEN_FALSE:
1132 				json = jansson_d.value.json_false();
1133 
1134 				break;
1135 
1136 			case .TOKEN_NULL:
1137 				json = jansson_d.value.json_null();
1138 
1139 				break;
1140 
1141 			case '{':
1142 				json = .parse_object(lex, flags, error);
1143 
1144 				break;
1145 
1146 			case '[':
1147 				json = .parse_array(lex, flags, error);
1148 
1149 				break;
1150 
1151 			case .TOKEN_INVALID:
1152 				.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid token");
1153 
1154 				return null;
1155 
1156 			default:
1157 				.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "unexpected token");
1158 
1159 				return null;
1160 		}
1161 
1162 		if (json == null) {
1163 			return null;
1164 		}
1165 
1166 		lex.depth--;
1167 
1168 		return json;
1169 	}
1170 
1171 nothrow @trusted @nogc
1172 private jansson_d.jansson.json_t* parse_json(scope .lex_t* lex, size_t flags, scope jansson_d.jansson.json_error_t* error)
1173 
1174 	in
1175 	{
1176 		assert(lex != null);
1177 	}
1178 
1179 	do
1180 	{
1181 		lex.depth = 0;
1182 
1183 		.lex_scan(lex, error);
1184 
1185 		if (!(flags & jansson_d.jansson.JSON_DECODE_ANY)) {
1186 			if ((lex.token != '[') && (lex.token != '{')) {
1187 				.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "'[' or '{' expected");
1188 
1189 				return null;
1190 			}
1191 		}
1192 
1193 		jansson_d.jansson.json_t* result = .parse_value(lex, flags, error);
1194 
1195 		if (result == null) {
1196 			return null;
1197 		}
1198 
1199 		if (!(flags & jansson_d.jansson.JSON_DISABLE_EOF_CHECK)) {
1200 			.lex_scan(lex, error);
1201 
1202 			if (lex.token != .TOKEN_EOF) {
1203 				.error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_end_of_input_expected, "end of file expected");
1204 				jansson_d.jansson.json_decref(result);
1205 
1206 				return null;
1207 			}
1208 		}
1209 
1210 		if (error != null) {
1211 			/* Save the position even though there was no error */
1212 			error.position = cast(int)(lex.stream.position);
1213 		}
1214 
1215 		return result;
1216 	}
1217 
1218 struct string_data_t
1219 {
1220 	const (char)* data;
1221 	size_t pos;
1222 }
1223 
1224 extern (C)
1225 pure nothrow @trusted @nogc @live
1226 private int string_get(scope void* data)
1227 
1228 	in
1229 	{
1230 		assert(data != null);
1231 	}
1232 
1233 	do
1234 	{
1235 		.string_data_t* stream = cast(.string_data_t*)(data);
1236 		char c = stream.data[stream.pos];
1237 
1238 		if (c == '\0') {
1239 			return core.stdc.stdio.EOF;
1240 		} else {
1241 			stream.pos++;
1242 
1243 			return cast(ubyte)(c);
1244 		}
1245 	}
1246 
1247 ///
1248 extern (C)
1249 nothrow @trusted @nogc //ToDo: @nodiscard
1250 public jansson_d.jansson.json_t* json_loads(scope const char* string_, size_t flags, scope jansson_d.jansson.json_error_t* error)
1251 
1252 	do
1253 	{
1254 		jansson_d.jansson_private.jsonp_error_init(error, "<string>");
1255 
1256 		if (string_ == null) {
1257 			.error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_invalid_argument, "wrong arguments");
1258 
1259 			return null;
1260 		}
1261 
1262 		.string_data_t stream_data =
1263 		{
1264 			data: string_,
1265 			pos: 0,
1266 		};
1267 
1268 		.lex_t lex = void;
1269 
1270 		if (.lex_init(&lex, &.string_get, flags, cast(void*)(&stream_data))) {
1271 			return null;
1272 		}
1273 
1274 		jansson_d.jansson.json_t* result = .parse_json(&lex, flags, error);
1275 
1276 		.lex_close(&lex);
1277 
1278 		return result;
1279 	}
1280 
1281 struct buffer_data_t
1282 {
1283 	const (char)* data;
1284 	size_t len;
1285 	size_t pos;
1286 }
1287 
1288 extern (C)
1289 pure nothrow @trusted @nogc @live
1290 private int buffer_get(scope void* data)
1291 
1292 	in
1293 	{
1294 		assert(data != null);
1295 	}
1296 
1297 	do
1298 	{
1299 		.buffer_data_t* stream = cast(.buffer_data_t*)(data);
1300 
1301 		if (stream.pos >= stream.len) {
1302 			return core.stdc.stdio.EOF;
1303 		}
1304 
1305 		char c = stream.data[stream.pos];
1306 		stream.pos++;
1307 
1308 		return cast(ubyte)(c);
1309 	}
1310 
1311 ///
1312 extern (C)
1313 nothrow @trusted @nogc //ToDo: @nodiscard
1314 public jansson_d.jansson.json_t* json_loadb(scope const char* buffer, size_t buflen, size_t flags, scope jansson_d.jansson.json_error_t* error)
1315 
1316 	do
1317 	{
1318 		jansson_d.jansson_private.jsonp_error_init(error, "<buffer>");
1319 
1320 		if (buffer == null) {
1321 			.error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_invalid_argument, "wrong arguments");
1322 
1323 			return null;
1324 		}
1325 
1326 		.buffer_data_t stream_data =
1327 		{
1328 			data: buffer,
1329 			pos: 0,
1330 			len: buflen,
1331 		};
1332 
1333 		.lex_t lex = void;
1334 
1335 		if (.lex_init(&lex, &.buffer_get, flags, cast(void*)(&stream_data))) {
1336 			return null;
1337 		}
1338 
1339 		jansson_d.jansson.json_t* result = .parse_json(&lex, flags, error);
1340 
1341 		.lex_close(&lex);
1342 
1343 		return result;
1344 	}
1345 
1346 ///
1347 extern (C)
1348 nothrow @trusted @nogc //ToDo: @nodiscard
1349 public jansson_d.jansson.json_t* json_loadf(core.stdc.stdio.FILE* input, size_t flags, scope jansson_d.jansson.json_error_t* error)
1350 
1351 	do
1352 	{
1353 		const (char)* source = void;
1354 
1355 		if (input == core.stdc.stdio.stdin) {
1356 			source = "<stdin>";
1357 		} else {
1358 			source = "<stream>";
1359 		}
1360 
1361 		jansson_d.jansson_private.jsonp_error_init(error, source);
1362 
1363 		if (input == null) {
1364 			.error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_invalid_argument, "wrong arguments");
1365 
1366 			return null;
1367 		}
1368 
1369 		.lex_t lex = void;
1370 
1371 		if (.lex_init(&lex, cast(.get_func)(&core.stdc.stdio.fgetc), flags, cast(void*)(input))) {
1372 			return null;
1373 		}
1374 
1375 		jansson_d.jansson.json_t* result = .parse_json(&lex, flags, error);
1376 
1377 		.lex_close(&lex);
1378 
1379 		return result;
1380 	}
1381 
1382 extern (C)
1383 nothrow @nogc @live
1384 private int fd_get_func(scope int* fd)
1385 
1386 	in
1387 	{
1388 		assert(fd != null);
1389 	}
1390 
1391 	do
1392 	{
1393 		static if (__traits(compiles, core.sys.posix.unistd.read)) {
1394 			ubyte c = void;
1395 
1396 			if (core.sys.posix.unistd.read(*fd, &c, 1) == 1) {
1397 				return c;
1398 			}
1399 		}
1400 
1401 		return core.stdc.stdio.EOF;
1402 	}
1403 
1404 ///
1405 extern (C)
1406 nothrow @nogc @live //ToDo: @nodiscard
1407 public jansson_d.jansson.json_t* json_loadfd(int input, size_t flags, scope jansson_d.jansson.json_error_t* error)
1408 
1409 	do
1410 	{
1411 		const (char)* source = void;
1412 
1413 		static if (__traits(compiles, core.sys.posix.unistd.STDIN_FILENO)) {
1414 			if (input == core.sys.posix.unistd.STDIN_FILENO) {
1415 				source = "<stdin>";
1416 			} else {
1417 				source = "<stream>";
1418 			}
1419 		} else {
1420 			source = "<stream>";
1421 		}
1422 
1423 		jansson_d.jansson_private.jsonp_error_init(error, source);
1424 
1425 		if (input < 0) {
1426 			.error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_invalid_argument, "wrong arguments");
1427 
1428 			return null;
1429 		}
1430 
1431 		.lex_t lex = void;
1432 
1433 		if (.lex_init(&lex, cast(.get_func)(&.fd_get_func), flags, &input)) {
1434 			return null;
1435 		}
1436 
1437 		jansson_d.jansson.json_t* result = .parse_json(&lex, flags, error);
1438 
1439 		.lex_close(&lex);
1440 
1441 		return result;
1442 	}
1443 
1444 ///
1445 extern (C)
1446 nothrow @nogc //ToDo: @nodiscard
1447 public jansson_d.jansson.json_t* json_load_file(scope const char* path, size_t flags, scope jansson_d.jansson.json_error_t* error)
1448 
1449 	do
1450 	{
1451 		jansson_d.jansson_private.jsonp_error_init(error, path);
1452 
1453 		if (path == null) {
1454 			.error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_invalid_argument, "wrong arguments");
1455 
1456 			return null;
1457 		}
1458 
1459 		core.stdc.stdio.FILE* fp = core.stdc.stdio.fopen(path, "rb");
1460 
1461 		if (fp == null) {
1462 			.error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_cannot_open_file, "unable to open %s: %s", path, core.stdc..string.strerror(core.stdc.errno.errno));
1463 
1464 			return null;
1465 		}
1466 
1467 		jansson_d.jansson.json_t* result = .json_loadf(fp, flags, error);
1468 
1469 		core.stdc.stdio.fclose(fp);
1470 
1471 		return result;
1472 	}
1473 
1474 enum MAX_BUF_LEN = 1024;
1475 
1476 struct callback_data_t
1477 {
1478 	char[.MAX_BUF_LEN] data = '\0';
1479 	size_t len;
1480 	size_t pos;
1481 	jansson_d.jansson.json_load_callback_t callback;
1482 	void* arg;
1483 }
1484 
1485 extern (C)
1486 nothrow @nogc
1487 private int callback_get(scope void* data)
1488 
1489 	in
1490 	{
1491 		assert(data != null);
1492 		assert((cast(.callback_data_t*)(data)).callback != null);
1493 	}
1494 
1495 	do
1496 	{
1497 		.callback_data_t* stream = cast(.callback_data_t*)(data);
1498 
1499 		if (stream.pos >= stream.len) {
1500 			stream.pos = 0;
1501 			stream.len = stream.callback(&(stream.data[0]), stream.data.length, stream.arg);
1502 
1503 			if ((stream.len == 0) || (stream.len == size_t.max)) {
1504 				return core.stdc.stdio.EOF;
1505 			}
1506 		}
1507 
1508 		char c = stream.data[stream.pos];
1509 		stream.pos++;
1510 
1511 		return cast(ubyte)(c);
1512 	}
1513 
1514 ///
1515 extern (C)
1516 nothrow @nogc //ToDo: @nodiscard
1517 public jansson_d.jansson.json_t* json_load_callback(jansson_d.jansson.json_load_callback_t callback, scope void* arg, size_t flags, scope jansson_d.jansson.json_error_t* error)
1518 
1519 	do
1520 	{
1521 		.callback_data_t stream_data = void;
1522 		core.stdc..string.memset(&stream_data, 0, stream_data.sizeof);
1523 		stream_data.callback = callback;
1524 		stream_data.arg = arg;
1525 
1526 		jansson_d.jansson_private.jsonp_error_init(error, "<callback>");
1527 
1528 		if (callback == null) {
1529 			.error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_invalid_argument, "wrong arguments");
1530 
1531 			return null;
1532 		}
1533 
1534 		.lex_t lex = void;
1535 
1536 		if (.lex_init(&lex, cast(.get_func)(&.callback_get), flags, &stream_data)) {
1537 			return null;
1538 		}
1539 
1540 		jansson_d.jansson.json_t* result = .parse_json(&lex, flags, error);
1541 
1542 		.lex_close(&lex);
1543 
1544 		return result;
1545 	}