static int json_decode_array(js_read_T *reader, typval_T *res, int options) { char_u *p; typval_T item; listitem_T *li; int ret; if (res != NULL && rettv_list_alloc(res) == FAIL) { res->v_type = VAR_SPECIAL; res->vval.v_number = VVAL_NONE; return FAIL; } ++reader->js_used; /* consume the '[' */ while (TRUE) { json_skip_white(reader); p = reader->js_buf + reader->js_used; if (*p == NUL) return MAYBE; if (*p == ']') { ++reader->js_used; /* consume the ']' */ break; } ret = json_decode_item(reader, res == NULL ? NULL : &item, options); if (ret != OK) return ret; if (res != NULL) { li = listitem_alloc(); if (li == NULL) { clear_tv(&item); return FAIL; } li->li_tv = item; list_append(res->vval.v_list, li); } json_skip_white(reader); p = reader->js_buf + reader->js_used; if (*p == ',') ++reader->js_used; else if (*p != ']') { if (*p == NUL) return MAYBE; return FAIL; } } return OK; }
/* * Decode the JSON from "reader" to find the end of the message. * "options" can be JSON_JS or zero. * This is only used for testing. * Return FAIL if the message has a decoding error. * Return MAYBE if the message is truncated, need to read more. * This only works reliable if the message contains an object, array or * string. A number might be trucated without knowing. * Does not advance the reader. */ int json_find_end(js_read_T *reader, int options) { int used_save = reader->js_used; int ret; /* We find the end once, to avoid calling strlen() many times. */ reader->js_end = reader->js_buf + STRLEN(reader->js_buf); json_skip_white(reader); ret = json_decode_item(reader, NULL, options); reader->js_used = used_save; return ret; }
/* * Decode the JSON from "reader" and store the result in "res". * "options" can be JSON_JS or zero; * Return FAIL for a decoding error. * Return MAYBE for an incomplete message. * Consumes the message anyway. */ int json_decode(js_read_T *reader, typval_T *res, int options) { int ret; /* We find the end once, to avoid calling strlen() many times. */ reader->js_end = reader->js_buf + STRLEN(reader->js_buf); json_skip_white(reader); ret = json_decode_item(reader, res, options); json_skip_white(reader); return ret; }
/* * Decode the JSON from "reader" and store the result in "res". * Return FAIL if the message has a decoding error or the message is * truncated. Consumes the message anyway. */ int json_decode(js_read_T *reader, typval_T *res) { int ret; /* We get the end once, to avoid calling strlen() many times. */ reader->js_end = reader->js_buf + STRLEN(reader->js_buf); json_skip_white(reader); ret = json_decode_item(reader, res); json_skip_white(reader); return ret == OK ? OK : FAIL; }
/* * Decode the JSON from "reader" and store the result in "res". * "options" can be JSON_JS or zero; * Return FAIL if not the whole message was consumed. */ int json_decode_all(js_read_T *reader, typval_T *res, int options) { int ret; /* We find the end once, to avoid calling strlen() many times. */ reader->js_end = reader->js_buf + STRLEN(reader->js_buf); json_skip_white(reader); ret = json_decode_item(reader, res, options); if (ret != OK) return FAIL; json_skip_white(reader); if (reader->js_buf[reader->js_used] != NUL) return FAIL; return OK; }
static int json_decode_object(js_read_T *reader, typval_T *res, int options) { char_u *p; typval_T tvkey; typval_T item; dictitem_T *di; char_u buf[NUMBUFLEN]; char_u *key = NULL; int ret; if (res != NULL && rettv_dict_alloc(res) == FAIL) { res->v_type = VAR_SPECIAL; res->vval.v_number = VVAL_NONE; return FAIL; } ++reader->js_used; /* consume the '{' */ while (TRUE) { json_skip_white(reader); p = reader->js_buf + reader->js_used; if (*p == NUL) return MAYBE; if (*p == '}') { ++reader->js_used; /* consume the '}' */ break; } if ((options & JSON_JS) && reader->js_buf[reader->js_used] != '"') { /* accept a key that is not in quotes */ key = p = reader->js_buf + reader->js_used; while (*p != NUL && *p != ':' && *p > ' ') ++p; tvkey.v_type = VAR_STRING; tvkey.vval.v_string = vim_strnsave(key, (int)(p - key)); reader->js_used += (int)(p - key); key = tvkey.vval.v_string; } else { ret = json_decode_item(reader, res == NULL ? NULL : &tvkey, options); if (ret != OK) return ret; if (res != NULL) { key = get_tv_string_buf_chk(&tvkey, buf); if (key == NULL || *key == NUL) { clear_tv(&tvkey); return FAIL; } } } json_skip_white(reader); p = reader->js_buf + reader->js_used; if (*p != ':') { if (res != NULL) clear_tv(&tvkey); if (*p == NUL) return MAYBE; return FAIL; } ++reader->js_used; json_skip_white(reader); ret = json_decode_item(reader, res == NULL ? NULL : &item, options); if (ret != OK) { if (res != NULL) clear_tv(&tvkey); return ret; } if (res != NULL) { di = dictitem_alloc(key); clear_tv(&tvkey); if (di == NULL) { clear_tv(&item); return FAIL; } di->di_tv = item; if (dict_add(res->vval.v_dict, di) == FAIL) { dictitem_free(di); return FAIL; } } json_skip_white(reader); p = reader->js_buf + reader->js_used; if (*p == ',') ++reader->js_used; else if (*p != '}') { if (*p == NUL) return MAYBE; return FAIL; } } return OK; }
static int json_decode_object(js_read_T *reader, typval_T *res) { char_u *p; typval_T tvkey; typval_T item; dictitem_T *di; char_u buf[NUMBUFLEN]; char_u *key = NULL; int ret; if (res != NULL && rettv_dict_alloc(res) == FAIL) { res->v_type = VAR_SPECIAL; res->vval.v_number = VVAL_NONE; return FAIL; } ++reader->js_used; /* consume the '{' */ while (TRUE) { json_skip_white(reader); p = reader->js_buf + reader->js_used; if (*p == NUL) return MAYBE; if (*p == '}') { ++reader->js_used; /* consume the '}' */ break; } ret = json_decode_item(reader, res == NULL ? NULL : &tvkey); if (ret != OK) return ret; if (res != NULL) { key = get_tv_string_buf_chk(&tvkey, buf); if (key == NULL || *key == NUL) { clear_tv(&tvkey); return FAIL; } } json_skip_white(reader); p = reader->js_buf + reader->js_used; if (*p != ':') { if (res != NULL) clear_tv(&tvkey); if (*p == NUL) return MAYBE; return FAIL; } ++reader->js_used; json_skip_white(reader); ret = json_decode_item(reader, res == NULL ? NULL : &item); if (ret != OK) { if (res != NULL) clear_tv(&tvkey); return ret; } if (res != NULL) { di = dictitem_alloc(key); clear_tv(&tvkey); if (di == NULL) { clear_tv(&item); return FAIL; } di->di_tv = item; if (dict_add(res->vval.v_dict, di) == FAIL) { dictitem_free(di); return FAIL; } } json_skip_white(reader); p = reader->js_buf + reader->js_used; if (*p == ',') ++reader->js_used; else if (*p != '}') { if (*p == NUL) return MAYBE; return FAIL; } } return OK; }