/* * Encode "val" into a JSON format string. */ char_u * json_encode(typval_T *val) { garray_T ga; /* Store bytes in the growarray. */ ga_init2(&ga, 1, 4000); json_encode_item(&ga, val, get_copyID()); return ga.ga_data; }
/* * Encode "val" into a JSON format string. * The result is added to "gap" * Returns FAIL on failure and makes gap->ga_data empty. */ static int json_encode_gap(garray_T *gap, typval_T *val, int options) { if (json_encode_item(gap, val, get_copyID(), options) == FAIL) { ga_clear(gap); gap->ga_data = vim_strsave((char_u *)""); return FAIL; } return OK; }
/* * Encode "val" into a JSON format string. * The result is in allocated memory. * The result is empty when encoding fails. * "options" can be JSON_JS or zero; */ char_u * json_encode(typval_T *val, int options) { garray_T ga; /* Store bytes in the growarray. */ ga_init2(&ga, 1, 4000); if (json_encode_item(&ga, val, get_copyID(), options) == FAIL) { vim_free(ga.ga_data); return vim_strsave((char_u *)""); } return ga.ga_data; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { if (nrhs < 1) error(ERROR_MINRHS); if (nrhs > 1) error(ERROR_MAXRHS); json_str = mxMalloc(BUFFER_SIZE); if (json_str == NULL) error(ERROR_MALLOC); json_strlen = BUFFER_SIZE; json_strpos = 0; json_encode_item(prhs[0]); json_str[json_strpos] = '\0'; plhs[0] = mxCreateString(json_str); mxFree(json_str); }
/* * Encode "val" into "gap". * Return FAIL or OK. */ static int json_encode_item(garray_T *gap, typval_T *val, int copyID, int options) { char_u numbuf[NUMBUFLEN]; char_u *res; list_T *l; dict_T *d; switch (val->v_type) { case VAR_SPECIAL: switch (val->vval.v_number) { case VVAL_FALSE: ga_concat(gap, (char_u *)"false"); break; case VVAL_TRUE: ga_concat(gap, (char_u *)"true"); break; case VVAL_NONE: if ((options & JSON_JS) != 0 && (options & JSON_NO_NONE) == 0) /* empty item */ break; /* FALLTHROUGH */ case VVAL_NULL: ga_concat(gap, (char_u *)"null"); break; } break; case VAR_NUMBER: vim_snprintf((char *)numbuf, NUMBUFLEN, "%lld", (long long)val->vval.v_number); ga_concat(gap, numbuf); break; case VAR_STRING: res = val->vval.v_string; write_string(gap, res); break; case VAR_FUNC: case VAR_PARTIAL: case VAR_JOB: case VAR_CHANNEL: /* no JSON equivalent TODO: better error */ EMSG(_(e_invarg)); return FAIL; case VAR_LIST: l = val->vval.v_list; if (l == NULL) ga_concat(gap, (char_u *)"[]"); else { if (l->lv_copyID == copyID) ga_concat(gap, (char_u *)"[]"); else { listitem_T *li; l->lv_copyID = copyID; ga_append(gap, '['); for (li = l->lv_first; li != NULL && !got_int; ) { if (json_encode_item(gap, &li->li_tv, copyID, options & JSON_JS) == FAIL) return FAIL; if ((options & JSON_JS) && li->li_next == NULL && li->li_tv.v_type == VAR_SPECIAL && li->li_tv.vval.v_number == VVAL_NONE) /* add an extra comma if the last item is v:none */ ga_append(gap, ','); li = li->li_next; if (li != NULL) ga_append(gap, ','); } ga_append(gap, ']'); l->lv_copyID = 0; } } break; case VAR_DICT: d = val->vval.v_dict; if (d == NULL) ga_concat(gap, (char_u *)"{}"); else { if (d->dv_copyID == copyID) ga_concat(gap, (char_u *)"{}"); else { int first = TRUE; int todo = (int)d->dv_hashtab.ht_used; hashitem_T *hi; d->dv_copyID = copyID; ga_append(gap, '{'); for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi) if (!HASHITEM_EMPTY(hi)) { --todo; if (first) first = FALSE; else ga_append(gap, ','); if ((options & JSON_JS) && is_simple_key(hi->hi_key)) ga_concat(gap, hi->hi_key); else write_string(gap, hi->hi_key); ga_append(gap, ':'); if (json_encode_item(gap, &dict_lookup(hi)->di_tv, copyID, options | JSON_NO_NONE) == FAIL) return FAIL; } ga_append(gap, '}'); d->dv_copyID = 0; } } break; case VAR_FLOAT: #ifdef FEAT_FLOAT # if defined(HAVE_MATH_H) if (isnan(val->vval.v_float)) ga_concat(gap, (char_u *)"NaN"); else if (isinf(val->vval.v_float)) ga_concat(gap, (char_u *)"Infinity"); else # endif { vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", val->vval.v_float); ga_concat(gap, numbuf); } break; #endif case VAR_UNKNOWN: internal_error("json_encode_item()"); return FAIL; } return OK; }
/* * Encode "val" into "gap". * Return FAIL or OK. */ static int json_encode_item(garray_T *gap, typval_T *val, int copyID) { char_u numbuf[NUMBUFLEN]; char_u *res; list_T *l; dict_T *d; switch (val->v_type) { case VAR_SPECIAL: switch (val->vval.v_number) { case VVAL_FALSE: ga_concat(gap, (char_u *)"false"); break; case VVAL_TRUE: ga_concat(gap, (char_u *)"true"); break; case VVAL_NONE: break; case VVAL_NULL: ga_concat(gap, (char_u *)"null"); break; } break; case VAR_NUMBER: vim_snprintf((char *)numbuf, NUMBUFLEN, "%ld", (long)val->vval.v_number); ga_concat(gap, numbuf); break; case VAR_STRING: res = val->vval.v_string; write_string(gap, res); break; case VAR_FUNC: /* no JSON equivalent */ EMSG(_(e_invarg)); return FAIL; case VAR_LIST: l = val->vval.v_list; if (l == NULL) ga_concat(gap, (char_u *)"null"); else { if (l->lv_copyID == copyID) ga_concat(gap, (char_u *)"[]"); else { listitem_T *li; l->lv_copyID = copyID; ga_append(gap, '['); for (li = l->lv_first; li != NULL && !got_int; ) { if (json_encode_item(gap, &li->li_tv, copyID) == FAIL) return FAIL; li = li->li_next; if (li != NULL) ga_append(gap, ','); } ga_append(gap, ']'); l->lv_copyID = 0; } } break; case VAR_DICT: d = val->vval.v_dict; if (d == NULL) ga_concat(gap, (char_u *)"null"); else { if (d->dv_copyID == copyID) ga_concat(gap, (char_u *)"{}"); else { int first = TRUE; int todo = (int)d->dv_hashtab.ht_used; hashitem_T *hi; d->dv_copyID = copyID; ga_append(gap, '{'); for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi) if (!HASHITEM_EMPTY(hi)) { --todo; if (first) first = FALSE; else ga_append(gap, ','); write_string(gap, hi->hi_key); ga_append(gap, ':'); if (json_encode_item(gap, &dict_lookup(hi)->di_tv, copyID) == FAIL) return FAIL; } ga_append(gap, '}'); d->dv_copyID = 0; } } break; #ifdef FEAT_FLOAT case VAR_FLOAT: vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", val->vval.v_float); ga_concat(gap, numbuf); break; #endif default: EMSG2(_(e_intern2), "json_encode_item()"); break; return FAIL; } return OK; }
void json_encode_item(const mxArray *obj) { mxArray *item; mxChar *chars; unsigned int field, nfields; const char *fieldname; mxLogical *logical_ptr; double *double_ptr; float *single_ptr; uint8_t *uint8_ptr; int8_t *int8_ptr; uint16_t *uint16_ptr; int16_t *int16_ptr; uint32_t *uint32_ptr; int32_t *int32_ptr; uint64_t *uint64_ptr; int64_t *int64_ptr; unsigned int i, n; n = mxGetNumberOfElements(obj); if (mxIsChar(obj)) { json_append_char('"'); chars = mxGetChars(obj); for (i=0; i<n; i++) { switch (chars[i]) { case '"': case '\\': case '/': json_append_char('\\'); json_append_char(*(char*)&chars[i]); break; case '\b': json_append_string("\\b"); break; case '\f': json_append_string("\\f"); break; case '\n': json_append_string("\\n"); break; case '\r': json_append_string("\\r"); break; case '\t': json_append_string("\\t"); break; default: if ((chars[i] < 32) || (chars[i] > 126)) json_append_string("\\u%04hx",chars[i]); else json_append_char(*(char*)&chars[i]); } } json_append_char('"'); } else if (n == 0) { json_append_string("[]"); } else { if (n > 1) json_append_char('['); switch (mxGetClassID(obj)) { case mxSTRUCT_CLASS: nfields = mxGetNumberOfFields(obj); for (i=0; i<n; i++) { json_append_char('{'); for (field=0; field<nfields; field++) { fieldname = mxGetFieldNameByNumber(obj,field); item = mxGetFieldByNumber(obj,i,field); if (item != NULL) { json_append_string("\"%s\":",fieldname); json_encode_item(item); json_append_char(','); } } if (nfields > 0) json_strpos--; json_append_string("},"); } break; case mxCELL_CLASS: for (i=0; i<n; i++) { json_encode_item(mxGetCell(obj,i)); json_append_char(','); } break; case mxLOGICAL_CLASS: logical_ptr = mxGetData(obj); for (i=0; i<n; i++) { if (logical_ptr[i]) { json_append_string("true,"); } else { json_append_string("false,"); } } break; case mxDOUBLE_CLASS: double_ptr = mxGetData(obj); for (i=0; i<n; i++) json_append_float(double_ptr[i]); break; case mxSINGLE_CLASS: single_ptr = mxGetData(obj); for (i=0; i<n; i++) json_append_float(single_ptr[i]); break; case mxINT8_CLASS: int8_ptr = mxGetData(obj); for (i=0; i<n; i++) json_append_string("%i,",int8_ptr[i]); break; case mxUINT8_CLASS: uint8_ptr = mxGetData(obj); for (i=0; i<n; i++) json_append_string("%u,",uint8_ptr[i]); break; case mxINT16_CLASS: int16_ptr = mxGetData(obj); for (i=0; i<n; i++) json_append_string("%i,",int16_ptr[i]); break; case mxUINT16_CLASS: uint16_ptr = mxGetData(obj); for (i=0; i<n; i++) json_append_string("%u,",uint16_ptr[i]); break; case mxINT32_CLASS: int32_ptr = mxGetData(obj); for (i=0; i<n; i++) json_append_string("%i,",int32_ptr[i]); break; case mxUINT32_CLASS: uint32_ptr = mxGetData(obj); for (i=0; i<n; i++) json_append_string("%u,",uint32_ptr[i]); break; case mxINT64_CLASS: int64_ptr = mxGetData(obj); for (i=0; i<n; i++) json_append_string("%lli,",int64_ptr[i]); break; case mxUINT64_CLASS: uint64_ptr = mxGetData(obj); for (i=0; i<n; i++) json_append_string("%llu,",uint64_ptr[i]); break; default: error_unsupported_class(obj); } if (json_strpos) json_strpos--; if (n > 1) json_append_char(']'); } }