ReactOS 0.4.15-dev-7788-g1ad9096
json.c File Reference
#include <math.h>
#include <assert.h>
#include "jscript.h"
#include "parser.h"
#include "wine/debug.h"
Include dependency graph for json.c:

Go to the source code of this file.

Classes

struct  json_parse_ctx_t
 
struct  stringify_ctx_t
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (jscript)
 
static BOOL is_json_space (WCHAR c)
 
static WCHAR skip_spaces (json_parse_ctx_t *ctx)
 
static BOOL is_keyword (json_parse_ctx_t *ctx, const WCHAR *keyword)
 
static HRESULT parse_json_string (json_parse_ctx_t *ctx, WCHAR **r)
 
static HRESULT parse_json_value (json_parse_ctx_t *ctx, jsval_t *r)
 
static HRESULT JSON_parse (script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
 
static BOOL stringify_push_obj (stringify_ctx_t *ctx, jsdisp_t *obj)
 
static void stringify_pop_obj (stringify_ctx_t *ctx)
 
static BOOL is_on_stack (stringify_ctx_t *ctx, jsdisp_t *obj)
 
static BOOL append_string_len (stringify_ctx_t *ctx, const WCHAR *str, size_t len)
 
static BOOL append_string (stringify_ctx_t *ctx, const WCHAR *str)
 
static BOOL append_char (stringify_ctx_t *ctx, WCHAR c)
 
static BOOL append_simple_quote (stringify_ctx_t *ctx, WCHAR c)
 
static HRESULT maybe_to_primitive (script_ctx_t *ctx, jsval_t val, jsval_t *r)
 
static HRESULT json_quote (stringify_ctx_t *ctx, const WCHAR *ptr, size_t len)
 
static BOOL is_callable (jsdisp_t *obj)
 
static HRESULT stringify (stringify_ctx_t *ctx, jsval_t val)
 
static HRESULT stringify_array (stringify_ctx_t *ctx, jsdisp_t *obj)
 
static HRESULT stringify_object (stringify_ctx_t *ctx, jsdisp_t *obj)
 
static HRESULT JSON_stringify (script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
 
HRESULT create_json (script_ctx_t *ctx, jsdisp_t **ret)
 

Variables

static const WCHAR parseW [] = {'p','a','r','s','e',0}
 
static const WCHAR stringifyW [] = {'s','t','r','i','n','g','i','f','y',0}
 
static const WCHAR nullW [] = {'n','u','l','l',0}
 
static const WCHAR trueW [] = {'t','r','u','e',0}
 
static const WCHAR falseW [] = {'f','a','l','s','e',0}
 
static const WCHAR toJSONW [] = {'t','o','J','S','O','N',0}
 
static const builtin_prop_t JSON_props []
 
static const builtin_info_t JSON_info
 

Function Documentation

◆ append_char()

static BOOL append_char ( stringify_ctx_t ctx,
WCHAR  c 
)
inlinestatic

Definition at line 400 of file json.c.

401{
402 return append_string_len(ctx, &c, 1);
403}
const GLubyte * c
Definition: glext.h:8905
static BOOL append_string_len(stringify_ctx_t *ctx, const WCHAR *str, size_t len)
Definition: json.c:370

Referenced by json_quote(), stringify_array(), and stringify_object().

◆ append_simple_quote()

static BOOL append_simple_quote ( stringify_ctx_t ctx,
WCHAR  c 
)
inlinestatic

Definition at line 405 of file json.c.

406{
407 WCHAR str[] = {'\\',c};
408 return append_string_len(ctx, str, 2);
409}
const WCHAR * str
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by json_quote().

◆ append_string()

static BOOL append_string ( stringify_ctx_t ctx,
const WCHAR str 
)
inlinestatic

Definition at line 395 of file json.c.

396{
398}
#define lstrlenW
Definition: compat.h:750

Referenced by json_quote(), stringify(), stringify_array(), and stringify_object().

◆ append_string_len()

static BOOL append_string_len ( stringify_ctx_t ctx,
const WCHAR str,
size_t  len 
)
static

Definition at line 370 of file json.c.

371{
372 if(!ctx->buf_size) {
373 ctx->buf = heap_alloc(len*2*sizeof(WCHAR));
374 if(!ctx->buf)
375 return FALSE;
376 ctx->buf_size = len*2;
377 }else if(ctx->buf_len + len > ctx->buf_size) {
378 WCHAR *new_buf;
379 size_t new_size;
380
381 new_size = ctx->buf_size * 2 + len;
382 new_buf = heap_realloc(ctx->buf, new_size*sizeof(WCHAR));
383 if(!new_buf)
384 return FALSE;
385 ctx->buf = new_buf;
386 ctx->buf_size = new_size;
387 }
388
389 if(len)
390 memcpy(ctx->buf + ctx->buf_len, str, len*sizeof(WCHAR));
391 ctx->buf_len += len;
392 return TRUE;
393}
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static void * heap_realloc(void *mem, size_t len)
Definition: appwiz.h:71
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
GLenum GLsizei len
Definition: glext.h:6722
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878

Referenced by append_char(), append_simple_quote(), append_string(), and stringify().

◆ create_json()

HRESULT create_json ( script_ctx_t ctx,
jsdisp_t **  ret 
)

Definition at line 837 of file json.c.

838{
839 jsdisp_t *json;
841
842 json = heap_alloc_zero(sizeof(*json));
843 if(!json)
844 return E_OUTOFMEMORY;
845
846 hres = init_dispex_from_constr(json, ctx, &JSON_info, ctx->object_constr);
847 if(FAILED(hres)) {
848 heap_free(json);
849 return hres;
850 }
851
852 *ret = json;
853 return S_OK;
854}
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
HRESULT init_dispex_from_constr(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *constr)
Definition: dispex.c:1030
static const builtin_info_t JSON_info
Definition: json.c:828
HRESULT hres
Definition: protocol.c:465
int ret

Referenced by init_global().

◆ is_callable()

static BOOL is_callable ( jsdisp_t obj)
inlinestatic

Definition at line 498 of file json.c.

499{
501}
@ JSCLASS_FUNCTION
Definition: jscript.h:126
static BOOL is_class(jsdisp_t *jsdisp, jsclass_t class)
Definition: jscript.h:504

Referenced by stringify().

◆ is_json_space()

static BOOL is_json_space ( WCHAR  c)
static

Definition at line 44 of file json.c.

45{
46 return c == ' ' || c == '\t' || c == '\n' || c == '\r';
47}

Referenced by skip_spaces().

◆ is_keyword()

static BOOL is_keyword ( json_parse_ctx_t ctx,
const WCHAR keyword 
)
static

Definition at line 56 of file json.c.

57{
58 unsigned i;
59 for(i=0; keyword[i]; i++) {
60 if(!ctx->ptr[i] || keyword[i] != ctx->ptr[i])
61 return FALSE;
62 }
63 if(is_identifier_char(ctx->ptr[i]))
64 return FALSE;
65 ctx->ptr += i;
66 return TRUE;
67}
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
BOOL is_identifier_char(WCHAR c)
Definition: lex.c:81

Referenced by parse_json_value().

◆ is_on_stack()

static BOOL is_on_stack ( stringify_ctx_t ctx,
jsdisp_t obj 
)
static

Definition at line 360 of file json.c.

361{
362 size_t i = ctx->stack_top;
363 while(i--) {
364 if(ctx->stack[i] == obj)
365 return TRUE;
366 }
367 return FALSE;
368}

Referenced by stringify_array(), and stringify_object().

◆ JSON_parse()

static HRESULT JSON_parse ( script_ctx_t ctx,
vdisp_t jsthis,
WORD  flags,
unsigned  argc,
jsval_t argv,
jsval_t r 
)
static

Definition at line 280 of file json.c.

281{
282 json_parse_ctx_t parse_ctx;
283 const WCHAR *buf;
284 jsstr_t *str;
285 jsval_t ret;
287
288 if(argc != 1) {
289 FIXME("Unsupported args\n");
290 return E_INVALIDARG;
291 }
292
293 hres = to_flat_string(ctx, argv[0], &str, &buf);
294 if(FAILED(hres))
295 return hres;
296
297 TRACE("%s\n", debugstr_w(buf));
298
299 parse_ctx.ptr = buf;
300 parse_ctx.end = buf + jsstr_length(str);
301 parse_ctx.ctx = ctx;
302 hres = parse_json_value(&parse_ctx, &ret);
304 if(FAILED(hres))
305 return hres;
306
307 if(skip_spaces(&parse_ctx)) {
308 FIXME("syntax error\n");
310 return E_FAIL;
311 }
312
313 if(r)
314 *r = ret;
315 else
317 return S_OK;
318}
static int argc
Definition: ServiceArgs.c:12
#define FIXME(fmt,...)
Definition: debug.h:111
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
HRESULT to_flat_string(script_ctx_t *, jsval_t, jsstr_t **, const WCHAR **) DECLSPEC_HIDDEN
Definition: jsutils.c:798
static WCHAR skip_spaces(json_parse_ctx_t *ctx)
Definition: json.c:49
static HRESULT parse_json_value(json_parse_ctx_t *ctx, jsval_t *r)
Definition: json.c:105
static void jsstr_release(jsstr_t *str)
Definition: jsstr.h:110
static unsigned jsstr_length(jsstr_t *str)
Definition: jsstr.h:58
void jsval_release(jsval_t val)
Definition: jsutils.c:191
#define debugstr_w
Definition: kernel32.h:32
#define argv
Definition: mplay32.c:18
#define TRACE(s)
Definition: solgame.cpp:4
Definition: jsstr.h:39
Definition: jsval.h:54
const WCHAR * ptr
Definition: json.c:39
script_ctx_t * ctx
Definition: json.c:41
const WCHAR * end
Definition: json.c:40

◆ json_quote()

static HRESULT json_quote ( stringify_ctx_t ctx,
const WCHAR ptr,
size_t  len 
)
static

Definition at line 448 of file json.c.

449{
450 if(!ptr || !append_char(ctx, '"'))
451 return E_OUTOFMEMORY;
452
453 while(len--) {
454 switch(*ptr) {
455 case '"':
456 case '\\':
458 return E_OUTOFMEMORY;
459 break;
460 case '\b':
461 if(!append_simple_quote(ctx, 'b'))
462 return E_OUTOFMEMORY;
463 break;
464 case '\f':
465 if(!append_simple_quote(ctx, 'f'))
466 return E_OUTOFMEMORY;
467 break;
468 case '\n':
469 if(!append_simple_quote(ctx, 'n'))
470 return E_OUTOFMEMORY;
471 break;
472 case '\r':
473 if(!append_simple_quote(ctx, 'r'))
474 return E_OUTOFMEMORY;
475 break;
476 case '\t':
477 if(!append_simple_quote(ctx, 't'))
478 return E_OUTOFMEMORY;
479 break;
480 default:
481 if(*ptr < ' ') {
482 static const WCHAR formatW[] = {'\\','u','%','0','4','x',0};
483 WCHAR buf[7];
484 swprintf(buf, formatW, *ptr);
485 if(!append_string(ctx, buf))
486 return E_OUTOFMEMORY;
487 }else {
488 if(!append_char(ctx, *ptr))
489 return E_OUTOFMEMORY;
490 }
491 }
492 ptr++;
493 }
494
495 return append_char(ctx, '"') ? S_OK : E_OUTOFMEMORY;
496}
#define swprintf
Definition: precomp.h:40
static BOOL append_string(stringify_ctx_t *ctx, const WCHAR *str)
Definition: json.c:395
static BOOL append_simple_quote(stringify_ctx_t *ctx, WCHAR c)
Definition: json.c:405
static BOOL append_char(stringify_ctx_t *ctx, WCHAR c)
Definition: json.c:400
static PVOID ptr
Definition: dispmode.c:27

Referenced by stringify(), and stringify_object().

◆ JSON_stringify()

static HRESULT JSON_stringify ( script_ctx_t ctx,
vdisp_t jsthis,
WORD  flags,
unsigned  argc,
jsval_t argv,
jsval_t r 
)
static

Definition at line 756 of file json.c.

757{
758 stringify_ctx_t stringify_ctx = {ctx, NULL,0,0, NULL,0,0, {0}};
760
761 TRACE("\n");
762
763 if(!argc) {
764 if(r)
765 *r = jsval_undefined();
766 return S_OK;
767 }
768
769 if(argc >= 2 && is_object_instance(argv[1])) {
770 FIXME("Replacer %s not yet supported\n", debugstr_jsval(argv[1]));
771 return E_NOTIMPL;
772 }
773
774 if(argc >= 3) {
775 jsval_t space_val;
776
777 hres = maybe_to_primitive(ctx, argv[2], &space_val);
778 if(FAILED(hres))
779 return hres;
780
781 if(is_number(space_val)) {
782 double n = get_number(space_val);
783 if(n >= 1) {
784 int i, len;
785 if(n > 10)
786 n = 10;
787 len = floor(n);
788 for(i=0; i < len; i++)
789 stringify_ctx.gap[i] = ' ';
790 stringify_ctx.gap[len] = 0;
791 }
792 }else if(is_string(space_val)) {
793 jsstr_t *space_str = get_string(space_val);
794 size_t len = jsstr_length(space_str);
795 if(len > 10)
796 len = 10;
797 jsstr_extract(space_str, 0, len, stringify_ctx.gap);
798 }
799
800 jsval_release(space_val);
801 }
802
803 hres = stringify(&stringify_ctx, argv[0]);
804 if(SUCCEEDED(hres) && r) {
805 assert(!stringify_ctx.stack_top);
806
807 if(hres == S_OK) {
808 jsstr_t *ret = jsstr_alloc_len(stringify_ctx.buf, stringify_ctx.buf_len);
809 if(ret)
810 *r = jsval_string(ret);
811 else
813 }else {
814 *r = jsval_undefined();
815 }
816 }
817
818 heap_free(stringify_ctx.buf);
819 heap_free(stringify_ctx.stack);
820 return hres;
821}
#define E_NOTIMPL
Definition: ddrawi.h:99
#define NULL
Definition: types.h:112
#define assert(x)
Definition: debug.h:53
GLdouble n
Definition: glext.h:7729
_Check_return_ _CRTIMP double __cdecl floor(_In_ double x)
#define SUCCEEDED(hr)
Definition: intsafe.h:50
const char * debugstr_jsval(const jsval_t) DECLSPEC_HIDDEN
Definition: jsutils.c:35
static HRESULT maybe_to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *r)
Definition: json.c:411
static HRESULT stringify(stringify_ctx_t *ctx, jsval_t val)
Definition: json.c:661
jsstr_t * jsstr_alloc_len(const WCHAR *buf, unsigned len)
Definition: jsstr.c:86
void jsstr_extract(jsstr_t *str, unsigned off, unsigned len, WCHAR *buf)
Definition: jsstr.c:113
static BOOL is_number(jsval_t v)
Definition: jsval.h:191
static jsval_t jsval_string(jsstr_t *str)
Definition: jsval.h:109
static jsval_t jsval_undefined(void)
Definition: jsval.h:137
static jsstr_t * get_string(jsval_t v)
Definition: jsval.h:229
static double get_number(jsval_t v)
Definition: jsval.h:224
static BOOL is_object_instance(jsval_t v)
Definition: jsval.h:166
static BOOL is_string(parse_buffer *buf)
Definition: parsing.c:600
WCHAR gap[11]
Definition: json.c:331
size_t stack_top
Definition: json.c:328
WCHAR * buf
Definition: json.c:323
size_t buf_len
Definition: json.c:325
jsdisp_t ** stack
Definition: json.c:327

◆ maybe_to_primitive()

static HRESULT maybe_to_primitive ( script_ctx_t ctx,
jsval_t  val,
jsval_t r 
)
static

Definition at line 411 of file json.c.

412{
413 jsdisp_t *obj;
415
417 return jsval_copy(val, r);
418
420 double n;
421 hres = to_number(ctx, val, &n);
423 if(SUCCEEDED(hres))
424 *r = jsval_number(n);
425 return hres;
426 }
427
429 jsstr_t *str;
430 hres = to_string(ctx, val, &str);
432 if(SUCCEEDED(hres))
433 *r = jsval_string(str);
434 return hres;
435 }
436
440 return S_OK;
441 }
442
443 *r = jsval_obj(obj);
444 return S_OK;
445}
BOOL bool_obj_value(jsdisp_t *obj)
Definition: bool.c:52
GLuint GLfloat * val
Definition: glext.h:7180
static HRESULT to_string(VARIANT *src, BSTR *dst)
Definition: host.c:47
jsdisp_t * iface_to_jsdisp(IDispatch *iface)
Definition: dispex.c:1060
static void jsdisp_release(jsdisp_t *jsdisp)
Definition: jscript.h:268
HRESULT to_number(script_ctx_t *, jsval_t, double *) DECLSPEC_HIDDEN
Definition: jsutils.c:609
@ JSCLASS_BOOLEAN
Definition: jscript.h:122
@ JSCLASS_STRING
Definition: jscript.h:132
@ JSCLASS_NUMBER
Definition: jscript.h:129
HRESULT jsval_copy(jsval_t v, jsval_t *r)
Definition: jsutils.c:231
static jsval_t jsval_obj(jsdisp_t *obj)
Definition: jsval.h:125
static jsval_t jsval_bool(BOOL b)
Definition: jsval.h:101
static IDispatch * get_object(jsval_t v)
Definition: jsval.h:219
static jsval_t jsval_number(double n)
Definition: jsval.h:144

