comparison src/json.c @ 7967:45ea5ebf3a98 v7.4.1279

commit https://github.com/vim/vim/commit/595e64e259faefb330866852e1b9f6168544572a Author: Bram Moolenaar <Bram@vim.org> Date: Sun Feb 7 19:19:53 2016 +0100 patch 7.4.1279 Problem: jsonencode() is not producing strict JSON. Solution: Add jsencode() and jsdecode(). Make jsonencode() and jsondecode() strict.
author Christian Brabandt <cb@256bit.org>
date Sun, 07 Feb 2016 19:30:05 +0100
parents 646d5148fee2
children c6443e78cf2d
comparison
equal deleted inserted replaced
7966:79c5a86fcdfe 7967:45ea5ebf3a98
14 */ 14 */
15 15
16 #include "vim.h" 16 #include "vim.h"
17 17
18 #if defined(FEAT_EVAL) || defined(PROTO) 18 #if defined(FEAT_EVAL) || defined(PROTO)
19 static int json_encode_item(garray_T *gap, typval_T *val, int copyID, int allow_none); 19 static int json_encode_item(garray_T *gap, typval_T *val, int copyID, int options);
20 static int json_decode_item(js_read_T *reader, typval_T *res); 20 static int json_decode_item(js_read_T *reader, typval_T *res, int options);
21 21
22 /* 22 /*
23 * Encode "val" into a JSON format string. 23 * Encode "val" into a JSON format string.
24 * The result is in allocated memory. 24 * The result is in allocated memory.
25 * The result is empty when encoding fails. 25 * The result is empty when encoding fails.
26 * "options" can be JSON_JS or zero;
26 */ 27 */
27 char_u * 28 char_u *
28 json_encode(typval_T *val) 29 json_encode(typval_T *val, int options)
29 { 30 {
30 garray_T ga; 31 garray_T ga;
31 32
32 /* Store bytes in the growarray. */ 33 /* Store bytes in the growarray. */
33 ga_init2(&ga, 1, 4000); 34 ga_init2(&ga, 1, 4000);
34 if (json_encode_item(&ga, val, get_copyID(), TRUE) == FAIL) 35 if (json_encode_item(&ga, val, get_copyID(), options) == FAIL)
35 { 36 {
36 vim_free(ga.ga_data); 37 vim_free(ga.ga_data);
37 return vim_strsave((char_u *)""); 38 return vim_strsave((char_u *)"");
38 } 39 }
39 return ga.ga_data; 40 return ga.ga_data;
40 } 41 }
41 42
42 /* 43 /*
43 * Encode ["nr", "val"] into a JSON format string in allocated memory. 44 * Encode ["nr", "val"] into a JSON format string in allocated memory.
45 * "options" can be JSON_JS or zero;
44 * Returns NULL when out of memory. 46 * Returns NULL when out of memory.
45 */ 47 */
46 char_u * 48 char_u *
47 json_encode_nr_expr(int nr, typval_T *val) 49 json_encode_nr_expr(int nr, typval_T *val, int options)
48 { 50 {
49 typval_T listtv; 51 typval_T listtv;
50 typval_T nrtv; 52 typval_T nrtv;
51 char_u *text; 53 char_u *text;
52 54
59 { 61 {
60 list_unref(listtv.vval.v_list); 62 list_unref(listtv.vval.v_list);
61 return NULL; 63 return NULL;
62 } 64 }
63 65
64 text = json_encode(&listtv); 66 text = json_encode(&listtv, options);
65 list_unref(listtv.vval.v_list); 67 list_unref(listtv.vval.v_list);
66 return text; 68 return text;
67 } 69 }
68 70
69 static void 71 static void
121 ga_append(gap, '"'); 123 ga_append(gap, '"');
122 } 124 }
123 } 125 }
124 126
125 /* 127 /*
128 * Return TRUE if "key" can be used without quotes.
129 * That is when it starts with a letter and only contains letters, digits and
130 * underscore.
131 */
132 static int
133 is_simple_key(char_u *key)
134 {
135 char_u *p;
136
137 if (!ASCII_ISALPHA(*key))
138 return FALSE;
139 for (p = key + 1; *p != NUL; ++p)
140 if (!ASCII_ISALPHA(*p) && *p != '_' && !vim_isdigit(*p))
141 return FALSE;
142 return TRUE;
143 }
144
145 /*
126 * Encode "val" into "gap". 146 * Encode "val" into "gap".
127 * Return FAIL or OK. 147 * Return FAIL or OK.
128 */ 148 */
129 static int 149 static int
130 json_encode_item(garray_T *gap, typval_T *val, int copyID, int allow_none) 150 json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
131 { 151 {
132 char_u numbuf[NUMBUFLEN]; 152 char_u numbuf[NUMBUFLEN];
133 char_u *res; 153 char_u *res;
134 list_T *l; 154 list_T *l;
135 dict_T *d; 155 dict_T *d;
139 case VAR_SPECIAL: 159 case VAR_SPECIAL:
140 switch (val->vval.v_number) 160 switch (val->vval.v_number)
141 { 161 {
142 case VVAL_FALSE: ga_concat(gap, (char_u *)"false"); break; 162 case VVAL_FALSE: ga_concat(gap, (char_u *)"false"); break;
143 case VVAL_TRUE: ga_concat(gap, (char_u *)"true"); break; 163 case VVAL_TRUE: ga_concat(gap, (char_u *)"true"); break;
144 case VVAL_NONE: if (!allow_none) 164 case VVAL_NONE: if ((options & JSON_JS) != 0
145 { 165 && (options & JSON_NO_NONE) == 0)
146 /* TODO: better error */ 166 /* empty item */
147 EMSG(_(e_invarg)); 167 break;
148 return FAIL; 168 /* FALLTHROUGH */
149 }
150 break;
151 case VVAL_NULL: ga_concat(gap, (char_u *)"null"); break; 169 case VVAL_NULL: ga_concat(gap, (char_u *)"null"); break;
152 } 170 }
153 break; 171 break;
154 172
155 case VAR_NUMBER: 173 case VAR_NUMBER:
183 201
184 l->lv_copyID = copyID; 202 l->lv_copyID = copyID;
185 ga_append(gap, '['); 203 ga_append(gap, '[');
186 for (li = l->lv_first; li != NULL && !got_int; ) 204 for (li = l->lv_first; li != NULL && !got_int; )
187 { 205 {
188 if (json_encode_item(gap, &li->li_tv, copyID, TRUE) 206 if (json_encode_item(gap, &li->li_tv, copyID,
189 == FAIL) 207 options & JSON_JS) == FAIL)
190 return FAIL; 208 return FAIL;
209 if ((options & JSON_JS)
210 && li->li_next == NULL
211 && li->li_tv.v_type == VAR_SPECIAL
212 && li->li_tv.vval.v_number == VVAL_NONE)
213 /* add an extra comma if the last item is v:none */
214 ga_append(gap, ',');
191 li = li->li_next; 215 li = li->li_next;
192 if (li != NULL) 216 if (li != NULL)
193 ga_append(gap, ','); 217 ga_append(gap, ',');
194 } 218 }
195 ga_append(gap, ']'); 219 ga_append(gap, ']');
222 --todo; 246 --todo;
223 if (first) 247 if (first)
224 first = FALSE; 248 first = FALSE;
225 else 249 else
226 ga_append(gap, ','); 250 ga_append(gap, ',');
227 write_string(gap, hi->hi_key); 251 if ((options & JSON_JS)
252 && is_simple_key(hi->hi_key))
253 ga_concat(gap, hi->hi_key);
254 else
255 write_string(gap, hi->hi_key);
228 ga_append(gap, ':'); 256 ga_append(gap, ':');
229 if (json_encode_item(gap, &dict_lookup(hi)->di_tv, 257 if (json_encode_item(gap, &dict_lookup(hi)->di_tv,
230 copyID, FALSE) == FAIL) 258 copyID, options | JSON_NO_NONE) == FAIL)
231 return FAIL; 259 return FAIL;
232 } 260 }
233 ga_append(gap, '}'); 261 ga_append(gap, '}');
234 d->dv_copyID = 0; 262 d->dv_copyID = 0;
235 } 263 }
263 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 291 reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
264 } 292 }
265 } 293 }
266 294
267 /* 295 /*
268 * Skip white space in "reader". 296 * Skip white space in "reader". All characters <= space are considered white
297 * space.
269 * Also tops up readahead when needed. 298 * Also tops up readahead when needed.
270 */ 299 */
271 static void 300 static void
272 json_skip_white(js_read_T *reader) 301 json_skip_white(js_read_T *reader)
273 { 302 {
280 { 309 {
281 if (reader->js_fill(reader)) 310 if (reader->js_fill(reader))
282 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 311 reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
283 continue; 312 continue;
284 } 313 }
285 if (c != ' ' && c != TAB && c != NL && c != CAR) 314 if (c == NUL || c > ' ')
286 break; 315 break;
287 ++reader->js_used; 316 ++reader->js_used;
288 } 317 }
289 fill_numbuflen(reader); 318 fill_numbuflen(reader);
290 } 319 }
291 320
292 static int 321 static int
293 json_decode_array(js_read_T *reader, typval_T *res) 322 json_decode_array(js_read_T *reader, typval_T *res, int options)
294 { 323 {
295 char_u *p; 324 char_u *p;
296 typval_T item; 325 typval_T item;
297 listitem_T *li; 326 listitem_T *li;
298 int ret; 327 int ret;
315 { 344 {
316 ++reader->js_used; /* consume the ']' */ 345 ++reader->js_used; /* consume the ']' */
317 break; 346 break;
318 } 347 }
319 348
320 ret = json_decode_item(reader, res == NULL ? NULL : &item); 349 ret = json_decode_item(reader, res == NULL ? NULL : &item, options);
321 if (ret != OK) 350 if (ret != OK)
322 return ret; 351 return ret;
323 if (res != NULL) 352 if (res != NULL)
324 { 353 {
325 li = listitem_alloc(); 354 li = listitem_alloc();
345 } 374 }
346 return OK; 375 return OK;
347 } 376 }
348 377
349 static int 378 static int
350 json_decode_object(js_read_T *reader, typval_T *res) 379 json_decode_object(js_read_T *reader, typval_T *res, int options)
351 { 380 {
352 char_u *p; 381 char_u *p;
353 typval_T tvkey; 382 typval_T tvkey;
354 typval_T item; 383 typval_T item;
355 dictitem_T *di; 384 dictitem_T *di;
375 { 404 {
376 ++reader->js_used; /* consume the '}' */ 405 ++reader->js_used; /* consume the '}' */
377 break; 406 break;
378 } 407 }
379 408
380 ret = json_decode_item(reader, res == NULL ? NULL : &tvkey); 409 if ((options & JSON_JS) && reader->js_buf[reader->js_used] != '"')
381 if (ret != OK) 410 {
382 return ret; 411 /* accept a key that is not in quotes */
383 if (res != NULL) 412 key = p = reader->js_buf + reader->js_used;
384 { 413 while (*p != NUL && *p != ':' && *p > ' ')
385 key = get_tv_string_buf_chk(&tvkey, buf); 414 ++p;
386 if (key == NULL || *key == NUL) 415 tvkey.v_type = VAR_STRING;
387 { 416 tvkey.vval.v_string = vim_strnsave(key, (int)(p - key));
388 clear_tv(&tvkey); 417 reader->js_used += (int)(p - key);
389 return FAIL; 418 key = tvkey.vval.v_string;
419 }
420 else
421 {
422 ret = json_decode_item(reader, res == NULL ? NULL : &tvkey,
423 options);
424 if (ret != OK)
425 return ret;
426 if (res != NULL)
427 {
428 key = get_tv_string_buf_chk(&tvkey, buf);
429 if (key == NULL || *key == NUL)
430 {
431 clear_tv(&tvkey);
432 return FAIL;
433 }
390 } 434 }
391 } 435 }
392 436
393 json_skip_white(reader); 437 json_skip_white(reader);
394 p = reader->js_buf + reader->js_used; 438 p = reader->js_buf + reader->js_used;
401 return FAIL; 445 return FAIL;
402 } 446 }
403 ++reader->js_used; 447 ++reader->js_used;
404 json_skip_white(reader); 448 json_skip_white(reader);
405 449
406 ret = json_decode_item(reader, res == NULL ? NULL : &item); 450 ret = json_decode_item(reader, res == NULL ? NULL : &item, options);
407 if (ret != OK) 451 if (ret != OK)
408 { 452 {
409 if (res != NULL) 453 if (res != NULL)
410 clear_tv(&tvkey); 454 clear_tv(&tvkey);
411 return ret; 455 return ret;
567 * 611 *
568 * Return FAIL for a decoding error. 612 * Return FAIL for a decoding error.
569 * Return MAYBE for an incomplete message. 613 * Return MAYBE for an incomplete message.
570 */ 614 */
571 static int 615 static int
572 json_decode_item(js_read_T *reader, typval_T *res) 616 json_decode_item(js_read_T *reader, typval_T *res, int options)
573 { 617 {
574 char_u *p; 618 char_u *p;
575 int len; 619 int len;
576 620
577 fill_numbuflen(reader); 621 fill_numbuflen(reader);
578 p = reader->js_buf + reader->js_used; 622 p = reader->js_buf + reader->js_used;
579 switch (*p) 623 switch (*p)
580 { 624 {
581 case '[': /* array */ 625 case '[': /* array */
582 return json_decode_array(reader, res); 626 return json_decode_array(reader, res, options);
583 627
584 case '{': /* object */ 628 case '{': /* object */
585 return json_decode_object(reader, res); 629 return json_decode_object(reader, res, options);
586 630
587 case '"': /* string */ 631 case '"': /* string */
588 return json_decode_string(reader, res); 632 return json_decode_string(reader, res);
589 633
590 case ',': /* comma: empty item */ 634 case ',': /* comma: empty item */
635 if ((options & JSON_JS) == 0)
636 return FAIL;
637 /* FALLTHROUGH */
591 case NUL: /* empty */ 638 case NUL: /* empty */
592 if (res != NULL) 639 if (res != NULL)
593 { 640 {
594 res->v_type = VAR_SPECIAL; 641 res->v_type = VAR_SPECIAL;
595 res->vval.v_number = VVAL_NONE; 642 res->vval.v_number = VVAL_NONE;
689 return FAIL; 736 return FAIL;
690 } 737 }
691 738
692 /* 739 /*
693 * Decode the JSON from "reader" and store the result in "res". 740 * Decode the JSON from "reader" and store the result in "res".
741 * "options" can be JSON_JS or zero;
694 * Return FAIL if not the whole message was consumed. 742 * Return FAIL if not the whole message was consumed.
695 */ 743 */
696 int 744 int
697 json_decode_all(js_read_T *reader, typval_T *res) 745 json_decode_all(js_read_T *reader, typval_T *res, int options)
698 { 746 {
699 int ret; 747 int ret;
700 748
701 /* We get the end once, to avoid calling strlen() many times. */ 749 /* We find the end once, to avoid calling strlen() many times. */
702 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 750 reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
703 json_skip_white(reader); 751 json_skip_white(reader);
704 ret = json_decode_item(reader, res); 752 ret = json_decode_item(reader, res, options);
705 if (ret != OK) 753 if (ret != OK)
706 return FAIL; 754 return FAIL;
707 json_skip_white(reader); 755 json_skip_white(reader);
708 if (reader->js_buf[reader->js_used] != NUL) 756 if (reader->js_buf[reader->js_used] != NUL)
709 return FAIL; 757 return FAIL;
710 return OK; 758 return OK;
711 } 759 }
712 760
713 /* 761 /*
714 * Decode the JSON from "reader" and store the result in "res". 762 * Decode the JSON from "reader" and store the result in "res".
763 * "options" can be JSON_JS or zero;
715 * Return FAIL if the message has a decoding error or the message is 764 * Return FAIL if the message has a decoding error or the message is
716 * truncated. Consumes the message anyway. 765 * truncated. Consumes the message anyway.
717 */ 766 */
718 int 767 int
719 json_decode(js_read_T *reader, typval_T *res) 768 json_decode(js_read_T *reader, typval_T *res, int options)
720 { 769 {
721 int ret; 770 int ret;
722 771
723 /* We get the end once, to avoid calling strlen() many times. */ 772 /* We find the end once, to avoid calling strlen() many times. */
724 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 773 reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
725 json_skip_white(reader); 774 json_skip_white(reader);
726 ret = json_decode_item(reader, res); 775 ret = json_decode_item(reader, res, options);
727 json_skip_white(reader); 776 json_skip_white(reader);
728 777
729 return ret == OK ? OK : FAIL; 778 return ret == OK ? OK : FAIL;
730 } 779 }
731 780
732 /* 781 /*
733 * Decode the JSON from "reader" to find the end of the message. 782 * Decode the JSON from "reader" to find the end of the message.
783 * "options" can be JSON_JS or zero;
734 * Return FAIL if the message has a decoding error. 784 * Return FAIL if the message has a decoding error.
735 * Return MAYBE if the message is truncated, need to read more. 785 * Return MAYBE if the message is truncated, need to read more.
736 * This only works reliable if the message contains an object, array or 786 * This only works reliable if the message contains an object, array or
737 * string. A number might be trucated without knowing. 787 * string. A number might be trucated without knowing.
738 * Does not advance the reader. 788 * Does not advance the reader.
739 */ 789 */
740 int 790 int
741 json_find_end(js_read_T *reader) 791 json_find_end(js_read_T *reader, int options)
742 { 792 {
743 int used_save = reader->js_used; 793 int used_save = reader->js_used;
744 int ret; 794 int ret;
745 795
746 /* We get the end once, to avoid calling strlen() many times. */ 796 /* We find the end once, to avoid calling strlen() many times. */
747 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 797 reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
748 json_skip_white(reader); 798 json_skip_white(reader);
749 ret = json_decode_item(reader, NULL); 799 ret = json_decode_item(reader, NULL, options);
750 reader->js_used = used_save; 800 reader->js_used = used_save;
751 return ret; 801 return ret;
752 } 802 }
753 #endif 803 #endif