xref: /vim-8.2.3635/src/json.c (revision 71ccd03e)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * json.c: Encoding and decoding JSON.
12  *
13  * Follows this standard: https://tools.ietf.org/html/rfc7159.html
14  */
15 #define USING_FLOAT_STUFF
16 
17 #include "vim.h"
18 
19 #if defined(FEAT_EVAL) || defined(PROTO)
20 
21 static int json_encode_item(garray_T *gap, typval_T *val, int copyID, int options);
22 
23 static char e_json_error[] = N_("E491: json decode error at '%s'");
24 
25 /*
26  * Encode "val" into a JSON format string.
27  * The result is added to "gap"
28  * Returns FAIL on failure and makes gap->ga_data empty.
29  */
30     static int
31 json_encode_gap(garray_T *gap, typval_T *val, int options)
32 {
33     if (json_encode_item(gap, val, get_copyID(), options) == FAIL)
34     {
35 	ga_clear(gap);
36 	gap->ga_data = vim_strsave((char_u *)"");
37 	return FAIL;
38     }
39     return OK;
40 }
41 
42 /*
43  * Encode "val" into a JSON format string.
44  * The result is in allocated memory.
45  * The result is empty when encoding fails.
46  * "options" can contain JSON_JS, JSON_NO_NONE and JSON_NL.
47  */
48     char_u *
49 json_encode(typval_T *val, int options)
50 {
51     garray_T ga;
52 
53     // Store bytes in the growarray.
54     ga_init2(&ga, 1, 4000);
55     json_encode_gap(&ga, val, options);
56     ga_append(&ga, NUL);
57     return ga.ga_data;
58 }
59 
60 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
61 /*
62  * Encode ["nr", "val"] into a JSON format string in allocated memory.
63  * "options" can contain JSON_JS, JSON_NO_NONE and JSON_NL.
64  * Returns NULL when out of memory.
65  */
66     char_u *
67 json_encode_nr_expr(int nr, typval_T *val, int options)
68 {
69     typval_T	listtv;
70     typval_T	nrtv;
71     garray_T	ga;
72 
73     nrtv.v_type = VAR_NUMBER;
74     nrtv.vval.v_number = nr;
75     if (rettv_list_alloc(&listtv) == FAIL)
76 	return NULL;
77     if (list_append_tv(listtv.vval.v_list, &nrtv) == FAIL
78 	    || list_append_tv(listtv.vval.v_list, val) == FAIL)
79     {
80 	list_unref(listtv.vval.v_list);
81 	return NULL;
82     }
83 
84     ga_init2(&ga, 1, 4000);
85     if (json_encode_gap(&ga, &listtv, options) == OK && (options & JSON_NL))
86 	ga_append(&ga, '\n');
87     list_unref(listtv.vval.v_list);
88     ga_append(&ga, NUL);
89     return ga.ga_data;
90 }
91 #endif
92 
93     static void
94 write_string(garray_T *gap, char_u *str)
95 {
96     char_u	*res = str;
97     char_u	numbuf[NUMBUFLEN];
98 
99     if (res == NULL)
100 	ga_concat(gap, (char_u *)"\"\"");
101     else
102     {
103 #if defined(USE_ICONV)
104 	vimconv_T   conv;
105 	char_u	    *converted = NULL;
106 
107 	if (!enc_utf8)
108 	{
109 	    // Convert the text from 'encoding' to utf-8, the JSON string is
110 	    // always utf-8.
111 	    conv.vc_type = CONV_NONE;
112 	    convert_setup(&conv, p_enc, (char_u*)"utf-8");
113 	    if (conv.vc_type != CONV_NONE)
114 		converted = res = string_convert(&conv, res, NULL);
115 	    convert_setup(&conv, NULL, NULL);
116 	}
117 #endif
118 	ga_append(gap, '"');
119 	while (*res != NUL)
120 	{
121 	    int c;
122 	    // always use utf-8 encoding, ignore 'encoding'
123 	    c = utf_ptr2char(res);
124 
125 	    switch (c)
126 	    {
127 		case 0x08:
128 		    ga_append(gap, '\\'); ga_append(gap, 'b'); break;
129 		case 0x09:
130 		    ga_append(gap, '\\'); ga_append(gap, 't'); break;
131 		case 0x0a:
132 		    ga_append(gap, '\\'); ga_append(gap, 'n'); break;
133 		case 0x0c:
134 		    ga_append(gap, '\\'); ga_append(gap, 'f'); break;
135 		case 0x0d:
136 		    ga_append(gap, '\\'); ga_append(gap, 'r'); break;
137 		case 0x22: // "
138 		case 0x5c: // backslash
139 		    ga_append(gap, '\\');
140 		    ga_append(gap, c);
141 		    break;
142 		default:
143 		    if (c >= 0x20)
144 		    {
145 			numbuf[utf_char2bytes(c, numbuf)] = NUL;
146 			ga_concat(gap, numbuf);
147 		    }
148 		    else
149 		    {
150 			vim_snprintf((char *)numbuf, NUMBUFLEN,
151 							 "\\u%04lx", (long)c);
152 			ga_concat(gap, numbuf);
153 		    }
154 	    }
155 	    res += utf_ptr2len(res);
156 	}
157 	ga_append(gap, '"');
158 #if defined(USE_ICONV)
159 	vim_free(converted);
160 #endif
161     }
162 }
163 
164 /*
165  * Return TRUE if "key" can be used without quotes.
166  * That is when it starts with a letter and only contains letters, digits and
167  * underscore.
168  */
169     static int
170 is_simple_key(char_u *key)
171 {
172     char_u *p;
173 
174     if (!ASCII_ISALPHA(*key))
175 	return FALSE;
176     for (p = key + 1; *p != NUL; ++p)
177 	if (!ASCII_ISALPHA(*p) && *p != '_' && !vim_isdigit(*p))
178 	    return FALSE;
179     return TRUE;
180 }
181 
182 /*
183  * Encode "val" into "gap".
184  * Return FAIL or OK.
185  */
186     static int
187 json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
188 {
189     char_u	numbuf[NUMBUFLEN];
190     char_u	*res;
191     blob_T	*b;
192     list_T	*l;
193     dict_T	*d;
194     int		i;
195 
196     switch (val->v_type)
197     {
198 	case VAR_BOOL:
199 	    switch ((long)val->vval.v_number)
200 	    {
201 		case VVAL_FALSE: ga_concat(gap, (char_u *)"false"); break;
202 		case VVAL_TRUE: ga_concat(gap, (char_u *)"true"); break;
203 	    }
204 	    break;
205 
206 	case VAR_SPECIAL:
207 	    switch ((long)val->vval.v_number)
208 	    {
209 		case VVAL_NONE: if ((options & JSON_JS) != 0
210 					     && (options & JSON_NO_NONE) == 0)
211 				    // empty item
212 				    break;
213 				// FALLTHROUGH
214 		case VVAL_NULL: ga_concat(gap, (char_u *)"null"); break;
215 	    }
216 	    break;
217 
218 	case VAR_NUMBER:
219 	    vim_snprintf((char *)numbuf, NUMBUFLEN, "%lld",
220 					      (varnumber_T)val->vval.v_number);
221 	    ga_concat(gap, numbuf);
222 	    break;
223 
224 	case VAR_STRING:
225 	    res = val->vval.v_string;
226 	    write_string(gap, res);
227 	    break;
228 
229 	case VAR_FUNC:
230 	case VAR_PARTIAL:
231 	case VAR_JOB:
232 	case VAR_CHANNEL:
233 	    // no JSON equivalent TODO: better error
234 	    emsg(_(e_invarg));
235 	    return FAIL;
236 
237 	case VAR_BLOB:
238 	    b = val->vval.v_blob;
239 	    if (b == NULL || b->bv_ga.ga_len == 0)
240 		ga_concat(gap, (char_u *)"[]");
241 	    else
242 	    {
243 		ga_append(gap, '[');
244 		for (i = 0; i < b->bv_ga.ga_len; i++)
245 		{
246 		    if (i > 0)
247 			ga_concat(gap, (char_u *)",");
248 		    vim_snprintf((char *)numbuf, NUMBUFLEN, "%d",
249 			    (int)blob_get(b, i));
250 		    ga_concat(gap, numbuf);
251 		}
252 		ga_append(gap, ']');
253 	    }
254 	    break;
255 
256 	case VAR_LIST:
257 	    l = val->vval.v_list;
258 	    if (l == NULL)
259 		ga_concat(gap, (char_u *)"[]");
260 	    else
261 	    {
262 		if (l->lv_copyID == copyID)
263 		    ga_concat(gap, (char_u *)"[]");
264 		else
265 		{
266 		    listitem_T	*li;
267 
268 		    l->lv_copyID = copyID;
269 		    ga_append(gap, '[');
270 		    CHECK_LIST_MATERIALIZE(l);
271 		    for (li = l->lv_first; li != NULL && !got_int; )
272 		    {
273 			if (json_encode_item(gap, &li->li_tv, copyID,
274 						   options & JSON_JS) == FAIL)
275 			    return FAIL;
276 			if ((options & JSON_JS)
277 				&& li->li_next == NULL
278 				&& li->li_tv.v_type == VAR_SPECIAL
279 				&& li->li_tv.vval.v_number == VVAL_NONE)
280 			    // add an extra comma if the last item is v:none
281 			    ga_append(gap, ',');
282 			li = li->li_next;
283 			if (li != NULL)
284 			    ga_append(gap, ',');
285 		    }
286 		    ga_append(gap, ']');
287 		    l->lv_copyID = 0;
288 		}
289 	    }
290 	    break;
291 
292 	case VAR_DICT:
293 	    d = val->vval.v_dict;
294 	    if (d == NULL)
295 		ga_concat(gap, (char_u *)"{}");
296 	    else
297 	    {
298 		if (d->dv_copyID == copyID)
299 		    ga_concat(gap, (char_u *)"{}");
300 		else
301 		{
302 		    int		first = TRUE;
303 		    int		todo = (int)d->dv_hashtab.ht_used;
304 		    hashitem_T	*hi;
305 
306 		    d->dv_copyID = copyID;
307 		    ga_append(gap, '{');
308 
309 		    for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int;
310 									 ++hi)
311 			if (!HASHITEM_EMPTY(hi))
312 			{
313 			    --todo;
314 			    if (first)
315 				first = FALSE;
316 			    else
317 				ga_append(gap, ',');
318 			    if ((options & JSON_JS)
319 						 && is_simple_key(hi->hi_key))
320 				ga_concat(gap, hi->hi_key);
321 			    else
322 				write_string(gap, hi->hi_key);
323 			    ga_append(gap, ':');
324 			    if (json_encode_item(gap, &dict_lookup(hi)->di_tv,
325 				      copyID, options | JSON_NO_NONE) == FAIL)
326 				return FAIL;
327 			}
328 		    ga_append(gap, '}');
329 		    d->dv_copyID = 0;
330 		}
331 	    }
332 	    break;
333 
334 	case VAR_FLOAT:
335 #ifdef FEAT_FLOAT
336 # if defined(HAVE_MATH_H)
337 	    if (isnan(val->vval.v_float))
338 		ga_concat(gap, (char_u *)"NaN");
339 	    else if (isinf(val->vval.v_float))
340 	    {
341 		if (val->vval.v_float < 0.0)
342 		    ga_concat(gap, (char_u *)"-Infinity");
343 		else
344 		    ga_concat(gap, (char_u *)"Infinity");
345 	    }
346 	    else
347 # endif
348 	    {
349 		vim_snprintf((char *)numbuf, NUMBUFLEN, "%g",
350 							   val->vval.v_float);
351 		ga_concat(gap, numbuf);
352 	    }
353 	    break;
354 #endif
355 	case VAR_UNKNOWN:
356 	case VAR_ANY:
357 	case VAR_VOID:
358 	    internal_error_no_abort("json_encode_item()");
359 	    return FAIL;
360     }
361     return OK;
362 }
363 
364 /*
365  * When "reader" has less than NUMBUFLEN bytes available, call the fill
366  * callback to get more.
367  */
368     static void
369 fill_numbuflen(js_read_T *reader)
370 {
371     if (reader->js_fill != NULL && (int)(reader->js_end - reader->js_buf)
372 						- reader->js_used < NUMBUFLEN)
373     {
374 	if (reader->js_fill(reader))
375 	    reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
376     }
377 }
378 
379 /*
380  * Skip white space in "reader".  All characters <= space are considered white
381  * space.
382  * Also tops up readahead when needed.
383  */
384     static void
385 json_skip_white(js_read_T *reader)
386 {
387     int c;
388 
389     for (;;)
390     {
391 	c = reader->js_buf[reader->js_used];
392 	if (reader->js_fill != NULL && c == NUL)
393 	{
394 	    if (reader->js_fill(reader))
395 	    {
396 		reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
397 		continue;
398 	    }
399 	}
400 	if (c == NUL || c > ' ')
401 	    break;
402 	++reader->js_used;
403     }
404     fill_numbuflen(reader);
405 }
406 
407     static int
408 json_decode_string(js_read_T *reader, typval_T *res, int quote)
409 {
410     garray_T    ga;
411     int		len;
412     char_u	*p;
413     int		c;
414     varnumber_T	nr;
415 
416     if (res != NULL)
417 	ga_init2(&ga, 1, 200);
418 
419     p = reader->js_buf + reader->js_used + 1; // skip over " or '
420     while (*p != quote)
421     {
422 	// The JSON is always expected to be utf-8, thus use utf functions
423 	// here. The string is converted below if needed.
424 	if (*p == NUL || p[1] == NUL || utf_ptr2len(p) < utf_byte2len(*p))
425 	{
426 	    // Not enough bytes to make a character or end of the string. Get
427 	    // more if possible.
428 	    if (reader->js_fill == NULL)
429 		break;
430 	    len = (int)(reader->js_end - p);
431 	    reader->js_used = (int)(p - reader->js_buf);
432 	    if (!reader->js_fill(reader))
433 		break; // didn't get more
434 	    p = reader->js_buf + reader->js_used;
435 	    reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
436 	    continue;
437 	}
438 
439 	if (*p == '\\')
440 	{
441 	    c = -1;
442 	    switch (p[1])
443 	    {
444 		case '\\': c = '\\'; break;
445 		case '"': c = '"'; break;
446 		case 'b': c = BS; break;
447 		case 't': c = TAB; break;
448 		case 'n': c = NL; break;
449 		case 'f': c = FF; break;
450 		case 'r': c = CAR; break;
451 		case 'u':
452 		    if (reader->js_fill != NULL
453 				     && (int)(reader->js_end - p) < NUMBUFLEN)
454 		    {
455 			reader->js_used = (int)(p - reader->js_buf);
456 			if (reader->js_fill(reader))
457 			{
458 			    p = reader->js_buf + reader->js_used;
459 			    reader->js_end = reader->js_buf
460 						     + STRLEN(reader->js_buf);
461 			}
462 		    }
463 		    nr = 0;
464 		    len = 0;
465 		    vim_str2nr(p + 2, NULL, &len,
466 			     STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4, TRUE);
467 		    if (len == 0)
468 		    {
469 			if (res != NULL)
470 			    ga_clear(&ga);
471 			return FAIL;
472 		    }
473 		    p += len + 2;
474 		    if (0xd800 <= nr && nr <= 0xdfff
475 			    && (int)(reader->js_end - p) >= 6
476 			    && *p == '\\' && *(p+1) == 'u')
477 		    {
478 			varnumber_T	nr2 = 0;
479 
480 			// decode surrogate pair: \ud812\u3456
481 			len = 0;
482 			vim_str2nr(p + 2, NULL, &len,
483 			     STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4, TRUE);
484 			if (len == 0)
485 			{
486 			    if (res != NULL)
487 				ga_clear(&ga);
488 			    return FAIL;
489 			}
490 			if (0xdc00 <= nr2 && nr2 <= 0xdfff)
491 			{
492 			    p += len + 2;
493 			    nr = (((nr - 0xd800) << 10) |
494 				((nr2 - 0xdc00) & 0x3ff)) + 0x10000;
495 			}
496 		    }
497 		    if (res != NULL)
498 		    {
499 			char_u	buf[NUMBUFLEN];
500 
501 			buf[utf_char2bytes((int)nr, buf)] = NUL;
502 			ga_concat(&ga, buf);
503 		    }
504 		    break;
505 		default:
506 		    // not a special char, skip over backslash
507 		    ++p;
508 		    continue;
509 	    }
510 	    if (c > 0)
511 	    {
512 		p += 2;
513 		if (res != NULL)
514 		    ga_append(&ga, c);
515 	    }
516 	}
517 	else
518 	{
519 	    len = utf_ptr2len(p);
520 	    if (res != NULL)
521 	    {
522 		if (ga_grow(&ga, len) == FAIL)
523 		{
524 		    ga_clear(&ga);
525 		    return FAIL;
526 		}
527 		mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len);
528 		ga.ga_len += len;
529 	    }
530 	    p += len;
531 	}
532     }
533 
534     reader->js_used = (int)(p - reader->js_buf);
535     if (*p == quote)
536     {
537 	++reader->js_used;
538 	if (res != NULL)
539 	{
540 	    ga_append(&ga, NUL);
541 	    res->v_type = VAR_STRING;
542 #if defined(USE_ICONV)
543 	    if (!enc_utf8)
544 	    {
545 		vimconv_T   conv;
546 
547 		// Convert the utf-8 string to 'encoding'.
548 		conv.vc_type = CONV_NONE;
549 		convert_setup(&conv, (char_u*)"utf-8", p_enc);
550 		if (conv.vc_type != CONV_NONE)
551 		{
552 		    res->vval.v_string =
553 				      string_convert(&conv, ga.ga_data, NULL);
554 		    vim_free(ga.ga_data);
555 		}
556 		convert_setup(&conv, NULL, NULL);
557 	    }
558 	    else
559 #endif
560 		res->vval.v_string = ga.ga_data;
561 	}
562 	return OK;
563     }
564     if (res != NULL)
565     {
566 	res->v_type = VAR_SPECIAL;
567 	res->vval.v_number = VVAL_NONE;
568 	ga_clear(&ga);
569     }
570     return MAYBE;
571 }
572 
573 typedef enum {
574     JSON_ARRAY,		// parsing items in an array
575     JSON_OBJECT_KEY,	// parsing key of an object
576     JSON_OBJECT		// parsing item in an object, after the key
577 } json_decode_T;
578 
579 typedef struct {
580     json_decode_T jd_type;
581     typval_T	  jd_tv;	// the list or dict
582     typval_T	  jd_key_tv;
583     char_u	  *jd_key;
584 } json_dec_item_T;
585 
586 /*
587  * Decode one item and put it in "res".  If "res" is NULL only advance.
588  * Must already have skipped white space.
589  *
590  * Return FAIL for a decoding error (and give an error).
591  * Return MAYBE for an incomplete message.
592  */
593     static int
594 json_decode_item(js_read_T *reader, typval_T *res, int options)
595 {
596     char_u	*p;
597     int		len;
598     int		retval;
599     garray_T	stack;
600     typval_T	item;
601     typval_T	*cur_item;
602     json_dec_item_T *top_item;
603     char_u	key_buf[NUMBUFLEN];
604 
605     ga_init2(&stack, sizeof(json_dec_item_T), 100);
606     cur_item = res;
607     init_tv(&item);
608     if (res != NULL)
609     init_tv(res);
610 
611     fill_numbuflen(reader);
612     p = reader->js_buf + reader->js_used;
613     for (;;)
614     {
615 	top_item = NULL;
616 	if (stack.ga_len > 0)
617 	{
618 	    top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1;
619 	    json_skip_white(reader);
620 	    p = reader->js_buf + reader->js_used;
621 	    if (*p == NUL)
622 	    {
623 		retval = MAYBE;
624 		if (top_item->jd_type == JSON_OBJECT)
625 		    // did get the key, clear it
626 		    clear_tv(&top_item->jd_key_tv);
627 		goto theend;
628 	    }
629 	    if (top_item->jd_type == JSON_OBJECT_KEY
630 					    || top_item->jd_type == JSON_ARRAY)
631 	    {
632 		// Check for end of object or array.
633 		if (*p == (top_item->jd_type == JSON_ARRAY ? ']' : '}'))
634 		{
635 		    ++reader->js_used; // consume the ']' or '}'
636 		    --stack.ga_len;
637 		    if (stack.ga_len == 0)
638 		    {
639 			retval = OK;
640 			goto theend;
641 		    }
642 		    if (cur_item != NULL)
643 			cur_item = &top_item->jd_tv;
644 		    goto item_end;
645 		}
646 	    }
647 	}
648 
649 	if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY
650 		&& (options & JSON_JS)
651 		&& reader->js_buf[reader->js_used] != '"'
652 		&& reader->js_buf[reader->js_used] != '\''
653 		&& reader->js_buf[reader->js_used] != '['
654 		&& reader->js_buf[reader->js_used] != '{')
655 	{
656 	    char_u *key;
657 
658 	    // accept an object key that is not in quotes
659 	    key = p = reader->js_buf + reader->js_used;
660 	    while (*p != NUL && *p != ':' && *p > ' ')
661 		++p;
662 	    if (cur_item != NULL)
663 	    {
664 		cur_item->v_type = VAR_STRING;
665 		cur_item->vval.v_string = vim_strnsave(key, p - key);
666 		top_item->jd_key = cur_item->vval.v_string;
667 	    }
668 	    reader->js_used += (int)(p - key);
669 	}
670 	else
671 	{
672 	    switch (*p)
673 	    {
674 		case '[': // start of array
675 		    if (top_item && top_item->jd_type == JSON_OBJECT_KEY)
676 		    {
677 			retval = FAIL;
678 			break;
679 		    }
680 		    if (ga_grow(&stack, 1) == FAIL)
681 		    {
682 			retval = FAIL;
683 			break;
684 		    }
685 		    if (cur_item != NULL && rettv_list_alloc(cur_item) == FAIL)
686 		    {
687 			cur_item->v_type = VAR_SPECIAL;
688 			cur_item->vval.v_number = VVAL_NONE;
689 			retval = FAIL;
690 			break;
691 		    }
692 
693 		    ++reader->js_used; // consume the '['
694 		    top_item = ((json_dec_item_T *)stack.ga_data)
695 								+ stack.ga_len;
696 		    top_item->jd_type = JSON_ARRAY;
697 		    ++stack.ga_len;
698 		    if (cur_item != NULL)
699 		    {
700 			top_item->jd_tv = *cur_item;
701 			cur_item = &item;
702 		    }
703 		    continue;
704 
705 		case '{': // start of object
706 		    if (top_item && top_item->jd_type == JSON_OBJECT_KEY)
707 		    {
708 			retval = FAIL;
709 			break;
710 		    }
711 		    if (ga_grow(&stack, 1) == FAIL)
712 		    {
713 			retval = FAIL;
714 			break;
715 		    }
716 		    if (cur_item != NULL && rettv_dict_alloc(cur_item) == FAIL)
717 		    {
718 			cur_item->v_type = VAR_SPECIAL;
719 			cur_item->vval.v_number = VVAL_NONE;
720 			retval = FAIL;
721 			break;
722 		    }
723 
724 		    ++reader->js_used; // consume the '{'
725 		    top_item = ((json_dec_item_T *)stack.ga_data)
726 								+ stack.ga_len;
727 		    top_item->jd_type = JSON_OBJECT_KEY;
728 		    ++stack.ga_len;
729 		    if (cur_item != NULL)
730 		    {
731 			top_item->jd_tv = *cur_item;
732 			cur_item = &top_item->jd_key_tv;
733 		    }
734 		    continue;
735 
736 		case '"': // string
737 		    retval = json_decode_string(reader, cur_item, *p);
738 		    break;
739 
740 		case '\'':
741 		    if (options & JSON_JS)
742 			retval = json_decode_string(reader, cur_item, *p);
743 		    else
744 		    {
745 			semsg(_(e_json_error), p);
746 			retval = FAIL;
747 		    }
748 		    break;
749 
750 		case ',': // comma: empty item
751 		    if ((options & JSON_JS) == 0)
752 		    {
753 			semsg(_(e_json_error), p);
754 			retval = FAIL;
755 			break;
756 		    }
757 		    // FALLTHROUGH
758 		case NUL: // empty
759 		    if (cur_item != NULL)
760 		    {
761 			cur_item->v_type = VAR_SPECIAL;
762 			cur_item->vval.v_number = VVAL_NONE;
763 		    }
764 		    retval = OK;
765 		    break;
766 
767 		default:
768 		    if (VIM_ISDIGIT(*p) || (*p == '-'
769 					&& (VIM_ISDIGIT(p[1]) || p[1] == NUL)))
770 		    {
771 			char_u  *sp = p;
772 
773 			if (*sp == '-')
774 			{
775 			    ++sp;
776 			    if (*sp == NUL)
777 			    {
778 				retval = MAYBE;
779 				break;
780 			    }
781 			    if (!VIM_ISDIGIT(*sp))
782 			    {
783 				semsg(_(e_json_error), p);
784 				retval = FAIL;
785 				break;
786 			    }
787 			}
788 			sp = skipdigits(sp);
789 #ifdef FEAT_FLOAT
790 			if (*sp == '.' || *sp == 'e' || *sp == 'E')
791 			{
792 			    if (cur_item == NULL)
793 			    {
794 				float_T f;
795 
796 				len = string2float(p, &f);
797 			    }
798 			    else
799 			    {
800 				cur_item->v_type = VAR_FLOAT;
801 				len = string2float(p, &cur_item->vval.v_float);
802 			    }
803 			}
804 			else
805 #endif
806 			{
807 			    varnumber_T nr;
808 
809 			    vim_str2nr(reader->js_buf + reader->js_used,
810 				    NULL, &len, 0, // what
811 				    &nr, NULL, 0, TRUE);
812 			    if (len == 0)
813 			    {
814 				semsg(_(e_json_error), p);
815 				retval = FAIL;
816 				goto theend;
817 			    }
818 			    if (cur_item != NULL)
819 			    {
820 				cur_item->v_type = VAR_NUMBER;
821 				cur_item->vval.v_number = nr;
822 			    }
823 			}
824 			reader->js_used += len;
825 			retval = OK;
826 			break;
827 		    }
828 		    if (STRNICMP((char *)p, "false", 5) == 0)
829 		    {
830 			reader->js_used += 5;
831 			if (cur_item != NULL)
832 			{
833 			    cur_item->v_type = VAR_BOOL;
834 			    cur_item->vval.v_number = VVAL_FALSE;
835 			}
836 			retval = OK;
837 			break;
838 		    }
839 		    if (STRNICMP((char *)p, "true", 4) == 0)
840 		    {
841 			reader->js_used += 4;
842 			if (cur_item != NULL)
843 			{
844 			    cur_item->v_type = VAR_BOOL;
845 			    cur_item->vval.v_number = VVAL_TRUE;
846 			}
847 			retval = OK;
848 			break;
849 		    }
850 		    if (STRNICMP((char *)p, "null", 4) == 0)
851 		    {
852 			reader->js_used += 4;
853 			if (cur_item != NULL)
854 			{
855 			    cur_item->v_type = VAR_SPECIAL;
856 			    cur_item->vval.v_number = VVAL_NULL;
857 			}
858 			retval = OK;
859 			break;
860 		    }
861 #ifdef FEAT_FLOAT
862 		    if (STRNICMP((char *)p, "NaN", 3) == 0)
863 		    {
864 			reader->js_used += 3;
865 			if (cur_item != NULL)
866 			{
867 			    cur_item->v_type = VAR_FLOAT;
868 			    cur_item->vval.v_float = NAN;
869 			}
870 			retval = OK;
871 			break;
872 		    }
873 		    if (STRNICMP((char *)p, "-Infinity", 9) == 0)
874 		    {
875 			reader->js_used += 9;
876 			if (cur_item != NULL)
877 			{
878 			    cur_item->v_type = VAR_FLOAT;
879 			    cur_item->vval.v_float = -INFINITY;
880 			}
881 			retval = OK;
882 			break;
883 		    }
884 		    if (STRNICMP((char *)p, "Infinity", 8) == 0)
885 		    {
886 			reader->js_used += 8;
887 			if (cur_item != NULL)
888 			{
889 			    cur_item->v_type = VAR_FLOAT;
890 			    cur_item->vval.v_float = INFINITY;
891 			}
892 			retval = OK;
893 			break;
894 		    }
895 #endif
896 		    // check for truncated name
897 		    len = (int)(reader->js_end
898 					 - (reader->js_buf + reader->js_used));
899 		    if (
900 			    (len < 5 && STRNICMP((char *)p, "false", len) == 0)
901 #ifdef FEAT_FLOAT
902 			    || (len < 9 && STRNICMP((char *)p, "-Infinity", len) == 0)
903 			    || (len < 8 && STRNICMP((char *)p, "Infinity", len) == 0)
904 			    || (len < 3 && STRNICMP((char *)p, "NaN", len) == 0)
905 #endif
906 			    || (len < 4 && (STRNICMP((char *)p, "true", len) == 0
907 				       ||  STRNICMP((char *)p, "null", len) == 0)))
908 
909 			retval = MAYBE;
910 		    else
911 			retval = FAIL;
912 		    break;
913 	    }
914 
915 	    // We are finished when retval is FAIL or MAYBE and when at the
916 	    // toplevel.
917 	    if (retval == FAIL)
918 		break;
919 	    if (retval == MAYBE || stack.ga_len == 0)
920 		goto theend;
921 
922 	    if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY
923 		    && cur_item != NULL)
924 	    {
925 		top_item->jd_key = tv_get_string_buf_chk(cur_item, key_buf);
926 		if (top_item->jd_key == NULL)
927 		{
928 		    clear_tv(cur_item);
929 		    emsg(_(e_invarg));
930 		    retval = FAIL;
931 		    goto theend;
932 		}
933 	    }
934 	}
935 
936 item_end:
937 	top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1;
938 	switch (top_item->jd_type)
939 	{
940 	    case JSON_ARRAY:
941 		if (res != NULL)
942 		{
943 		    listitem_T	*li = listitem_alloc();
944 
945 		    if (li == NULL)
946 		    {
947 			clear_tv(cur_item);
948 			retval = FAIL;
949 			goto theend;
950 		    }
951 		    li->li_tv = *cur_item;
952 		    list_append(top_item->jd_tv.vval.v_list, li);
953 		}
954 		if (cur_item != NULL)
955 		    cur_item = &item;
956 
957 		json_skip_white(reader);
958 		p = reader->js_buf + reader->js_used;
959 		if (*p == ',')
960 		    ++reader->js_used;
961 		else if (*p != ']')
962 		{
963 		    if (*p == NUL)
964 			retval = MAYBE;
965 		    else
966 		    {
967 			semsg(_(e_json_error), p);
968 			retval = FAIL;
969 		    }
970 		    goto theend;
971 		}
972 		break;
973 
974 	    case JSON_OBJECT_KEY:
975 		json_skip_white(reader);
976 		p = reader->js_buf + reader->js_used;
977 		if (*p != ':')
978 		{
979 		    if (cur_item != NULL)
980 			clear_tv(cur_item);
981 		    if (*p == NUL)
982 			retval = MAYBE;
983 		    else
984 		    {
985 			semsg(_(e_json_error), p);
986 			retval = FAIL;
987 		    }
988 		    goto theend;
989 		}
990 		++reader->js_used;
991 		json_skip_white(reader);
992 		top_item->jd_type = JSON_OBJECT;
993 		if (cur_item != NULL)
994 		    cur_item = &item;
995 		break;
996 
997 	    case JSON_OBJECT:
998 		if (cur_item != NULL
999 			&& dict_find(top_item->jd_tv.vval.v_dict,
1000 						 top_item->jd_key, -1) != NULL)
1001 		{
1002 		    semsg(_("E938: Duplicate key in JSON: \"%s\""),
1003 							     top_item->jd_key);
1004 		    clear_tv(&top_item->jd_key_tv);
1005 		    clear_tv(cur_item);
1006 		    retval = FAIL;
1007 		    goto theend;
1008 		}
1009 
1010 		if (cur_item != NULL)
1011 		{
1012 		    dictitem_T *di = dictitem_alloc(top_item->jd_key);
1013 
1014 		    clear_tv(&top_item->jd_key_tv);
1015 		    if (di == NULL)
1016 		    {
1017 			clear_tv(cur_item);
1018 			retval = FAIL;
1019 			goto theend;
1020 		    }
1021 		    di->di_tv = *cur_item;
1022 		    di->di_tv.v_lock = 0;
1023 		    if (dict_add(top_item->jd_tv.vval.v_dict, di) == FAIL)
1024 		    {
1025 			dictitem_free(di);
1026 			retval = FAIL;
1027 			goto theend;
1028 		    }
1029 		}
1030 
1031 		json_skip_white(reader);
1032 		p = reader->js_buf + reader->js_used;
1033 		if (*p == ',')
1034 		    ++reader->js_used;
1035 		else if (*p != '}')
1036 		{
1037 		    if (*p == NUL)
1038 			retval = MAYBE;
1039 		    else
1040 		    {
1041 			semsg(_(e_json_error), p);
1042 			retval = FAIL;
1043 		    }
1044 		    goto theend;
1045 		}
1046 		top_item->jd_type = JSON_OBJECT_KEY;
1047 		if (cur_item != NULL)
1048 		    cur_item = &top_item->jd_key_tv;
1049 		break;
1050 	}
1051     }
1052 
1053     // Get here when parsing failed.
1054     if (res != NULL)
1055     {
1056 	clear_tv(res);
1057 	res->v_type = VAR_SPECIAL;
1058 	res->vval.v_number = VVAL_NONE;
1059     }
1060     semsg(_(e_json_error), p);
1061 
1062 theend:
1063     ga_clear(&stack);
1064     return retval;
1065 }
1066 
1067 /*
1068  * Decode the JSON from "reader" and store the result in "res".
1069  * "options" can be JSON_JS or zero;
1070  * Return FAIL if not the whole message was consumed.
1071  */
1072     static int
1073 json_decode_all(js_read_T *reader, typval_T *res, int options)
1074 {
1075     int ret;
1076 
1077     // We find the end once, to avoid calling strlen() many times.
1078     reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
1079     json_skip_white(reader);
1080     ret = json_decode_item(reader, res, options);
1081     if (ret != OK)
1082     {
1083 	if (ret == MAYBE)
1084 	    semsg(_(e_json_error), reader->js_buf);
1085 	return FAIL;
1086     }
1087     json_skip_white(reader);
1088     if (reader->js_buf[reader->js_used] != NUL)
1089     {
1090 	emsg(_(e_trailing));
1091 	return FAIL;
1092     }
1093     return OK;
1094 }
1095 
1096 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
1097 /*
1098  * Decode the JSON from "reader" and store the result in "res".
1099  * "options" can be JSON_JS or zero;
1100  * Return FAIL for a decoding error.
1101  * Return MAYBE for an incomplete message.
1102  * Consumes the message anyway.
1103  */
1104     int
1105 json_decode(js_read_T *reader, typval_T *res, int options)
1106 {
1107     int ret;
1108 
1109     // We find the end once, to avoid calling strlen() many times.
1110     reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
1111     json_skip_white(reader);
1112     ret = json_decode_item(reader, res, options);
1113     json_skip_white(reader);
1114 
1115     return ret;
1116 }
1117 #endif
1118 
1119 /*
1120  * Decode the JSON from "reader" to find the end of the message.
1121  * "options" can be JSON_JS or zero.
1122  * This is only used for testing.
1123  * Return FAIL if the message has a decoding error.
1124  * Return MAYBE if the message is truncated, need to read more.
1125  * This only works reliable if the message contains an object, array or
1126  * string.  A number might be truncated without knowing.
1127  * Does not advance the reader.
1128  */
1129     int
1130 json_find_end(js_read_T *reader, int options)
1131 {
1132     int used_save = reader->js_used;
1133     int ret;
1134 
1135     // We find the end once, to avoid calling strlen() many times.
1136     reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
1137     json_skip_white(reader);
1138     ret = json_decode_item(reader, NULL, options);
1139     reader->js_used = used_save;
1140     return ret;
1141 }
1142 
1143 /*
1144  * "js_decode()" function
1145  */
1146     void
1147 f_js_decode(typval_T *argvars, typval_T *rettv)
1148 {
1149     js_read_T	reader;
1150 
1151     reader.js_buf = tv_get_string(&argvars[0]);
1152     reader.js_fill = NULL;
1153     reader.js_used = 0;
1154     if (json_decode_all(&reader, rettv, JSON_JS) != OK)
1155 	emsg(_(e_invarg));
1156 }
1157 
1158 /*
1159  * "js_encode()" function
1160  */
1161     void
1162 f_js_encode(typval_T *argvars, typval_T *rettv)
1163 {
1164     rettv->v_type = VAR_STRING;
1165     rettv->vval.v_string = json_encode(&argvars[0], JSON_JS);
1166 }
1167 
1168 /*
1169  * "json_decode()" function
1170  */
1171     void
1172 f_json_decode(typval_T *argvars, typval_T *rettv)
1173 {
1174     js_read_T	reader;
1175 
1176     reader.js_buf = tv_get_string(&argvars[0]);
1177     reader.js_fill = NULL;
1178     reader.js_used = 0;
1179     json_decode_all(&reader, rettv, 0);
1180 }
1181 
1182 /*
1183  * "json_encode()" function
1184  */
1185     void
1186 f_json_encode(typval_T *argvars, typval_T *rettv)
1187 {
1188     rettv->v_type = VAR_STRING;
1189     rettv->vval.v_string = json_encode(&argvars[0], 0);
1190 }
1191 #endif
1192