Referenced by JSON_stringify(), and stringify().

◆ parse_json_string()

static HRESULT parse_json_string ( json_parse_ctx_t ctx,
WCHAR **  r 
)
static

Definition at line 70 of file json.c.

71{
72 const WCHAR *ptr = ++ctx->ptr;
73 size_t len;
74 WCHAR *buf;
75
76 while(*ctx->ptr && *ctx->ptr != '"') {
77 if(*ctx->ptr++ == '\\')
78 ctx->ptr++;
79 }
80 if(!*ctx->ptr) {
81 FIXME("unterminated string\n");
82 return E_FAIL;
83 }
84
85 len = ctx->ptr-ptr;
86 buf = heap_alloc((len+1)*sizeof(WCHAR));
87 if(!buf)
88 return E_OUTOFMEMORY;
89 if(len)
90 memcpy(buf, ptr, len*sizeof(WCHAR));
91
92 if(!unescape(buf, &len)) {
93 FIXME("unescape failed\n");
95 return E_FAIL;
96 }
97
98 buf[len] = 0;
99 ctx->ptr++;
100 *r = buf;
101 return S_OK;
102}
BOOL unescape(WCHAR *str, size_t *len)
Definition: lex.c:227

Referenced by parse_json_value().

◆ parse_json_value()

