struct json *json_create_string(const char *string) { struct json *item = json_new_item(); if (item) { item->type = JSON_T_STRING; item->valuestring = json_strdup(string); } return item; }
void json_add_item_to_object(struct json *object, const char *string, struct json *item) { if (!item) return; if (item->string) json_free(item->string); item->string = json_strdup(string); json_add_item_to_array(object, item); }
void json_replace_item_in_object(struct json *object, const char *string, struct json *newitem) { int i = 0; struct json *c = object->child; while (c && json_strcasecmp(c->string, string)) i++, c = c->next; if (c) { newitem->string = json_strdup(string); json_replace_item_in_array(object, i, newitem); } }
static struct command_result *waitsendpay_done(struct command *cmd, const char *buf, const jsmntok_t *result, struct pay_command *pc) { struct pay_attempt *attempt = current_attempt(pc); attempt->result = json_strdup(pc->ps->attempts, buf, result); attempt->end = time_now(); return forward_result(cmd, buf, result, pc); }
/* Render a value to text. */ static char *print_value(struct json *item, int depth, int fmt) { char *out = NULL; if (!item) return 0; if (fmt == item->print_fmt && item->print_out) return item->print_out; switch ((item->type) & 255) { case JSON_T_NULL: out = json_strdup("null"); break; case JSON_T_FALSE: out = json_strdup("false"); break; case JSON_T_TRUE: out = json_strdup("true"); break; case JSON_T_NUMBER: out = print_number(item); break; case JSON_T_STRING: out = print_string(item); break; case JSON_T_ARRAY: out = print_array(item, depth, fmt); break; case JSON_T_OBJECT: out = print_object(item, depth, fmt); break; } if (item->print_out) json_free(item->print_out); item->print_out = out; item->print_fmt = fmt; return out; }
/* Render the cstring provided to an escaped version that can be printed. */ static char *print_string_ptr(const char *str) { const char *ptr; char *ptr2, *out; int len = 0; unsigned char token; if (!str) return json_strdup(""); ptr = str; while ((token = *ptr) && ++len) { if (strchr("\"\\\b\f\n\r\t", token)) len++; else if (token < 32) len += 5; ptr++; } out = (char *)json_malloc(len + 3); if (!out) return 0; ptr2 = out; ptr = str; *ptr2++ = '\"'; while (*ptr) { if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\') *ptr2++ = *ptr++; else { *ptr2++ = '\\'; switch (token = *ptr++) { case '\\': *ptr2++ = '\\'; break; case '\"': *ptr2++ = '\"'; break; case '\b': *ptr2++ = 'b'; break; case '\f': *ptr2++ = 'f'; break; case '\n': *ptr2++ = 'n'; break; case '\r': *ptr2++ = 'r'; break; case '\t': *ptr2++ = 't'; break; default: sprintf(ptr2, "u%04x", token); ptr2 += 5; break; /* escape and print */ } } } *ptr2++ = '\"'; *ptr2++ = 0; return out; }
json * json_from_string (char *str, int *err) { json *root; json *cur; char *c; int s; if (!str) return NULL; root = calloc (1, sizeof *root); root->label = strdup("root"); cur = NULL; c = str; s = INIT; while (*c != '\0') { int skip; if (*c == ' ' || *c == '\n' || *c == '\t' || *c == '\r') { c++; continue; } skip = 1; if (s == INIT) { if (*c == '{') root->type = JSON_TYPE_OBJECT; else if (*c == '[') root->type = JSON_TYPE_ARRAY; else error (JSON_ERR_ERR); cur = root->val.obj = calloc (1, sizeof *cur); cur->parent = root; s = root->type == JSON_TYPE_OBJECT ? LABEL : VALUE; } else if (s == LABEL) { char *label; size_t len; if (*c != '"') error (JSON_ERR_QUOTE); len = json_strdup (c + 1, &label); if (len == 0) error (JSON_ERR_QUOTE); cur->label = label; skip = len + 2; s = SEPARATOR; } else if (s == SEPARATOR) { if (*c != ':') error (JSON_ERR_SEPARATOR); s = VALUE; } else if (s == VALUE) { if (*c == '"') { size_t len; char *val; cur->type = JSON_TYPE_STR; len = json_strdup (c + 1, &val); cur->val.str = val; skip = len + 2; s = TWILLIGHT; } else if ((*c >= '0' && *c <= '9') || *c == '-') { skip = json_parse_num (c, cur); s = TWILLIGHT; } else if (*c == '[') { json *n; cur->type = JSON_TYPE_ARRAY; n = calloc (1, sizeof *n); n->parent = cur; cur = cur->val.obj = n; s = VALUE; } else if (*c == '{') { json *n; cur->type = JSON_TYPE_OBJECT; n = calloc (1, sizeof *n); n->parent = cur; cur = cur->val.obj = n; s = LABEL; } else if ((*c | 0x20) == 'n') cur->type = JSON_TYPE_NULL; else if (*c == 't' || *c == 'T') cur->type = JSON_TYPE_TRUE; else if (*c == 'f' || *c == 'F') cur->type = JSON_TYPE_FALSE; else { cur->type = JSON_TYPE_EMPTY; if (*c == ']' || *c == '}') s = TWILLIGHT; else error (JSON_ERR_ERR); } } else if (s == TWILLIGHT) { if (*c == ',') { json *n; n = calloc (1, sizeof *n); cur->next = n; n->parent = cur->parent; cur = n; if (n->parent->type == JSON_TYPE_OBJECT) s = LABEL; else s = VALUE; } else if (*c == '}' || *c == ']') { if (cur->parent != NULL) cur = cur->parent; else printf ("DONE\n"); /* Stay in twillight state */ } else error (JSON_ERR_ERR); } c += skip; } if (err) *err = 0; return root; Out: json_free (root); return NULL; }
/* * json_column_group_index -- * Parse a column group or index entry from JSON input. */ static int json_column_group_index(WT_SESSION *session, JSON_INPUT_STATE *ins, CONFIG_LIST *clp, int idx) { WT_DECL_RET; char *config, *p, *uri; int isconfig; uri = NULL; config = NULL; while (json_peek(session, ins) == '{') { JSON_EXPECT(session, ins, '{'); JSON_EXPECT(session, ins, 's'); isconfig = JSON_STRING_MATCH(ins, "config"); if (!isconfig && !JSON_STRING_MATCH(ins, "uri")) goto err; JSON_EXPECT(session, ins, ':'); JSON_EXPECT(session, ins, 's'); if ((ret = json_strdup(ins, &p)) != 0) { ret = util_err(ret, NULL); goto err; } if (isconfig) config = p; else uri = p; isconfig = !isconfig; JSON_EXPECT(session, ins, ','); JSON_EXPECT(session, ins, 's'); if (!JSON_STRING_MATCH(ins, isconfig ? "config" : "uri")) goto err; JSON_EXPECT(session, ins, ':'); JSON_EXPECT(session, ins, 's'); if ((ret = json_strdup(ins, &p)) != 0) { ret = util_err(ret, NULL); goto err; } if (isconfig) config = p; else uri = p; JSON_EXPECT(session, ins, '}'); if ((idx && strncmp(uri, "index:", 6) != 0) || (!idx && strncmp(uri, "colgroup:", 9) != 0)) { ret = util_err(EINVAL, "%s: misplaced colgroup or index", uri); goto err; } if ((ret = config_list_add(clp, uri)) != 0 || (ret = config_list_add(clp, config)) != 0) goto err; if (json_peek(session, ins) != ',') break; JSON_EXPECT(session, ins, ','); if (json_peek(session, ins) != '{') goto err; } if (0) { err: if (ret == 0) ret = EINVAL; } return (ret); }
/* * json_top_level -- * Parse the top level JSON input. */ static int json_top_level(WT_SESSION *session, JSON_INPUT_STATE *ins, uint32_t flags) { CONFIG_LIST cl; WT_DECL_RET; char *config, *tableuri; int toktype; static const char *json_markers[] = { "\"config\"", "\"colgroups\"", "\"indices\"", "\"data\"", NULL }; memset(&cl, 0, sizeof(cl)); tableuri = NULL; JSON_EXPECT(session, ins, '{'); while (json_peek(session, ins) == 's') { JSON_EXPECT(session, ins, 's'); tableuri = realloc(tableuri, ins->toklen); snprintf(tableuri, ins->toklen, "%.*s", (int)(ins->toklen - 2), ins->tokstart + 1); JSON_EXPECT(session, ins, ':'); /* * Allow any ordering of 'config', 'colgroups', * 'indices' before 'data', which must appear last. * The non-'data' items build up a list of entries * that created in our session before the data is * inserted. */ for (;;) { if (json_skip(session, ins, json_markers) != 0) goto err; JSON_EXPECT(session, ins, 's'); if (JSON_STRING_MATCH(ins, "config")) { JSON_EXPECT(session, ins, ':'); JSON_EXPECT(session, ins, 's'); if ((ret = json_strdup(ins, &config)) != 0) { ret = util_err(ret, NULL); goto err; } if ((ret = config_list_add(&cl, tableuri)) != 0) goto err; if ((ret = config_list_add(&cl, config)) != 0) goto err; tableuri = NULL; } else if (JSON_STRING_MATCH(ins, "colgroups")) { JSON_EXPECT(session, ins, ':'); JSON_EXPECT(session, ins, '['); if ((ret = json_column_group_index( session, ins, &cl, 0)) != 0) goto err; JSON_EXPECT(session, ins, ']'); } else if (JSON_STRING_MATCH(ins, "indices")) { JSON_EXPECT(session, ins, ':'); JSON_EXPECT(session, ins, '['); if ((ret = json_column_group_index( session, ins, &cl, 1)) != 0) goto err; JSON_EXPECT(session, ins, ']'); } else if (JSON_STRING_MATCH(ins, "data")) { JSON_EXPECT(session, ins, ':'); JSON_EXPECT(session, ins, '['); if ((ret = json_data(session, ins, &cl, flags)) != 0) goto err; config_list_free(&cl); break; } else goto err; } while ((toktype = json_peek(session, ins)) == '}' || toktype == ']') JSON_EXPECT(session, ins, toktype); if (toktype == 0) /* Check EOF. */ break; if (toktype == ',') { JSON_EXPECT(session, ins, ','); if (json_peek(session, ins) != 's') goto err; continue; } } JSON_EXPECT(session, ins, 0); if (0) { err: if (ret == 0) ret = EINVAL; } config_list_free(&cl); if (tableuri != NULL) free(tableuri); return (ret); }