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