static HRESULT parse_json_value ( json_parse_ctx_t ctx,
jsval_t r 
)
static

Definition at line 105 of file json.c.

106{
108
109 switch(skip_spaces(ctx)) {
110
111 /* JSONNullLiteral */
112 case 'n':
113 if(!is_keyword(ctx, nullW))
114 break;
115 *r = jsval_null();
116 return S_OK;
117
118 /* JSONBooleanLiteral */
119 case 't':
120 if(!is_keyword(ctx, trueW))
121 break;
122 *r = jsval_bool(TRUE);
123 return S_OK;
124 case 'f':
125 if(!is_keyword(ctx, falseW))
126 break;
127 *r = jsval_bool(FALSE);
128 return S_OK;
129
130 /* JSONObject */
131 case '{': {
132 WCHAR *prop_name;
133 jsdisp_t *obj;
134 jsval_t val;
135
137 if(FAILED(hres))
138 return hres;
139
140 ctx->ptr++;
141 if(skip_spaces(ctx) == '}') {
142 ctx->ptr++;
143 *r = jsval_obj(obj);
144 return S_OK;
145 }
146
147 while(1) {
148 if(*ctx->ptr != '"')
149 break;
150 hres = parse_json_string(ctx, &prop_name);
151 if(FAILED(hres))
152 break;
153
154 if(skip_spaces(ctx) != ':') {
155 FIXME("missing ':'\n");
156 heap_free(prop_name);
157 break;
158 }
159
160 ctx->ptr++;
162 if(SUCCEEDED(hres)) {
163 hres = jsdisp_propput_name(obj, prop_name, val);
165 }
166 heap_free(prop_name);
167 if(FAILED(hres))
168 break;
169
170 if(skip_spaces(ctx) == '}') {
171 ctx->ptr++;
172 *r = jsval_obj(obj);
173 return S_OK;
174 }
175
176 if(*ctx->ptr++ != ',') {
177 FIXME("expected ','\n");
178 break;
179 }
181 }
182
184 break;
185 }
186
187 /* JSONString */
188 case '"': {
189 WCHAR *string;
190 jsstr_t *str;
191
192 hres = parse_json_string(ctx, &string);
193 if(FAILED(hres))
194 return hres;
195
196 /* FIXME: avoid reallocation */
197 str = jsstr_alloc(string);
198 heap_free(string);
199 if(!str)
200 return E_OUTOFMEMORY;
201
202 *r = jsval_string(str);
203 return S_OK;
204 }
205
206 /* JSONArray */
207 case '[': {
209 unsigned i = 0;
210 jsval_t val;
211
212 hres = create_array(ctx->ctx, 0, &array);
213 if(FAILED(hres))
214 return hres;
215
216 ctx->ptr++;
217 if(skip_spaces(ctx) == ']') {
218 ctx->ptr++;
219 *r = jsval_obj(array);
220 return S_OK;
221 }
222
223 while(1) {
225 if(FAILED(hres))
226 break;
227
230 if(FAILED(hres))
231 break;
232
233 if(skip_spaces(ctx) == ']') {
234 ctx->ptr++;
235 *r = jsval_obj(array);
236 return S_OK;
237 }
238
239 if(*ctx->ptr != ',') {
240 FIXME("expected ','\n");
241 break;
242 }
243
244 ctx->ptr++;
245 i++;
246 }
247
249 break;
250 }
251
252 /* JSONNumber */
253 default: {
254 int sign = 1;
255 double n;
256
257 if(*ctx->ptr == '-') {
258 sign = -1;
259 ctx->ptr++;
261 }
262
263 if(*ctx->ptr == '0' && ctx->ptr + 1 < ctx->end && iswdigit(ctx->ptr[1]))
264 break;
265
266 hres = parse_decimal(&ctx->ptr, ctx->end, &n);
267 if(FAILED(hres))
268 break;
269
270 *r = jsval_number(sign*n);
271 return S_OK;
272 }
273 }
274
275 FIXME("Syntax error at %s\n", debugstr_w(ctx->ptr));
276 return E_FAIL;
277}
HRESULT create_array(script_ctx_t *ctx, DWORD length, jsdisp_t **ret)
Definition: array.c:1381
#define iswdigit(_c)
Definition: ctype.h:667
HRESULT jsdisp_propput_name(jsdisp_t *obj, const WCHAR *name, jsval_t val)
Definition: dispex.c:1344
HRESULT jsdisp_propput_idx(jsdisp_t *obj, DWORD idx, jsval_t val)
Definition: dispex.c:1349
HRESULT parse_decimal(const WCHAR **iter, const WCHAR *end, double *ret)
Definition: lex.c:397
HRESULT create_object(script_ctx_t *, jsdisp_t *, jsdisp_t **) DECLSPEC_HIDDEN
Definition: object.c:731
static BOOL is_keyword(json_parse_ctx_t *ctx, const WCHAR *keyword)
Definition: json.c:56
static const WCHAR falseW[]
Definition: json.c:34
static const WCHAR trueW[]
Definition: json.c:33
static const WCHAR nullW[]
Definition: json.c:32
static HRESULT parse_json_string(json_parse_ctx_t *ctx, WCHAR **r)
Definition: json.c:70
static jsstr_t * jsstr_alloc(const WCHAR *str)
Definition: jsstr.h:103
static jsval_t jsval_null(void)
Definition: jsval.h:130
#define sign(x)
Definition: mapdesc.cc:613
char string[160]
Definition: util.h:11
CONTEXT ctx

