xref: /vim-8.2.3635/src/json.c (revision 2d2970ea)
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 		    CHECK_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_ANY:
355 	case VAR_VOID:
356 	    internal_error_no_abort("json_encode_item()");
357 	    return FAIL;
358     }
359     return OK;
360 }
361 
362 /*
363  * When "reader" has less than NUMBUFLEN bytes available, call the fill
364  * callback to get more.
365  */
366     static void
367 fill_numbuflen(js_read_T *reader)
368 {
369     if (reader->js_fill != NULL && (int)(reader->js_end - reader->js_buf)
370 						- reader->js_used < NUMBUFLEN)
371     {
372 	if (reader->js_fill(reader))
373 	    reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
374     }
375 }
376 
377 /*
378  * Skip white space in "reader".  All characters <= space are considered white
379  * space.
380  * Also tops up readahead when needed.
381  */
382     static void
383 json_skip_white(js_read_T *reader)
384 {
385     int c;
386 
387     for (;;)
388     {
389 	c = reader->js_buf[reader->js_used];
390 	if (reader->js_fill != NULL && c == NUL)
391 	{
392 	    if (reader->js_fill(reader))
393 	    {
394 		reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
395 		continue;
396 	    }
397 	}
398 	if (c == NUL || c > ' ')
399 	    break;
400 	++reader->js_used;
401     }
402     fill_numbuflen(reader);
403 }
404 
405     static int
406 json_decode_string(js_read_T *reader, typval_T *res, int quote)
407 {
408     garray_T    ga;
409     int		len;
410     char_u	*p;
411     int		c;
412     varnumber_T	nr;
413 
414     if (res != NULL)
415 	ga_init2(&ga, 1, 200);
416 
417     p = reader->js_buf + reader->js_used + 1; // skip over " or '
418     while (*p != quote)
419     {
420 	// The JSON is always expected to be utf-8, thus use utf functions
421 	// here. The string is converted below if needed.
422 	if (*p == NUL || p[1] == NUL || utf_ptr2len(p) < utf_byte2len(*p))
423 	{
424 	    // Not enough bytes to make a character or end of the string. Get
425 	    // more if possible.
426 	    if (reader->js_fill == NULL)
427 		break;
428 	    len = (int)(reader->js_end - p);
429 	    reader->js_used = (int)(p - reader->js_buf);
430 	    if (!reader->js_fill(reader))
431 		break; // didn't get more
432 	    p = reader->js_buf + reader->js_used;
433 	    reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
434 	    continue;
435 	}
436 
437 	if (*p == '\\')
438 	{
439 	    c = -1;
440 	    switch (p[1])
441 	    {
442 		case '\\': c = '\\'; break;
443 		case '"': c = '"'; break;
444 		case 'b': c = BS; break;
445 		case 't': c = TAB; break;
446 		case 'n': c = NL; break;
447 		case 'f': c = FF; break;
448 		case 'r': c = CAR; break;
449 		case 'u':
450 		    if (reader->js_fill != NULL
451 				     && (int)(reader->js_end - p) < NUMBUFLEN)
452 		    {
453 			reader->js_used = (int)(p - reader->js_buf);
454 			if (reader->js_fill(reader))
455 			{
456 			    p = reader->js_buf + reader->js_used;
457 			    reader->js_end = reader->js_buf
458 						     + STRLEN(reader->js_buf);
459 			}
460 		    }
461 		    nr = 0;
462 		    len = 0;
463 		    vim_str2nr(p + 2, NULL, &len,
464 			     STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4, TRUE);
465 		    if (len == 0)
466 		    {
467 			if (res != NULL)
468 			    ga_clear(&ga);
469 			return FAIL;
470 		    }
471 		    p += len + 2;
472 		    if (0xd800 <= nr && nr <= 0xdfff
473 			    && (int)(reader->js_end - p) >= 6
474 			    && *p == '\\' && *(p+1) == 'u')
475 		    {
476 			varnumber_T	nr2 = 0;
477 
478 			// decode surrogate pair: \ud812\u3456
479 			len = 0;
480 			vim_str2nr(p + 2, NULL, &len,
481 			     STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4, TRUE);
482 			if (len == 0)
483 			{
484 			    if (res != NULL)
485 				ga_clear(&ga);
486 			    return FAIL;
487 			}
488 			if (0xdc00 <= nr2 && nr2 <= 0xdfff)
489 			{
490 			    p += len + 2;
491 			    nr = (((nr - 0xd800) << 10) |
492 				((nr2 - 0xdc00) & 0x3ff)) + 0x10000;
493 			}
494 		    }
495 		    if (res != NULL)
496 		    {
497 			char_u	buf[NUMBUFLEN];
498 
499 			buf[utf_char2bytes((int)nr, buf)] = NUL;
500 			ga_concat(&ga, buf);
501 		    }
502 		    break;
503 		default:
504 		    // not a special char, skip over backslash
505 		    ++p;
506 		    continue;
507 	    }
508 	    if (c > 0)
509 	    {
510 		p += 2;
511 		if (res != NULL)
512 		    ga_append(&ga, c);
513 	    }
514 	}
515 	else
516 	{
517 	    len = utf_ptr2len(p);
518 	    if (res != NULL)
519 	    {
520 		if (ga_grow(&ga, len) == FAIL)
521 		{
522 		    ga_clear(&ga);
523 		    return FAIL;
524 		}
525 		mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len);
526 		ga.ga_len += len;
527 	    }
528 	    p += len;
529 	}
530     }
531 
532     reader->js_used = (int)(p - reader->js_buf);
533     if (*p == quote)
534     {
535 	++reader->js_used;
536 	if (res != NULL)
537 	{
538 	    ga_append(&ga, NUL);
539 	    res->v_type = VAR_STRING;
540 #if defined(USE_ICONV)
541 	    if (!enc_utf8)
542 	    {
543 		vimconv_T   conv;
544 
545 		// Convert the utf-8 string to 'encoding'.
546 		conv.vc_type = CONV_NONE;
547 		convert_setup(&conv, (char_u*)"utf-8", p_enc);
548 		if (conv.vc_type != CONV_NONE)
549 		{
550 		    res->vval.v_string =
551 				      string_convert(&conv, ga.ga_data, NULL);
552 		    vim_free(ga.ga_data);
553 		}
554 		convert_setup(&conv, NULL, NULL);
555 	    }
556 	    else
557 #endif
558 		res->vval.v_string = ga.ga_data;
559 	}
560 	return OK;
561     }
562     if (res != NULL)
563     {
564 	res->v_type = VAR_SPECIAL;
565 	res->vval.v_number = VVAL_NONE;
566 	ga_clear(&ga);
567     }
568     return MAYBE;
569 }
570 
571 typedef enum {
572     JSON_ARRAY,		// parsing items in an array
573     JSON_OBJECT_KEY,	// parsing key of an object
574     JSON_OBJECT		// parsing item in an object, after the key
575 } json_decode_T;
576 
577 typedef struct {
578     json_decode_T jd_type;
579     typval_T	  jd_tv;	// the list or dict
580     typval_T	  jd_key_tv;
581     char_u	  *jd_key;
582 } json_dec_item_T;
583 
584 /*
585  * Decode one item and put it in "res".  If "res" is NULL only advance.
586  * Must already have skipped white space.
587  *
588  * Return FAIL for a decoding error (and give an error).
589  * Return MAYBE for an incomplete message.
590  */
591     static int
592 json_decode_item(js_read_T *reader, typval_T *res, int options)
593 {
594     char_u	*p;
595     int		len;
596     int		retval;
597     garray_T	stack;
598     typval_T	item;
599     typval_T	*cur_item;
600     json_dec_item_T *top_item;
601     char_u	key_buf[NUMBUFLEN];
602 
603     ga_init2(&stack, sizeof(json_dec_item_T), 100);
604     cur_item = res;
605     init_tv(&item);
606     if (res != NULL)
607     init_tv(res);
608 
609     fill_numbuflen(reader);
610     p = reader->js_buf + reader->js_used;
611     for (;;)
612     {
613 	top_item = NULL;
614 	if (stack.ga_len > 0)
615 	{
616 	    top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1;
617 	    json_skip_white(reader);
618 	    p = reader->js_buf + reader->js_used;
619 	    if (*p == NUL)
620 	    {
621 		retval = MAYBE;
622 		if (top_item->jd_type == JSON_OBJECT)
623 		    // did get the key, clear it
624 		    clear_tv(&top_item->jd_key_tv);
625 		goto theend;
626 	    }
627 	    if (top_item->jd_type == JSON_OBJECT_KEY
628 					    || top_item->jd_type == JSON_ARRAY)
629 	    {
630 		// Check for end of object or array.
631 		if (*p == (top_item->jd_type == JSON_ARRAY ? ']' : '}'))
632 		{
633 		    ++reader->js_used; // consume the ']' or '}'
634 		    --stack.ga_len;
635 		    if (stack.ga_len == 0)
636 		    {
637 			retval = OK;
638 			goto theend;
639 		    }
640 		    if (cur_item != NULL)
641 			cur_item = &top_item->jd_tv;
642 		    goto item_end;
643 		}
644 	    }
645 	}
646 
647 	if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY
648 		&& (options & JSON_JS)
649 		&& reader->js_buf[reader->js_used] != '"'
650 		&& reader->js_buf[reader->js_used] != '\''
651 		&& reader->js_buf[reader->js_used] != '['
652 		&& reader->js_buf[reader->js_used] != '{')
653 	{
654 	    char_u *key;
655 
656 	    // accept an object key that is not in quotes
657 	    key = p = reader->js_buf + reader->js_used;
658 	    while (*p != NUL && *p != ':' && *p > ' ')
659 		++p;
660 	    if (cur_item != NULL)
661 	    {
662 		cur_item->v_type = VAR_STRING;
663 		cur_item->vval.v_string = vim_strnsave(key, (int)(p - key));
664 		top_item->jd_key = cur_item->vval.v_string;
665 	    }
666 	    reader->js_used += (int)(p - key);
667 	}
668 	else
669 	{
670 	    switch (*p)
671 	    {
672 		case '[': // start of array
673 		    if (top_item && top_item->jd_type == JSON_OBJECT_KEY)
674 		    {
675 			retval = FAIL;
676 			break;
677 		    }
678 		    if (ga_grow(&stack, 1) == FAIL)
679 		    {
680 			retval = FAIL;
681 			break;
682 		    }
683 		    if (cur_item != NULL && rettv_list_alloc(cur_item) == FAIL)
684 		    {
685 			cur_item->v_type = VAR_SPECIAL;
686 			cur_item->vval.v_number = VVAL_NONE;
687 			retval = FAIL;
688 			break;
689 		    }
690 
691 		    ++reader->js_used; // consume the '['
692 		    top_item = ((json_dec_item_T *)stack.ga_data)
693 								+ stack.ga_len;
694 		    top_item->jd_type = JSON_ARRAY;
695 		    ++stack.ga_len;
696 		    if (cur_item != NULL)
697 		    {
698 			top_item->jd_tv = *cur_item;
699 			cur_item = &item;
700 		    }
701 		    continue;
702 
703 		case '{': // start of object
704 		    if (top_item && top_item->jd_type == JSON_OBJECT_KEY)
705 		    {
706 			retval = FAIL;
707 			break;
708 		    }
709 		    if (ga_grow(&stack, 1) == FAIL)
710 		    {
711 			retval = FAIL;
712 			break;
713 		    }
714 		    if (cur_item != NULL && rettv_dict_alloc(cur_item) == FAIL)
715 		    {
716 			cur_item->v_type = VAR_SPECIAL;
717 			cur_item->vval.v_number = VVAL_NONE;
718 			retval = FAIL;
719 			break;
720 		    }
721 
722 		    ++reader->js_used; // consume the '{'
723 		    top_item = ((json_dec_item_T *)stack.ga_data)
724 								+ stack.ga_len;
725 		    top_item->jd_type = JSON_OBJECT_KEY;
726 		    ++stack.ga_len;
727 		    if (cur_item != NULL)
728 		    {
729 			top_item->jd_tv = *cur_item;
730 			cur_item = &top_item->jd_key_tv;
731 		    }
732 		    continue;
733 
734 		case '"': // string
735 		    retval = json_decode_string(reader, cur_item, *p);
736 		    break;
737 
738 		case '\'':
739 		    if (options & JSON_JS)
740 			retval = json_decode_string(reader, cur_item, *p);
741 		    else
742 		    {
743 			emsg(_(e_invarg));
744 			retval = FAIL;
745 		    }
746 		    break;
747 
748 		case ',': // comma: empty item
749 		    if ((options & JSON_JS) == 0)
750 		    {
751 			emsg(_(e_invarg));
752 			retval = FAIL;
753 			break;
754 		    }
755 		    // FALLTHROUGH
756 		case NUL: // empty
757 		    if (cur_item != NULL)
758 		    {
759 			cur_item->v_type = VAR_SPECIAL;
760 			cur_item->vval.v_number = VVAL_NONE;
761 		    }
762 		    retval = OK;
763 		    break;
764 
765 		default:
766 		    if (VIM_ISDIGIT(*p) || (*p == '-'
767 					&& (VIM_ISDIGIT(p[1]) || p[1] == NUL)))
768 		    {
769 			char_u  *sp = p;
770 
771 			if (*sp == '-')
772 			{
773 			    ++sp;
774 			    if (*sp == NUL)
775 			    {
776 				retval = MAYBE;
777 				break;
778 			    }
779 			    if (!VIM_ISDIGIT(*sp))
780 			    {
781 				emsg(_(e_invarg));
782 				retval = FAIL;
783 				break;
784 			    }
785 			}
786 			sp = skipdigits(sp);
787 #ifdef FEAT_FLOAT
788 			if (*sp == '.' || *sp == 'e' || *sp == 'E')
789 			{
790 			    if (cur_item == NULL)
791 			    {
792 				float_T f;
793 
794 				len = string2float(p, &f);
795 			    }
796 			    else
797 			    {
798 				cur_item->v_type = VAR_FLOAT;
799 				len = string2float(p, &cur_item->vval.v_float);
800 			    }
801 			}
802 			else
803 #endif
804 			{
805 			    varnumber_T nr;
806 
807 			    vim_str2nr(reader->js_buf + reader->js_used,
808 				    NULL, &len, 0, // what
809 				    &nr, NULL, 0, TRUE);
810 			    if (len == 0)
811 			    {
812 				emsg(_(e_invarg));
813 				retval = FAIL;
814 				goto theend;
815 			    }
816 			    if (cur_item != NULL)
817 			    {
818 				cur_item->v_type = VAR_NUMBER;
819 				cur_item->vval.v_number = nr;
820 			    }
821 			}
822 			reader->js_used += len;
823 			retval = OK;
824 			break;
825 		    }
826 		    if (STRNICMP((char *)p, "false", 5) == 0)
827 		    {
828 			reader->js_used += 5;
829 			if (cur_item != NULL)
830 			{
831 			    cur_item->v_type = VAR_BOOL;
832 			    cur_item->vval.v_number = VVAL_FALSE;
833 			}
834 			retval = OK;
835 			break;
836 		    }
837 		    if (STRNICMP((char *)p, "true", 4) == 0)
838 		    {
839 			reader->js_used += 4;
840 			if (cur_item != NULL)
841 			{
842 			    cur_item->v_type = VAR_BOOL;
843 			    cur_item->vval.v_number = VVAL_TRUE;
844 			}
845 			retval = OK;
846 			break;
847 		    }
848 		    if (STRNICMP((char *)p, "null", 4) == 0)
849 		    {
850 			reader->js_used += 4;
851 			if (cur_item != NULL)
852 			{
853 			    cur_item->v_type = VAR_SPECIAL;
854 			    cur_item->vval.v_number = VVAL_NULL;
855 			}
856 			retval = OK;
857 			break;
858 		    }
859 #ifdef FEAT_FLOAT
860 		    if (STRNICMP((char *)p, "NaN", 3) == 0)
861 		    {
862 			reader->js_used += 3;
863 			if (cur_item != NULL)
864 			{
865 			    cur_item->v_type = VAR_FLOAT;
866 			    cur_item->vval.v_float = NAN;
867 			}
868 			retval = OK;
869 			break;
870 		    }
871 		    if (STRNICMP((char *)p, "-Infinity", 9) == 0)
872 		    {
873 			reader->js_used += 9;
874 			if (cur_item != NULL)
875 			{
876 			    cur_item->v_type = VAR_FLOAT;
877 			    cur_item->vval.v_float = -INFINITY;
878 			}
879 			retval = OK;
880 			break;
881 		    }
882 		    if (STRNICMP((char *)p, "Infinity", 8) == 0)
883 		    {
884 			reader->js_used += 8;
885 			if (cur_item != NULL)
886 			{
887 			    cur_item->v_type = VAR_FLOAT;
888 			    cur_item->vval.v_float = INFINITY;
889 			}
890 			retval = OK;
891 			break;
892 		    }
893 #endif
894 		    // check for truncated name
895 		    len = (int)(reader->js_end
896 					 - (reader->js_buf + reader->js_used));
897 		    if (
898 			    (len < 5 && STRNICMP((char *)p, "false", len) == 0)
899 #ifdef FEAT_FLOAT
900 			    || (len < 9 && STRNICMP((char *)p, "-Infinity", len) == 0)
901 			    || (len < 8 && STRNICMP((char *)p, "Infinity", len) == 0)
902 			    || (len < 3 && STRNICMP((char *)p, "NaN", len) == 0)
903 #endif
904 			    || (len < 4 && (STRNICMP((char *)p, "true", len) == 0
905 				       ||  STRNICMP((char *)p, "null", len) == 0)))
906 
907 			retval = MAYBE;
908 		    else
909 			retval = FAIL;
910 		    break;
911 	    }
912 
913 	    // We are finished when retval is FAIL or MAYBE and when at the
914 	    // toplevel.
915 	    if (retval == FAIL)
916 		break;
917 	    if (retval == MAYBE || stack.ga_len == 0)
918 		goto theend;
919 
920 	    if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY
921 		    && cur_item != NULL)
922 	    {
923 		top_item->jd_key = tv_get_string_buf_chk(cur_item, key_buf);
924 		if (top_item->jd_key == NULL)
925 		{
926 		    clear_tv(cur_item);
927 		    emsg(_(e_invarg));
928 		    retval = FAIL;
929 		    goto theend;
930 		}
931 	    }
932 	}
933 
934 item_end:
935 	top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1;
936 	switch (top_item->jd_type)
937 	{
938 	    case JSON_ARRAY:
939 		if (res != NULL)
940 		{
941 		    listitem_T	*li = listitem_alloc();
942 
943 		    if (li == NULL)
944 		    {
945 			clear_tv(cur_item);
946 			retval = FAIL;
947 			goto theend;
948 		    }
949 		    li->li_tv = *cur_item;
950 		    list_append(top_item->jd_tv.vval.v_list, li);
951 		}
952 		if (cur_item != NULL)
953 		    cur_item = &item;
954 
955 		json_skip_white(reader);
956 		p = reader->js_buf + reader->js_used;
957 		if (*p == ',')
958 		    ++reader->js_used;
959 		else if (*p != ']')
960 		{
961 		    if (*p == NUL)
962 			retval = MAYBE;
963 		    else
964 		    {
965 			emsg(_(e_invarg));
966 			retval = FAIL;
967 		    }
968 		    goto theend;
969 		}
970 		break;
971 
972 	    case JSON_OBJECT_KEY:
973 		json_skip_white(reader);
974 		p = reader->js_buf + reader->js_used;
975 		if (*p != ':')
976 		{
977 		    if (cur_item != NULL)
978 			clear_tv(cur_item);
979 		    if (*p == NUL)
980 			retval = MAYBE;
981 		    else
982 		    {
983 			emsg(_(e_invarg));
984 			retval = FAIL;
985 		    }
986 		    goto theend;
987 		}
988 		++reader->js_used;
989 		json_skip_white(reader);
990 		top_item->jd_type = JSON_OBJECT;
991 		if (cur_item != NULL)
992 		    cur_item = &item;
993 		break;
994 
995 	    case JSON_OBJECT:
996 		if (cur_item != NULL
997 			&& dict_find(top_item->jd_tv.vval.v_dict,
998 						 top_item->jd_key, -1) != NULL)
999 		{
1000 		    semsg(_("E938: Duplicate key in JSON: \"%s\""),
1001 							     top_item->jd_key);
1002 		    clear_tv(&top_item->jd_key_tv);
1003 		    clear_tv(cur_item);
1004 		    retval = FAIL;
1005 		    goto theend;
1006 		}
1007 
1008 		if (cur_item != NULL)
1009 		{
1010 		    dictitem_T *di = dictitem_alloc(top_item->jd_key);
1011 
1012 		    clear_tv(&top_item->jd_key_tv);
1013 		    if (di == NULL)
1014 		    {
1015 			clear_tv(cur_item);
1016 			retval = FAIL;
1017 			goto theend;
1018 		    }
1019 		    di->di_tv = *cur_item;
1020 		    di->di_tv.v_lock = 0;
1021 		    if (dict_add(top_item->jd_tv.vval.v_dict, di) == FAIL)
1022 		    {
1023 			dictitem_free(di);
1024 			retval = FAIL;
1025 			goto theend;
1026 		    }
1027 		}
1028 
1029 		json_skip_white(reader);
1030 		p = reader->js_buf + reader->js_used;
1031 		if (*p == ',')
1032 		    ++reader->js_used;
1033 		else if (*p != '}')
1034 		{
1035 		    if (*p == NUL)
1036 			retval = MAYBE;
1037 		    else
1038 		    {
1039 			emsg(_(e_invarg));
1040 			retval = FAIL;
1041 		    }
1042 		    goto theend;
1043 		}
1044 		top_item->jd_type = JSON_OBJECT_KEY;
1045 		if (cur_item != NULL)
1046 		    cur_item = &top_item->jd_key_tv;
1047 		break;
1048 	}
1049     }
1050 
1051     // Get here when parsing failed.
1052     if (res != NULL)
1053     {
1054 	clear_tv(res);
1055 	res->v_type = VAR_SPECIAL;
1056 	res->vval.v_number = VVAL_NONE;
1057     }
1058     emsg(_(e_invarg));
1059 
1060 theend:
1061     ga_clear(&stack);
1062     return retval;
1063 }
1064 
1065 /*
1066  * Decode the JSON from "reader" and store the result in "res".
1067  * "options" can be JSON_JS or zero;
1068  * Return FAIL if not the whole message was consumed.
1069  */
1070     static int
1071 json_decode_all(js_read_T *reader, typval_T *res, int options)
1072 {
1073     int ret;
1074 
1075     // We find the end once, to avoid calling strlen() many times.
1076     reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
1077     json_skip_white(reader);
1078     ret = json_decode_item(reader, res, options);
1079     if (ret != OK)
1080     {
1081 	if (ret == MAYBE)
1082 	    emsg(_(e_invarg));
1083 	return FAIL;
1084     }
1085     json_skip_white(reader);
1086     if (reader->js_buf[reader->js_used] != NUL)
1087     {
1088 	emsg(_(e_trailing));
1089 	return FAIL;
1090     }
1091     return OK;
1092 }
1093 
1094 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
1095 /*
1096  * Decode the JSON from "reader" and store the result in "res".
1097  * "options" can be JSON_JS or zero;
1098  * Return FAIL for a decoding error.
1099  * Return MAYBE for an incomplete message.
1100  * Consumes the message anyway.
1101  */
1102     int
1103 json_decode(js_read_T *reader, typval_T *res, int options)
1104 {
1105     int ret;
1106 
1107     // We find the end once, to avoid calling strlen() many times.
1108     reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
1109     json_skip_white(reader);
1110     ret = json_decode_item(reader, res, options);
1111     json_skip_white(reader);
1112 
1113     return ret;
1114 }
1115 #endif
1116 
1117 /*
1118  * Decode the JSON from "reader" to find the end of the message.
1119  * "options" can be JSON_JS or zero.
1120  * This is only used for testing.
1121  * Return FAIL if the message has a decoding error.
1122  * Return MAYBE if the message is truncated, need to read more.
1123  * This only works reliable if the message contains an object, array or
1124  * string.  A number might be truncated without knowing.
1125  * Does not advance the reader.
1126  */
1127     int
1128 json_find_end(js_read_T *reader, int options)
1129 {
1130     int used_save = reader->js_used;
1131     int ret;
1132 
1133     // We find the end once, to avoid calling strlen() many times.
1134     reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
1135     json_skip_white(reader);
1136     ret = json_decode_item(reader, NULL, options);
1137     reader->js_used = used_save;
1138     return ret;
1139 }
1140 
1141 /*
1142  * "js_decode()" function
1143  */
1144     void
1145 f_js_decode(typval_T *argvars, typval_T *rettv)
1146 {
1147     js_read_T	reader;
1148 
1149     reader.js_buf = tv_get_string(&argvars[0]);
1150     reader.js_fill = NULL;
1151     reader.js_used = 0;
1152     if (json_decode_all(&reader, rettv, JSON_JS) != OK)
1153 	emsg(_(e_invarg));
1154 }
1155 
1156 /*
1157  * "js_encode()" function
1158  */
1159     void
1160 f_js_encode(typval_T *argvars, typval_T *rettv)
1161 {
1162     rettv->v_type = VAR_STRING;
1163     rettv->vval.v_string = json_encode(&argvars[0], JSON_JS);
1164 }
1165 
1166 /*
1167  * "json_decode()" function
1168  */
1169     void
1170 f_json_decode(typval_T *argvars, typval_T *rettv)
1171 {
1172     js_read_T	reader;
1173 
1174     reader.js_buf = tv_get_string(&argvars[0]);
1175     reader.js_fill = NULL;
1176     reader.js_used = 0;
1177     json_decode_all(&reader, rettv, 0);
1178 }
1179 
1180 /*
1181  * "json_encode()" function
1182  */
1183     void
1184 f_json_encode(typval_T *argvars, typval_T *rettv)
1185 {
1186     rettv->v_type = VAR_STRING;
1187     rettv->vval.v_string = json_encode(&argvars[0], 0);
1188 }
1189 #endif
1190