ReactOS 0.4.17-dev-357-ga8f14ff
json.c
Go to the documentation of this file.
1/*
2 * Copyright 2016 Jacek Caban for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#ifdef __REACTOS__
20#include <wine/config.h>
21#include <wine/port.h>
22#endif
23
24#include <math.h>
25#include <assert.h>
26
27#include "jscript.h"
28#include "parser.h"
29
30#include "wine/debug.h"
31
33
34typedef struct {
35 const WCHAR *ptr;
36 const WCHAR *end;
39
41{
42 return c == ' ' || c == '\t' || c == '\n' || c == '\r';
43}
44
46{
47 while(is_json_space(*ctx->ptr))
48 ctx->ptr++;
49 return *ctx->ptr;
50}
51
53{
54 unsigned i;
55 for(i=0; keyword[i]; i++) {
56 if(!ctx->ptr[i] || keyword[i] != ctx->ptr[i])
57 return FALSE;
58 }
59 if(is_identifier_char(ctx->ptr[i]))
60 return FALSE;
61 ctx->ptr += i;
62 return TRUE;
63}
64
66{
67 WCHAR *pd, *p, c, *end = str + *len;
68 int i;
69
70 pd = p = str;
71 while(p < end) {
72 if(*p != '\\') {
73 *pd++ = *p++;
74 continue;
75 }
76
77 if(++p == end)
78 return FALSE;
79
80 switch(*p) {
81 case '\"':
82 case '\\':
83 case '/':
84 c = *p;
85 break;
86 case 'b':
87 c = '\b';
88 break;
89 case 't':
90 c = '\t';
91 break;
92 case 'n':
93 c = '\n';
94 break;
95 case 'f':
96 c = '\f';
97 break;
98 case 'r':
99 c = '\r';
100 break;
101 case 'u':
102 if(p + 4 >= end)
103 return FALSE;
104 i = hex_to_int(*++p);
105 if(i == -1)
106 return FALSE;
107 c = i << 12;
108
109 i = hex_to_int(*++p);
110 if(i == -1)
111 return FALSE;
112 c += i << 8;
113
114 i = hex_to_int(*++p);
115 if(i == -1)
116 return FALSE;
117 c += i << 4;
118
119 i = hex_to_int(*++p);
120 if(i == -1)
121 return FALSE;
122 c += i;
123 break;
124 default:
125 return FALSE;
126 }
127
128 *pd++ = c;
129 p++;
130 }
131
132 *len = pd - str;
133 return TRUE;
134}
135
136/* ECMA-262 5.1 Edition 15.12.1.1 */
138{
139 const WCHAR *ptr = ++ctx->ptr;
140 size_t len;
141 WCHAR *buf;
142
143 while(*ctx->ptr && *ctx->ptr != '"') {
144 if(*ctx->ptr++ == '\\')
145 ctx->ptr++;
146 }
147 if(!*ctx->ptr) {
148 FIXME("unterminated string\n");
149 return E_FAIL;
150 }
151
152 len = ctx->ptr-ptr;
153 buf = malloc((len+1)*sizeof(WCHAR));
154 if(!buf)
155 return E_OUTOFMEMORY;
156 if(len)
157 memcpy(buf, ptr, len*sizeof(WCHAR));
158
159 if(!(ctx->ctx->html_mode ? unescape_json_string(buf, &len) : unescape(buf, &len))) {
160 WARN("unescape failed\n");
161 free(buf);
162 return JS_E_INVALID_CHAR;
163 }
164
165 buf[len] = 0;
166 ctx->ptr++;
167 *r = buf;
168 return S_OK;
169}
170
171/* ECMA-262 5.1 Edition 15.12.1.2 */
173{
175
176 switch(skip_spaces(ctx)) {
177
178 /* JSONNullLiteral */
179 case 'n':
180 if(!is_keyword(ctx, L"null"))
181 break;
182 *r = jsval_null();
183 return S_OK;
184
185 /* JSONBooleanLiteral */
186 case 't':
187 if(!is_keyword(ctx, L"true"))
188 break;
189 *r = jsval_bool(TRUE);
190 return S_OK;
191 case 'f':
192 if(!is_keyword(ctx, L"false"))
193 break;
194 *r = jsval_bool(FALSE);
195 return S_OK;
196
197 /* JSONObject */
198 case '{': {
199 WCHAR *prop_name;
200 jsdisp_t *obj;
201 jsval_t val;
202
204 if(FAILED(hres))
205 return hres;
206
207 ctx->ptr++;
208 if(skip_spaces(ctx) == '}') {
209 ctx->ptr++;
210 *r = jsval_obj(obj);
211 return S_OK;
212 }
213
214 while(1) {
215 if(*ctx->ptr != '"')
216 break;
217 hres = parse_json_string(ctx, &prop_name);
218 if(FAILED(hres))
219 break;
220
221 if(skip_spaces(ctx) != ':') {
222 FIXME("missing ':'\n");
223 free(prop_name);
224 break;
225 }
226
227 ctx->ptr++;
229 if(SUCCEEDED(hres)) {
230 hres = jsdisp_propput_name(obj, prop_name, val);
232 }
233 free(prop_name);
234 if(FAILED(hres))
235 break;
236
237 if(skip_spaces(ctx) == '}') {
238 ctx->ptr++;
239 *r = jsval_obj(obj);
240 return S_OK;
241 }
242
243 if(*ctx->ptr++ != ',') {
244 FIXME("expected ','\n");
245 break;
246 }
248 }
249
251 break;
252 }
253
254 /* JSONString */
255 case '"': {
256 WCHAR *string;
257 jsstr_t *str;
258
259 hres = parse_json_string(ctx, &string);
260 if(FAILED(hres))
261 return hres;
262
263 /* FIXME: avoid reallocation */
264 str = jsstr_alloc(string);
265 free(string);
266 if(!str)
267 return E_OUTOFMEMORY;
268
269 *r = jsval_string(str);
270 return S_OK;
271 }
272
273 /* JSONArray */
274 case '[': {
276 unsigned i = 0;
277 jsval_t val;
278
279 hres = create_array(ctx->ctx, 0, &array);
280 if(FAILED(hres))
281 return hres;
282
283 ctx->ptr++;
284 if(skip_spaces(ctx) == ']') {
285 ctx->ptr++;
286 *r = jsval_obj(array);
287 return S_OK;
288 }
289
290 while(1) {
292 if(FAILED(hres))
293 break;
294
297 if(FAILED(hres))
298 break;
299
300 if(skip_spaces(ctx) == ']') {
301 ctx->ptr++;
302 *r = jsval_obj(array);
303 return S_OK;
304 }
305
306 if(*ctx->ptr != ',') {
307 FIXME("expected ','\n");
308 break;
309 }
310
311 ctx->ptr++;
312 i++;
313 }
314
316 break;
317 }
318
319 /* JSONNumber */
320 default: {
321 int sign = 1;
322 double n;
323
324 if(*ctx->ptr == '-') {
325 sign = -1;
326 ctx->ptr++;
328 }
329
330 if(*ctx->ptr == '0' && ctx->ptr + 1 < ctx->end && is_digit(ctx->ptr[1]))
331 break;
332
333 hres = parse_decimal(&ctx->ptr, ctx->end, &n);
334 if(FAILED(hres))
335 break;
336
337 *r = jsval_number(sign*n);
338 return S_OK;
339 }
340 }
341
342 FIXME("Syntax error at %s\n", debugstr_w(ctx->ptr));
343 return E_FAIL;
344}
345
347{
351};
352
354{
355 jsval_t res, args[2];
356 const WCHAR *str;
357
358 if(!(str = jsstr_flatten(name)))
359 proc_ctx->hres = E_OUTOFMEMORY;
360 else
361 proc_ctx->hres = jsdisp_propget_name(holder, str, &args[1]);
362 if(FAILED(proc_ctx->hres))
363 return jsval_undefined();
364
365 if(is_object_instance(args[1])) {
367 jsstr_t *jsstr;
368 DISPID id;
369 BOOL b;
370
371 if(!obj) {
372 FIXME("non-JS obj in JSON object: %p\n", get_object(args[1]));
373 proc_ctx->hres = E_NOTIMPL;
374 goto ret;
375 }else if(is_class(obj, JSCLASS_ARRAY)) {
376 unsigned i, length = array_get_length(obj);
377 WCHAR buf[14], *buf_end;
378
379 buf_end = buf + ARRAY_SIZE(buf) - 1;
380 *buf_end-- = 0;
381 for(i = 0; i < length; i++) {
382 str = idx_to_str(i, buf_end);
383 if(!(jsstr = jsstr_alloc(str))) {
384 proc_ctx->hres = E_OUTOFMEMORY;
385 goto ret;
386 }
387 res = transform_json_object(proc_ctx, obj, jsstr);
388 jsstr_release(jsstr);
389 if(is_undefined(res)) {
390 if(FAILED(proc_ctx->hres))
391 goto ret;
392 if(FAILED(jsdisp_get_id(obj, str, 0, &id)))
393 continue;
394 proc_ctx->hres = disp_delete(to_disp(obj), id, &b);
395 }else {
398 }
399 if(FAILED(proc_ctx->hres))
400 goto ret;
401 }
402 }else {
403 id = DISPID_STARTENUM;
404 for(;;) {
406 if(proc_ctx->hres == S_FALSE)
407 break;
408 if(FAILED(proc_ctx->hres) || FAILED(proc_ctx->hres = jsdisp_get_prop_name(obj, id, &jsstr)))
409 goto ret;
410 res = transform_json_object(proc_ctx, obj, jsstr);
411 if(is_undefined(res)) {
412 if(SUCCEEDED(proc_ctx->hres))
413 proc_ctx->hres = disp_delete(to_disp(obj), id, &b);
414 }else {
415 if(!(str = jsstr_flatten(jsstr)))
416 proc_ctx->hres = E_OUTOFMEMORY;
417 else
420 }
421 jsstr_release(jsstr);
422 if(FAILED(proc_ctx->hres))
423 goto ret;
424 }
425 }
426 }
427
428 args[0] = jsval_string(name);
429 proc_ctx->hres = disp_call_value(proc_ctx->ctx, proc_ctx->reviver, jsval_obj(holder),
431ret:
433 return FAILED(proc_ctx->hres) ? jsval_undefined() : res;
434}
435
436/* ECMA-262 5.1 Edition 15.12.2 */
438{
439 json_parse_ctx_t parse_ctx;
440 const WCHAR *buf;
441 jsdisp_t *root;
442 jsstr_t *str;
443 jsval_t ret;
445
446 hres = to_flat_string(ctx, argv[0], &str, &buf);
447 if(FAILED(hres))
448 return hres;
449
450 TRACE("%s\n", debugstr_w(buf));
451
452 parse_ctx.ptr = buf;
453 parse_ctx.end = buf + jsstr_length(str);
454 parse_ctx.ctx = ctx;
455 hres = parse_json_value(&parse_ctx, &ret);
456 if(SUCCEEDED(hres) && skip_spaces(&parse_ctx)) {
457 FIXME("syntax error\n");
459 hres = E_FAIL;
460 }
462 if(FAILED(hres))
463 return hres;
464
465 /* FIXME: check IsCallable */
466 if(argc > 1 && is_object_instance(argv[1])) {
468 if(FAILED(hres)) {
470 return hres;
471 }
474
475 if(SUCCEEDED(hres)) {
476 struct transform_json_object_ctx proc_ctx = { ctx, get_object(argv[1]), S_OK };
477
478 str = jsstr_empty();
479 ret = transform_json_object(&proc_ctx, root, str);
481 hres = proc_ctx.hres;
482 }
484 if(FAILED(hres))
485 return hres;
486 }
487
488 if(r)
489 *r = ret;
490 else
492 return S_OK;
493}
494
495typedef struct {
497
499 size_t buf_size;
500 size_t buf_len;
501
503 size_t stack_top;
505
506 WCHAR gap[11]; /* according to the spec, it's no longer than 10 chars */
507
510
512{
513 if(!ctx->stack_size) {
514 ctx->stack = malloc(4*sizeof(*ctx->stack));
515 if(!ctx->stack)
516 return FALSE;
517 ctx->stack_size = 4;
518 }else if(ctx->stack_top == ctx->stack_size) {
519 jsdisp_t **new_stack;
520
521 new_stack = realloc(ctx->stack, ctx->stack_size*2*sizeof(*ctx->stack));
522 if(!new_stack)
523 return FALSE;
524 ctx->stack = new_stack;
525 ctx->stack_size *= 2;
526 }
527
528 ctx->stack[ctx->stack_top++] = obj;
529 return TRUE;
530}
531
533{
534 ctx->stack_top--;
535}
536
538{
539 size_t i = ctx->stack_top;
540 while(i--) {
541 if(ctx->stack[i] == obj)
542 return TRUE;
543 }
544 return FALSE;
545}
546
548{
549 if(!ctx->buf_size) {
550 ctx->buf = malloc(len*2*sizeof(WCHAR));
551 if(!ctx->buf)
552 return FALSE;
553 ctx->buf_size = len*2;
554 }else if(ctx->buf_len + len > ctx->buf_size) {
555 WCHAR *new_buf;
556 size_t new_size;
557
558 new_size = ctx->buf_size * 2 + len;
559 new_buf = realloc(ctx->buf, new_size*sizeof(WCHAR));
560 if(!new_buf)
561 return FALSE;
562 ctx->buf = new_buf;
563 ctx->buf_size = new_size;
564 }
565
566 if(len)
567 memcpy(ctx->buf + ctx->buf_len, str, len*sizeof(WCHAR));
568 ctx->buf_len += len;
569 return TRUE;
570}
571
573{
575}
576
578{
579 return append_string_len(ctx, &c, 1);
580}
581
583{
584 WCHAR str[] = {'\\',c};
585 return append_string_len(ctx, str, 2);
586}
587
589{
590 jsdisp_t *obj;
592
594 return jsval_copy(val, r);
595
597 double n;
598 hres = to_number(ctx, val, &n);
600 if(SUCCEEDED(hres))
601 *r = jsval_number(n);
602 return hres;
603 }
604
606 jsstr_t *str;
607 hres = to_string(ctx, val, &str);
609 if(SUCCEEDED(hres))
610 *r = jsval_string(str);
611 return hres;
612 }
613
617 return S_OK;
618 }
619
620 *r = jsval_obj(obj);
621 return S_OK;
622}
623
624/* ECMA-262 5.1 Edition 15.12.3 (abstract operation Quote) */
626{
627 if(!ptr || !append_char(ctx, '"'))
628 return E_OUTOFMEMORY;
629
630 while(len--) {
631 switch(*ptr) {
632 case '"':
633 case '\\':
635 return E_OUTOFMEMORY;
636 break;
637 case '\b':
638 if(!append_simple_quote(ctx, 'b'))
639 return E_OUTOFMEMORY;
640 break;
641 case '\f':
642 if(!append_simple_quote(ctx, 'f'))
643 return E_OUTOFMEMORY;
644 break;
645 case '\n':
646 if(!append_simple_quote(ctx, 'n'))
647 return E_OUTOFMEMORY;
648 break;
649 case '\r':
650 if(!append_simple_quote(ctx, 'r'))
651 return E_OUTOFMEMORY;
652 break;
653 case '\t':
654 if(!append_simple_quote(ctx, 't'))
655 return E_OUTOFMEMORY;
656 break;
657 default:
658 if(*ptr < ' ') {
659 WCHAR buf[7];
660 swprintf(buf, ARRAY_SIZE(buf), L"\\u%04x", *ptr);
661 if(!append_string(ctx, buf))
662 return E_OUTOFMEMORY;
663 }else {
664 if(!append_char(ctx, *ptr))
665 return E_OUTOFMEMORY;
666 }
667 }
668 ptr++;
669 }
670
671 return append_char(ctx, '"') ? S_OK : E_OUTOFMEMORY;
672}
673
675{
677}
678
679static HRESULT stringify(stringify_ctx_t *ctx, jsdisp_t *object, const WCHAR *name);
680
681/* ECMA-262 5.1 Edition 15.12.3 (abstract operation JA) */
683{
684 unsigned length, i, j;
685 WCHAR name[16];
687
688 if(is_on_stack(ctx, obj)) {
689 FIXME("Found a cycle\n");
690 return E_FAIL;
691 }
692
694 return E_OUTOFMEMORY;
695
696 if(!append_char(ctx, '['))
697 return E_OUTOFMEMORY;
698
700
701 for(i=0; i < length; i++) {
702 if(i && !append_char(ctx, ','))
703 return E_OUTOFMEMORY;
704
705 if(*ctx->gap) {
706 if(!append_char(ctx, '\n'))
707 return E_OUTOFMEMORY;
708
709 for(j=0; j < ctx->stack_top; j++) {
710 if(!append_string(ctx, ctx->gap))
711 return E_OUTOFMEMORY;
712 }
713 }
714
717 if(FAILED(hres))
718 return hres;
719 if(hres == S_FALSE && !append_string(ctx, L"null"))
720 return E_OUTOFMEMORY;
721 }
722
723 if((length && *ctx->gap && !append_char(ctx, '\n')) || !append_char(ctx, ']'))
724 return E_OUTOFMEMORY;
725
727 return S_OK;
728}
729
730/* ECMA-262 5.1 Edition 15.12.3 (abstract operation JO) */
732{
733 DISPID dispid = DISPID_STARTENUM;
734 unsigned prop_cnt = 0, i;
735 size_t stepback;
736 BSTR prop_name;
738
739 if(is_on_stack(ctx, obj)) {
740 FIXME("Found a cycle\n");
741 return E_FAIL;
742 }
743
745 return E_OUTOFMEMORY;
746
747 if(!append_char(ctx, '{'))
748 return E_OUTOFMEMORY;
749
750 while((hres = IDispatchEx_GetNextDispID(to_dispex(obj), fdexEnumDefault, dispid, &dispid)) == S_OK) {
751 stepback = ctx->buf_len;
752
753 if(prop_cnt && !append_char(ctx, ',')) {
755 break;
756 }
757
758 if(*ctx->gap) {
759 if(!append_char(ctx, '\n')) {
761 break;
762 }
763
764 for(i=0; i < ctx->stack_top; i++) {
765 if(!append_string(ctx, ctx->gap)) {
767 break;
768 }
769 }
770 }
771
772 hres = IDispatchEx_GetMemberName(to_dispex(obj), dispid, &prop_name);
773 if(FAILED(hres))
774 return hres;
775
776 hres = json_quote(ctx, prop_name, SysStringLen(prop_name));
777 if(FAILED(hres)) {
778 SysFreeString(prop_name);
779 return hres;
780 }
781
782 if(!append_char(ctx, ':') || (*ctx->gap && !append_char(ctx, ' '))) {
783 SysFreeString(prop_name);
784 return E_OUTOFMEMORY;
785 }
786
787 hres = stringify(ctx, obj, prop_name);
788 SysFreeString(prop_name);
789 if(FAILED(hres))
790 return hres;
791
792 if(hres == S_FALSE) {
793 ctx->buf_len = stepback;
794 continue;
795 }
796
797 prop_cnt++;
798 }
799
800 if(prop_cnt && *ctx->gap) {
801 if(!append_char(ctx, '\n'))
802 return E_OUTOFMEMORY;
803
804 for(i=1; i < ctx->stack_top; i++) {
805 if(!append_string(ctx, ctx->gap)) {
807 break;
808 }
809 }
810 }
811
812 if(!append_char(ctx, '}'))
813 return E_OUTOFMEMORY;
814
816 return S_OK;
817}
818
819/* ECMA-262 5.1 Edition 15.12.3 (abstract operation Str) */
821{
822 jsval_t value, v;
824
825 hres = jsdisp_propget_name(object, name, &value);
826 if(FAILED(hres))
827 return hres == DISP_E_UNKNOWNNAME ? S_FALSE : hres;
828
830 jsdisp_t *obj;
831 DISPID id;
832
834 if(!obj) {
836 return S_FALSE;
837 }
838
839 hres = jsdisp_get_id(obj, L"toJSON", 0, &id);
840 if(hres == S_OK)
841 FIXME("Use toJSON.\n");
842 }
843
844 if(ctx->replacer) {
845 jsstr_t *name_str;
846 jsval_t args[2];
847 if(!(name_str = jsstr_alloc(name))) {
849 return E_OUTOFMEMORY;
850 }
851 args[0] = jsval_string(name_str);
852 args[1] = value;
854 jsstr_release(name_str);
856 if(FAILED(hres))
857 return hres;
858 value = v;
859 }
860
861 v = value;
864 if(FAILED(hres))
865 return hres;
866
867 switch(jsval_type(value)) {
868 case JSV_NULL:
870 hres = S_FALSE;
871 else if(!append_string(ctx, L"null"))
873 break;
874 case JSV_BOOL:
875 if(!append_string(ctx, get_bool(value) ? L"true" : L"false"))
877 break;
878 case JSV_STRING: {
880 const WCHAR *ptr = jsstr_flatten(str);
881 if(ptr)
883 else
885 break;
886 }
887 case JSV_NUMBER: {
888 double n = get_number(value);
889 if(isfinite(n)) {
890 const WCHAR *ptr;
891 jsstr_t *str;
892
893 /* FIXME: Optimize. There is no need for jsstr_t here. */
895 if(FAILED(hres))
896 break;
897
899 assert(ptr != NULL);
902 }else {
903 if(!append_string(ctx, L"null"))
905 }
906 break;
907 }
908 case JSV_OBJECT: {
909 jsdisp_t *obj;
910
912 if(!obj) {
913 hres = S_FALSE;
914 break;
915 }
916
917 if(!is_callable(obj))
919 else
920 hres = S_FALSE;
921
923 break;
924 }
925 case JSV_UNDEFINED:
926 hres = S_FALSE;
927 break;
928 case JSV_VARIANT:
929 FIXME("VARIANT\n");
930 hres = E_NOTIMPL;
931 break;
932 }
933
935 return hres;
936}
937
938/* ECMA-262 5.1 Edition 15.12.3 */
940{
941 stringify_ctx_t stringify_ctx = { ctx };
942 jsdisp_t *obj = NULL, *replacer;
944
945 TRACE("\n");
946
947 if(!argc) {
948 if(r)
949 *r = jsval_undefined();
950 return S_OK;
951 }
952
953 if(argc >= 2 && is_object_instance(argv[1]) && (replacer = to_jsdisp(get_object(argv[1])))) {
954 if(is_callable(replacer)) {
955 stringify_ctx.replacer = jsdisp_addref(replacer);
956 }else if(is_class(replacer, JSCLASS_ARRAY)) {
957 FIXME("Array replacer not yet supported\n");
958 return E_NOTIMPL;
959 }
960 }
961
962 if(argc >= 3) {
963 jsval_t space_val;
964
965 hres = maybe_to_primitive(ctx, argv[2], &space_val);
966 if(FAILED(hres))
967 goto fail;
968
969 if(is_number(space_val)) {
970 double n = get_number(space_val);
971 if(n >= 1) {
972 int i, len;
973 if(n > 10)
974 n = 10;
975 len = floor(n);
976 for(i=0; i < len; i++)
977 stringify_ctx.gap[i] = ' ';
978 stringify_ctx.gap[len] = 0;
979 }
980 }else if(is_string(space_val)) {
981 jsstr_t *space_str = get_string(space_val);
982 size_t len = jsstr_length(space_str);
983 if(len > 10)
984 len = 10;
985 jsstr_extract(space_str, 0, len, stringify_ctx.gap);
986 }
987
988 jsval_release(space_val);
989 }
990
992 goto fail;
993 if(FAILED(hres = jsdisp_propput_name(obj, L"", argv[0])))
994 goto fail;
995
996 hres = stringify(&stringify_ctx, obj, L"");
997 if(SUCCEEDED(hres) && r) {
998 assert(!stringify_ctx.stack_top);
999
1000 if(hres == S_OK) {
1001 jsstr_t *ret = jsstr_alloc_len(stringify_ctx.buf, stringify_ctx.buf_len);
1002 if(ret)
1003 *r = jsval_string(ret);
1004 else
1006 }else {
1007 *r = jsval_undefined();
1008 }
1009 }
1010
1011fail:
1012 if(obj)
1014 if(stringify_ctx.replacer)
1015 jsdisp_release(stringify_ctx.replacer);
1016 free(stringify_ctx.buf);
1017 free(stringify_ctx.stack);
1018 return hres;
1019}
1020
1021static const builtin_prop_t JSON_props[] = {
1022 {L"parse", JSON_parse, PROPF_METHOD|2},
1023 {L"stringify", JSON_stringify, PROPF_METHOD|3}
1024};
1025
1028 .props_cnt = ARRAY_SIZE(JSON_props),
1029 .props = JSON_props,
1030};
1031
1033{
1034 jsdisp_t *json;
1035 HRESULT hres;
1036
1037 json = calloc(1, sizeof(*json));
1038 if(!json)
1039 return E_OUTOFMEMORY;
1040
1041 hres = init_dispex_from_constr(json, ctx, &JSON_info, ctx->object_constr);
1042 if(FAILED(hres)) {
1043 free(json);
1044 return hres;
1045 }
1046
1047 *ret = json;
1048 return S_OK;
1049}
HRESULT create_array(script_ctx_t *ctx, DWORD length, jsdisp_t **ret)
Definition: array.c:1780
WCHAR * idx_to_str(DWORD idx, WCHAR *ptr)
Definition: array.c:100
unsigned array_get_length(jsdisp_t *array)
Definition: array.c:50
#define is_digit(c)
Definition: astoll.c:39
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
BOOL bool_obj_value(jsdisp_t *obj)
Definition: bool.c:51
struct _root root
static BOOL get_bool(D3DXPARAMETER_TYPE type, const void *data)
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
OLECHAR * BSTR
Definition: compat.h:2293
#define lstrlenW
Definition: compat.h:750
MonoAssembly int argc
Definition: metahost.c:107
#define assert(_expr)
Definition: assert.h:32
_ACRTIMP wchar_t *__cdecl _itow(int, wchar_t *, int)
Definition: string.c:2140
#define isfinite(x)
Definition: math.h:363
_ACRTIMP double __cdecl floor(double)
Definition: floor.c:18
#define swprintf
Definition: precomp.h:40
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
size_t const new_size
Definition: expand.cpp:66
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
const GLdouble * v
Definition: gl.h:2040
GLuint GLuint end
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble n
Definition: glext.h:7729
GLuint res
Definition: glext.h:9613
const GLubyte * c
Definition: glext.h:8905
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
static HRESULT to_string(VARIANT *src, BSTR *dst)
Definition: host.c:46
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
HRESULT jsdisp_define_data_property(jsdisp_t *obj, const WCHAR *name, unsigned flags, jsval_t value)
Definition: dispex.c:3349
HRESULT jsdisp_propput_name(jsdisp_t *obj, const WCHAR *name, jsval_t val)
Definition: dispex.c:2859
HRESULT jsdisp_get_id(jsdisp_t *jsdisp, const WCHAR *name, DWORD flags, DISPID *id)
Definition: dispex.c:2550
HRESULT init_dispex_from_constr(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *constr)
Definition: dispex.c:2512
HRESULT disp_delete(IDispatch *disp, DISPID id, BOOL *ret)
Definition: dispex.c:3038
jsdisp_t * iface_to_jsdisp(IDispatch *iface)
Definition: dispex.c:2543
HRESULT jsdisp_get_prop_name(jsdisp_t *obj, DISPID id, jsstr_t **r)
Definition: dispex.c:3429
ULONG jsdisp_release(jsdisp_t *obj)
Definition: dispex.c:1911
HRESULT jsdisp_call_value(jsdisp_t *jsfunc, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
Definition: dispex.c:2581
HRESULT jsdisp_propget_name(jsdisp_t *obj, const WCHAR *name, jsval_t *val)
Definition: dispex.c:2946
HRESULT jsdisp_propput_idx(jsdisp_t *obj, DWORD idx, jsval_t val)
Definition: dispex.c:2864
jsdisp_t * jsdisp_addref(jsdisp_t *obj)
Definition: dispex.c:1902
jsdisp_t * to_jsdisp(IDispatch *disp)
Definition: dispex.c:2447
HRESULT jsdisp_next_prop(jsdisp_t *obj, DISPID id, enum jsdisp_enum_type enum_type, DISPID *ret)
Definition: dispex.c:3073
static int hex_to_int(const WCHAR wch)
Definition: global.c:434
HRESULT parse_decimal(const WCHAR **iter, const WCHAR *end, double *ret)
Definition: lex.c:397
BOOL unescape(WCHAR *str, size_t *len)
Definition: lex.c:227
BOOL is_identifier_char(WCHAR c)
Definition: lex.c:83
HRESULT to_flat_string(script_ctx_t *, jsval_t, jsstr_t **, const WCHAR **)
Definition: jsutils.c:846
#define JS_E_INVALID_CHAR
Definition: jscript.h:542
HRESULT create_object(script_ctx_t *, jsdisp_t *, jsdisp_t **)
Definition: object.c:1131
@ JSDISP_ENUM_OWN_ENUMERABLE
Definition: jscript.h:242
HRESULT double_to_string(double, jsstr_t **)
Definition: jsutils.c:767
static HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
Definition: jscript.h:518
static IDispatch * to_disp(jsdisp_t *jsdisp)
Definition: jscript.h:222
HRESULT to_number(script_ctx_t *, jsval_t, double *)
Definition: jsutils.c:630
static IDispatchEx * to_dispex(jsdisp_t *jsdisp)
Definition: jscript.h:227
@ JSCLASS_JSON
Definition: jscript.h:118
@ JSCLASS_FUNCTION
Definition: jscript.h:109
@ JSCLASS_BOOLEAN
Definition: jscript.h:105
@ JSCLASS_STRING
Definition: jscript.h:115
@ JSCLASS_ARRAY
Definition: jscript.h:104
@ JSCLASS_NUMBER
Definition: jscript.h:112
static BOOL is_class(jsdisp_t *jsdisp, jsclass_t class)
Definition: jscript.h:503
const unsigned int PROPF_WRITABLE
Definition: jsdisp.idl:37
const unsigned int PROPF_ENUMERABLE
Definition: jsdisp.idl:36
const unsigned int PROPF_CONFIGURABLE
Definition: jsdisp.idl:38
const unsigned int PROPF_METHOD
Definition: jsdisp.idl:33
static HRESULT maybe_to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *r)
Definition: json.c:588
static BOOL is_keyword(json_parse_ctx_t *ctx, const WCHAR *keyword)
Definition: json.c:52
static const builtin_prop_t JSON_props[]
Definition: json.c:1021
static BOOL append_string(stringify_ctx_t *ctx, const WCHAR *str)
Definition: json.c:572
static HRESULT JSON_parse(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
Definition: json.c:437
static HRESULT JSON_stringify(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
Definition: json.c:939
static void stringify_pop_obj(stringify_ctx_t *ctx)
Definition: json.c:532
static BOOL is_json_space(WCHAR c)
Definition: json.c:40
HRESULT create_json(script_ctx_t *ctx, jsdisp_t **ret)
Definition: json.c:1032
static HRESULT stringify(stringify_ctx_t *ctx, jsdisp_t *object, const WCHAR *name)
Definition: json.c:820
static BOOL append_string_len(stringify_ctx_t *ctx, const WCHAR *str, size_t len)
Definition: json.c:547
static HRESULT stringify_array(stringify_ctx_t *ctx, jsdisp_t *obj)
Definition: json.c:682
static BOOL append_simple_quote(stringify_ctx_t *ctx, WCHAR c)
Definition: json.c:582
static const builtin_info_t JSON_info
Definition: json.c:1026
static BOOL stringify_push_obj(stringify_ctx_t *ctx, jsdisp_t *obj)
Definition: json.c:511
static HRESULT stringify_object(stringify_ctx_t *ctx, jsdisp_t *obj)
Definition: json.c:731
static BOOL is_callable(jsdisp_t *obj)
Definition: json.c:674
static BOOL append_char(stringify_ctx_t *ctx, WCHAR c)
Definition: json.c:577
static jsval_t transform_json_object(struct transform_json_object_ctx *proc_ctx, jsdisp_t *holder, jsstr_t *name)
Definition: json.c:353
static HRESULT parse_json_string(json_parse_ctx_t *ctx, WCHAR **r)
Definition: json.c:137
static WCHAR skip_spaces(json_parse_ctx_t *ctx)
Definition: json.c:45
static HRESULT parse_json_value(json_parse_ctx_t *ctx, jsval_t *r)
Definition: json.c:172
static HRESULT json_quote(stringify_ctx_t *ctx, const WCHAR *ptr, size_t len)
Definition: json.c:625
static BOOL is_on_stack(stringify_ctx_t *ctx, jsdisp_t *obj)
Definition: json.c:537
static BOOL unescape_json_string(WCHAR *str, size_t *len)
Definition: json.c:65
jsstr_t * jsstr_alloc_len(const WCHAR *buf, unsigned len)
Definition: jsstr.c:86
jsstr_t * jsstr_empty(void)
Definition: jsstr.c:291
void jsstr_extract(jsstr_t *str, unsigned off, unsigned len, WCHAR *buf)
Definition: jsstr.c:113
static const WCHAR * jsstr_flatten(jsstr_t *str)
Definition: jsstr.h:136
static void jsstr_release(jsstr_t *str)
Definition: jsstr.h:107
static unsigned jsstr_length(jsstr_t *str)
Definition: jsstr.h:55
static jsstr_t * jsstr_alloc(const WCHAR *str)
Definition: jsstr.h:100
HRESULT jsval_copy(jsval_t v, jsval_t *r)
Definition: jsutils.c:225
void jsval_release(jsval_t val)
Definition: jsutils.c:186
static BOOL is_number(jsval_t v)
Definition: jsval.h:200
@ JSV_STRING
Definition: jsval.h:48
@ JSV_NUMBER
Definition: jsval.h:49
@ JSV_VARIANT
Definition: jsval.h:51
@ JSV_OBJECT
Definition: jsval.h:47
@ JSV_NULL
Definition: jsval.h:46
@ JSV_UNDEFINED
Definition: jsval.h:45
@ JSV_BOOL
Definition: jsval.h:50
static jsval_t jsval_null(void)
Definition: jsval.h:130
static jsval_t jsval_string(jsstr_t *str)
Definition: jsval.h:109
static jsval_t jsval_undefined(void)
Definition: jsval.h:146
static jsval_t jsval_obj(jsdisp_t *obj)
Definition: jsval.h:125
static jsval_t jsval_bool(BOOL b)
Definition: jsval.h:101
static jsval_type_t jsval_type(jsval_t v)
Definition: jsval.h:219
static BOOL is_null_disp(jsval_t v)
Definition: jsval.h:190
static jsstr_t * get_string(jsval_t v)
Definition: jsval.h:238
static BOOL is_undefined(jsval_t v)
Definition: jsval.h:180
static double get_number(jsval_t v)
Definition: jsval.h:233
static IDispatch * get_object(jsval_t v)
Definition: jsval.h:228
static BOOL is_object_instance(jsval_t v)
Definition: jsval.h:175
static jsval_t jsval_number(double n)
Definition: jsval.h:153
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
#define debugstr_w
Definition: kernel32.h:32
#define sign(x)
Definition: mapdesc.cc:613
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
char string[160]
Definition: util.h:11
static PVOID ptr
Definition: dispmode.c:27
HRESULT hres
Definition: protocol.c:465
static VARIANTARG static DISPID
Definition: ordinal.c:49
#define argv
Definition: mplay32.c:18
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:196
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
#define DISPATCH_METHOD
Definition: oleauto.h:1006
static BOOL is_string(parse_buffer *buf)
Definition: parsing.c:600
short WCHAR
Definition: pedump.c:58
#define calloc
Definition: rosglue.h:14
const WCHAR * str
#define TRACE(s)
Definition: solgame.cpp:4
Definition: jsstr.h:36
Definition: jsval.h:54
Definition: match.c:390
Definition: undname.c:54
jsclass_t class
Definition: jscript.h:183
const WCHAR * ptr
Definition: json.c:35
script_ctx_t * ctx
Definition: json.c:37
const WCHAR * end
Definition: json.c:36
Definition: name.c:39
size_t buf_size
Definition: json.c:499
size_t stack_size
Definition: json.c:504
script_ctx_t * ctx
Definition: json.c:496
WCHAR gap[11]
Definition: json.c:506
size_t stack_top
Definition: json.c:503
WCHAR * buf
Definition: json.c:498
size_t buf_len
Definition: json.c:500
jsdisp_t ** stack
Definition: json.c:502
jsdisp_t * replacer
Definition: json.c:508
script_ctx_t * ctx
Definition: json.c:348
IDispatch * reviver
Definition: json.c:349
CONTEXT ctx
Definition: pdh_main.c:96
#define S_FALSE
Definition: winerror.h:3451
#define DISP_E_UNKNOWNNAME
Definition: winerror.h:3618