Referenced by JSON_parse(), and parse_json_value().

◆ skip_spaces()

static WCHAR skip_spaces ( json_parse_ctx_t ctx)
static

Definition at line 49 of file json.c.

50{
51 while(is_json_space(*ctx->ptr))
52 ctx->ptr++;
53 return *ctx->ptr;
54}
static BOOL is_json_space(WCHAR c)
Definition: json.c:44

Referenced by JSON_parse(), and parse_json_value().

◆ stringify()

static HRESULT stringify ( stringify_ctx_t ctx,
jsval_t  val 
)
static

Definition at line 661 of file json.c.

662{
665
667 jsdisp_t *obj;
668 DISPID id;
669
671 if(!obj)
672 return S_FALSE;
673
674 hres = jsdisp_get_id(obj, toJSONW, 0, &id);
676 if(hres == S_OK)
677 FIXME("Use toJSON.\n");
678 }
679
680 /* FIXME: Support replacer replacer. */
681
683 if(FAILED(hres))
684 return hres;
685
686 switch(jsval_type(value)) {
687 case JSV_NULL:
688 if(!append_string(ctx, nullW))
690 break;
691 case JSV_BOOL:
694 break;
695 case JSV_STRING: {
697 const WCHAR *ptr = jsstr_flatten(str);
698 if(ptr)
700 else
702 break;
703 }
704 case JSV_NUMBER: {
705 double n = get_number(value);
706 if(is_finite(n)) {
707 const WCHAR *ptr;
708 jsstr_t *str;
709
710 /* FIXME: Optimize. There is no need for jsstr_t here. */
712 if(FAILED(hres))
713 break;
714
716 assert(ptr != NULL);
719 }else {
720 if(!append_string(ctx, nullW))
722 }
723 break;
724 }
725 case JSV_OBJECT: {
726 jsdisp_t *obj;
727
729 if(!obj) {
730 hres = S_FALSE;
731 break;
732 }
733
734 if(!is_callable(obj))
736 else
737 hres = S_FALSE;
738
740 break;
741 }
742 case JSV_UNDEFINED:
743 hres = S_FALSE;
744 break;
745 case JSV_VARIANT:
746 FIXME("VARIANT\n");
747 hres = E_NOTIMPL;
748 break;
749 }
750
752 return hres;
753}
static BOOL get_bool(D3DXPARAMETER_TYPE type, const void *data)
GLuint id
Definition: glext.h:5910
HRESULT jsdisp_get_id(jsdisp_t *jsdisp, const WCHAR *name, DWORD flags, DISPID *id)
Definition: dispex.c:1067
HRESULT double_to_string(double, jsstr_t **) DECLSPEC_HIDDEN
Definition: jsutils.c:727
BOOL is_finite(double) DECLSPEC_HIDDEN
Definition: jsutils.c:58
@ JSCLASS_ARRAY
Definition: jscript.h:121
static const WCHAR toJSONW[]
Definition: json.c:36
static HRESULT stringify_array(stringify_ctx_t *ctx, jsdisp_t *obj)
Definition: json.c:506
static HRESULT stringify_object(stringify_ctx_t *ctx, jsdisp_t *obj)
Definition: json.c:562
static BOOL is_callable(jsdisp_t *obj)
Definition: json.c:498
static HRESULT json_quote(stringify_ctx_t *ctx, const WCHAR *ptr, size_t len)
Definition: json.c:448
static const WCHAR * jsstr_flatten(jsstr_t *str)
Definition: jsstr.h:139
@ 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_type_t jsval_type(jsval_t v)
Definition: jsval.h:210
static VARIANTARG static DISPID
Definition: ordinal.c:52
Definition: pdh_main.c:94
#define S_FALSE
Definition: winerror.h:2357

