static bool add_value_to_config(Json::Value& config, std::string& key_value, bool is_json) { size_t equals_idx = key_value.find('='); size_t dot_idx = key_value.find('.'); if (equals_idx != std::string::npos) { if (dot_idx != std::string::npos && dot_idx < equals_idx) { // Pass-specific config value specified with -Dpassname.key=value std::string pass = key_value.substr(0, dot_idx); std::string key = key_value.substr(dot_idx + 1, equals_idx - dot_idx - 1); std::string value_string = key_value.substr(equals_idx + 1); if (is_json) { config[pass.c_str()][key.c_str()] = parse_json_value(value_string); } else { config[pass.c_str()][key.c_str()] = value_string.c_str(); } } else { // Global config value specified with -Dkey=value std::string key = key_value.substr(0, equals_idx); std::string value_string = key_value.substr(equals_idx + 1); if (is_json) { config[key.c_str()] = parse_json_value(value_string); } else { config[key.c_str()] = value_string.c_str(); } } return true; } return false; }
void JSON::parse() { assert(start != NULL, "Need something to parse"); if (start == NULL) { _valid = false; error(INTERNAL_ERROR, "JSON parser was called with a string that was NULL."); } else { _valid = parse_json_value(); } }
// Should only be called when we actually have the start of an array // Otherwise it is an internal error bool JSON::parse_json_array() { NOT_PRODUCT(const char* prev_pos); int c; mark_pos(); // Check that we are not called in error if (expect_any("[", "array start character", INTERNAL_ERROR) <= 0) { return false; } if (!callback(JSON_ARRAY_BEGIN, NULL, level++)) { return false; } for (;;) { mark_pos(); c = skip_to_token(); if (c == 0) { error(SYNTAX_ERROR, "EOS when expecting a json value or array end"); return false; } else if (c < 0) { return false; } else if (c == ']') { // We got here from either empty array "[]" or ending comma "[1,]" next(); break; } mark_pos(); NOT_PRODUCT(prev_pos = pos); if (parse_json_value() == false) { return false; } assert(pos > prev_pos, "parsing stalled"); c = skip_to_token(); mark_pos(); if (expect_any(",]", "value separator or array end") <= 0) { return false; } if (c == ']') { break; } } assert(c == ']', "array parsing ended without array end token (']')"); return callback(JSON_ARRAY_END, NULL, --level); }
/* ECMA-262 5.1 Edition 15.12.2 */ static HRESULT JSON_parse(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { json_parse_ctx_t parse_ctx; const WCHAR *buf; jsstr_t *str; jsval_t ret; HRESULT hres; if(argc != 1) { FIXME("Unsupported args\n"); return E_INVALIDARG; } hres = to_flat_string(ctx, argv[0], &str, &buf); if(FAILED(hres)) return hres; TRACE("%s\n", debugstr_w(buf)); parse_ctx.ptr = buf; parse_ctx.end = buf + jsstr_length(str); parse_ctx.ctx = ctx; hres = parse_json_value(&parse_ctx, &ret); jsstr_release(str); if(FAILED(hres)) return hres; if(skip_spaces(&parse_ctx)) { FIXME("syntax error\n"); jsval_release(ret); return E_FAIL; } if(r) *r = ret; else jsval_release(ret); return S_OK; }
// Should only be called when we actually have the start of an object // Otherwise it is an internal error bool JSON::parse_json_object() { NOT_PRODUCT(const char* prev_pos); int c; mark_pos(); // Check that we are not called in error if (expect_any("{", "object start", INTERNAL_ERROR) <= 0) { return false; } if (!callback(JSON_OBJECT_BEGIN, NULL, level++)) { return false; } for (;;) { mark_pos(); c = skip_to_token(); if (c == 0) { error(SYNTAX_ERROR, "EOS when expecting an object key or object end"); return false; } else if (c < 0) { return false; } else if (c == '}') { // We got here from either empty object "{}" or ending comma "{a:1,}" next(); break; } NOT_PRODUCT(prev_pos = pos); if (parse_json_key() == false) { return false; } assert(pos > prev_pos, "parsing stalled"); skip_to_token(); mark_pos(); if (expect_any(":", "object key-value separator") <= 0) { return false; } skip_to_token(); mark_pos(); NOT_PRODUCT(prev_pos = pos); if (parse_json_value() == false) { return false; } assert(pos > prev_pos, "parsing stalled"); c = skip_to_token(); mark_pos(); if (expect_any(",}", "value separator or object end") <= 0) { return false; } if (c == '}') { break; } } assert(c == '}', "array parsing ended without object end token ('}')"); return callback(JSON_OBJECT_END, NULL, --level); }
/* ECMA-262 5.1 Edition 15.12.1.2 */ static HRESULT parse_json_value(json_parse_ctx_t *ctx, jsval_t *r) { HRESULT hres; switch(skip_spaces(ctx)) { /* JSONNullLiteral */ case 'n': if(!is_keyword(ctx, nullW)) break; *r = jsval_null(); return S_OK; /* JSONBooleanLiteral */ case 't': if(!is_keyword(ctx, trueW)) break; *r = jsval_bool(TRUE); return S_OK; case 'f': if(!is_keyword(ctx, falseW)) break; *r = jsval_bool(FALSE); return S_OK; /* JSONObject */ case '{': { WCHAR *prop_name; jsdisp_t *obj; jsval_t val; hres = create_object(ctx->ctx, NULL, &obj); if(FAILED(hres)) return hres; ctx->ptr++; if(skip_spaces(ctx) == '}') { ctx->ptr++; *r = jsval_obj(obj); return S_OK; } while(1) { if(*ctx->ptr != '"') break; hres = parse_json_string(ctx, &prop_name); if(FAILED(hres)) break; if(skip_spaces(ctx) != ':') { FIXME("missing ':'\n"); heap_free(prop_name); break; } ctx->ptr++; hres = parse_json_value(ctx, &val); if(SUCCEEDED(hres)) { hres = jsdisp_propput_name(obj, prop_name, val); jsval_release(val); } heap_free(prop_name); if(FAILED(hres)) break; if(skip_spaces(ctx) == '}') { ctx->ptr++; *r = jsval_obj(obj); return S_OK; } if(*ctx->ptr++ != ',') { FIXME("expected ','\n"); break; } skip_spaces(ctx); } jsdisp_release(obj); break; } /* JSONString */ case '"': { WCHAR *string; jsstr_t *str; hres = parse_json_string(ctx, &string); if(FAILED(hres)) return hres; /* FIXME: avoid reallocation */ str = jsstr_alloc(string); heap_free(string); if(!str) return E_OUTOFMEMORY; *r = jsval_string(str); return S_OK; } /* JSONArray */ case '[': { jsdisp_t *array; unsigned i = 0; jsval_t val; hres = create_array(ctx->ctx, 0, &array); if(FAILED(hres)) return hres; ctx->ptr++; if(skip_spaces(ctx) == ']') { ctx->ptr++; *r = jsval_obj(array); return S_OK; } while(1) { hres = parse_json_value(ctx, &val); if(FAILED(hres)) break; hres = jsdisp_propput_idx(array, i, val); jsval_release(val); if(FAILED(hres)) break; if(skip_spaces(ctx) == ']') { ctx->ptr++; *r = jsval_obj(array); return S_OK; } if(*ctx->ptr != ',') { FIXME("expected ','\n"); break; } ctx->ptr++; i++; } jsdisp_release(array); break; } /* JSONNumber */ default: { int sign = 1; double n; if(*ctx->ptr == '-') { sign = -1; ctx->ptr++; skip_spaces(ctx); } if(!isdigitW(*ctx->ptr)) break; if(*ctx->ptr == '0') { ctx->ptr++; n = 0; if(is_identifier_char(*ctx->ptr)) break; }else { hres = parse_decimal(&ctx->ptr, ctx->end, &n); if(FAILED(hres)) return hres; } *r = jsval_number(sign*n); return S_OK; } } FIXME("Syntax error at %s\n", debugstr_w(ctx->ptr)); return E_FAIL; }