Referenced by JSON_stringify(), stringify_array(), and stringify_object().

◆ stringify_array()

static HRESULT stringify_array ( stringify_ctx_t ctx,
jsdisp_t obj 
)
static

Definition at line 506 of file json.c.

507{
508 unsigned length, i, j;
509 jsval_t val;
511
512 if(is_on_stack(ctx, obj)) {
513 FIXME("Found a cycle\n");
514 return E_FAIL;
515 }
516
518 return E_OUTOFMEMORY;
519
520 if(!append_char(ctx, '['))
521 return E_OUTOFMEMORY;
522
524
525 for(i=0; i < length; i++) {
526 if(i && !append_char(ctx, ','))
527 return E_OUTOFMEMORY;
528
529 if(*ctx->gap) {
530 if(!append_char(ctx, '\n'))
531 return E_OUTOFMEMORY;
532
533 for(j=0; j < ctx->stack_top; j++) {
534 if(!append_string(ctx, ctx->gap))
535 return E_OUTOFMEMORY;
536 }
537 }
538
540 if(SUCCEEDED(hres)) {
541 hres = stringify(ctx, val);
542 if(FAILED(hres))
543 return hres;
544 if(hres == S_FALSE && !append_string(ctx, nullW))
545 return E_OUTOFMEMORY;
546 }else if(hres == DISP_E_UNKNOWNNAME) {
547 if(!append_string(ctx, nullW))
548 return E_OUTOFMEMORY;
549 }else {
550 return hres;
551 }
552 }
553
554 if((length && *ctx->gap && !append_char(ctx, '\n')) || !append_char(ctx, ']'))
555 return E_OUTOFMEMORY;
556
558 return S_OK;
559}
unsigned array_get_length(jsdisp_t *array)
Definition: array.c:73
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
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
HRESULT jsdisp_get_idx(jsdisp_t *obj, DWORD idx, jsval_t *r)
Definition: dispex.c:1425
static void stringify_pop_obj(stringify_ctx_t *ctx)
Definition: json.c:355
static BOOL stringify_push_obj(stringify_ctx_t *ctx, jsdisp_t *obj)
Definition: json.c:334
static BOOL is_on_stack(stringify_ctx_t *ctx, jsdisp_t *obj)
Definition: json.c:360
#define DISP_E_UNKNOWNNAME
Definition: winerror.h:2515

Referenced by stringify().

◆ stringify_object()

static HRESULT stringify_object ( stringify_ctx_t ctx,
jsdisp_t obj 
)
static

Definition at line 562 of file json.c.

563{
564 DISPID dispid = DISPID_STARTENUM;
566 unsigned prop_cnt = 0, i;
567 size_t stepback;
568 BSTR prop_name;
570
571 if(is_on_stack(ctx, obj)) {
572 FIXME("Found a cycle\n");
573 return E_FAIL;
574 }
575
577 return E_OUTOFMEMORY;
578
579 if(!append_char(ctx, '{'))
580 return E_OUTOFMEMORY;
581
582 while((hres = IDispatchEx_GetNextDispID(&obj->IDispatchEx_iface, fdexEnumDefault, dispid, &dispid)) == S_OK) {
584 hres = jsdisp_propget(obj, dispid, &val);
585 if(FAILED(hres))
586 return hres;
587
588 if(is_undefined(val))
589 continue;
590
591 stepback = ctx->buf_len;
592
593 if(prop_cnt && !append_char(ctx, ',')) {
595 break;
596 }
597
598 if(*ctx->gap) {
599 if(!append_char(ctx, '\n')) {
601 break;
602 }
603
604 for(i=0; i < ctx->stack_top; i++) {
605 if(!append_string(ctx, ctx->gap)) {
607 break;
608 }
609 }
610 }
611
612 hres = IDispatchEx_GetMemberName(&obj->IDispatchEx_iface, dispid, &prop_name);
613 if(FAILED(hres))
614 break;
615
616 hres = json_quote(ctx, prop_name, SysStringLen(prop_name));
617 SysFreeString(prop_name);
618 if(FAILED(hres))
619 break;
620
621 if(!append_char(ctx, ':') || (*ctx->gap && !append_char(ctx, ' '))) {
623 break;
624 }
625
626 hres = stringify(ctx, val);
627 if(FAILED(hres))
628 break;
629
630 if(hres == S_FALSE) {
631 ctx->buf_len = stepback;
632 continue;
633 }
634
635 prop_cnt++;
636 }
638 if(FAILED(hres))
639 return hres;
640
641 if(prop_cnt && *ctx->gap) {
642 if(!append_char(ctx, '\n'))
643 return E_OUTOFMEMORY;
644
645 for(i=1; i < ctx->stack_top; i++) {
646 if(!append_string(ctx, ctx->gap)) {
648 break;
649 }
650 }
651 }
652
653 if(!append_char(ctx, '}'))
654 return E_OUTOFMEMORY;
655
657 return S_OK;
658}
OLECHAR * BSTR
Definition: compat.h:2293
HRESULT jsdisp_propget(jsdisp_t *jsdisp, DISPID id, jsval_t *val)
Definition: dispex.c:1447
static BOOL is_undefined(jsval_t v)
Definition: jsval.h:171
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:196
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271

Referenced by stringify().

◆ stringify_pop_obj()

static void stringify_pop_obj ( stringify_ctx_t ctx)
static

Definition at line 355 of file json.c.

356{
357 ctx->stack_top--;
358}

Referenced by stringify_array(), and stringify_object().

◆ stringify_push_obj()

static BOOL stringify_push_obj ( stringify_ctx_t ctx,
jsdisp_t obj 
)
static

Definition at line 334 of file json.c.

335{
336 if(!ctx->stack_size) {
337 ctx->stack = heap_alloc(4*sizeof(*ctx->stack));
338 if(!ctx->stack)
339 return FALSE;
340 ctx->stack_size = 4;
341 }else if(ctx->stack_top == ctx->stack_size) {
342 jsdisp_t **new_stack;
343
344 new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(*ctx->stack));
345 if(!new_stack)
346 return FALSE;
347 ctx->stack = new_stack;
348 ctx->stack_size *= 2;
349 }
350
351 ctx->stack[ctx->stack_top++] = obj;
352 return TRUE;
353}

Referenced by stringify_array(), and stringify_object().

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( jscript  )

Variable Documentation

◆ falseW

◆ JSON_info

const builtin_info_t JSON_info
static
Initial value:
= {
{NULL, NULL, 0},
}
#define ARRAY_SIZE(A)
Definition: main.h:33
@ JSCLASS_JSON
Definition: jscript.h:135
static const builtin_prop_t JSON_props[]
Definition: json.c:823

Definition at line 828 of file json.c.

Referenced by create_json().

◆ JSON_props

const builtin_prop_t JSON_props[]
static
Initial value:
= {
}
#define PROPF_METHOD
Definition: jscript.h:97
static const WCHAR stringifyW[]
Definition: json.c:30
static const WCHAR parseW[]
Definition: json.c:29
static HRESULT JSON_parse(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
Definition: json.c:280
static HRESULT JSON_stringify(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
Definition: json.c:756

Definition at line 823 of file json.c.

◆ nullW

const WCHAR nullW[] = {'n','u','l','l',0}
static

◆ parseW

const WCHAR parseW[] = {'p','a','r','s','e',0}
static

Definition at line 29 of file json.c.

◆ stringifyW

const WCHAR stringifyW[] = {'s','t','r','i','n','g','i','f','y',0}
static

Definition at line 30 of file json.c.

◆ toJSONW

const WCHAR toJSONW[] = {'t','o','J','S','O','N',0}
static

Definition at line 36 of file json.c.

Referenced by stringify().

◆ trueW