mirror of
https://github.com/vim/vim.git
synced 2025-09-02 21:13:50 -04:00
patch 7.4.1407
Problem: json_encode() does not handle NaN and inf properly. (David Barnett) Solution: For JSON turn them into "null". For JS use "NaN" and "Infinity". Add isnan().
This commit is contained in:
parent
e16e5a9d8d
commit
f1b6ac7229
18
src/eval.c
18
src/eval.c
@ -628,6 +628,9 @@ static void f_insert(typval_T *argvars, typval_T *rettv);
|
|||||||
static void f_invert(typval_T *argvars, typval_T *rettv);
|
static void f_invert(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_isdirectory(typval_T *argvars, typval_T *rettv);
|
static void f_isdirectory(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_islocked(typval_T *argvars, typval_T *rettv);
|
static void f_islocked(typval_T *argvars, typval_T *rettv);
|
||||||
|
#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
|
||||||
|
static void f_isnan(typval_T *argvars, typval_T *rettv);
|
||||||
|
#endif
|
||||||
static void f_items(typval_T *argvars, typval_T *rettv);
|
static void f_items(typval_T *argvars, typval_T *rettv);
|
||||||
#ifdef FEAT_JOB
|
#ifdef FEAT_JOB
|
||||||
# ifdef FEAT_CHANNEL
|
# ifdef FEAT_CHANNEL
|
||||||
@ -8320,6 +8323,9 @@ static struct fst
|
|||||||
{"invert", 1, 1, f_invert},
|
{"invert", 1, 1, f_invert},
|
||||||
{"isdirectory", 1, 1, f_isdirectory},
|
{"isdirectory", 1, 1, f_isdirectory},
|
||||||
{"islocked", 1, 1, f_islocked},
|
{"islocked", 1, 1, f_islocked},
|
||||||
|
#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
|
||||||
|
{"isnan", 1, 1, f_isnan},
|
||||||
|
#endif
|
||||||
{"items", 1, 1, f_items},
|
{"items", 1, 1, f_items},
|
||||||
#ifdef FEAT_JOB
|
#ifdef FEAT_JOB
|
||||||
# ifdef FEAT_CHANNEL
|
# ifdef FEAT_CHANNEL
|
||||||
@ -14740,6 +14746,18 @@ f_islocked(typval_T *argvars, typval_T *rettv)
|
|||||||
clear_lval(&lv);
|
clear_lval(&lv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
|
||||||
|
/*
|
||||||
|
* "isnan()" function
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
f_isnan(typval_T *argvars, typval_T *rettv)
|
||||||
|
{
|
||||||
|
rettv->vval.v_number = argvars[0].v_type == VAR_FLOAT
|
||||||
|
&& isnan(argvars[0].vval.v_float);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void dict_list(typval_T *argvars, typval_T *rettv, int what);
|
static void dict_list(typval_T *argvars, typval_T *rettv, int what);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
51
src/json.c
51
src/json.c
@ -16,6 +16,12 @@
|
|||||||
#include "vim.h"
|
#include "vim.h"
|
||||||
|
|
||||||
#if defined(FEAT_EVAL) || defined(PROTO)
|
#if defined(FEAT_EVAL) || defined(PROTO)
|
||||||
|
|
||||||
|
#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
|
||||||
|
/* for isnan() and isinf() */
|
||||||
|
# include <math.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static int json_encode_item(garray_T *gap, typval_T *val, int copyID, int options);
|
static int json_encode_item(garray_T *gap, typval_T *val, int copyID, int options);
|
||||||
static int json_decode_item(js_read_T *reader, typval_T *res, int options);
|
static int json_decode_item(js_read_T *reader, typval_T *res, int options);
|
||||||
|
|
||||||
@ -267,8 +273,20 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
|
|||||||
|
|
||||||
case VAR_FLOAT:
|
case VAR_FLOAT:
|
||||||
#ifdef FEAT_FLOAT
|
#ifdef FEAT_FLOAT
|
||||||
vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", val->vval.v_float);
|
# if defined(HAVE_MATH_H)
|
||||||
ga_concat(gap, numbuf);
|
if ((options & JSON_JS) && isnan(val->vval.v_float))
|
||||||
|
ga_concat(gap, (char_u *)"NaN");
|
||||||
|
else if ((options & JSON_JS) && isinf(val->vval.v_float))
|
||||||
|
ga_concat(gap, (char_u *)"Infinity");
|
||||||
|
else if (isnan(val->vval.v_float) || isinf(val->vval.v_float))
|
||||||
|
ga_concat(gap, (char_u *)"null");
|
||||||
|
else
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
vim_snprintf((char *)numbuf, NUMBUFLEN, "%g",
|
||||||
|
val->vval.v_float);
|
||||||
|
ga_concat(gap, numbuf);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case VAR_UNKNOWN:
|
case VAR_UNKNOWN:
|
||||||
@ -720,9 +738,36 @@ json_decode_item(js_read_T *reader, typval_T *res, int options)
|
|||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
#ifdef FEAT_FLOAT
|
||||||
|
if (STRNICMP((char *)p, "NaN", 3) == 0)
|
||||||
|
{
|
||||||
|
reader->js_used += 3;
|
||||||
|
if (res != NULL)
|
||||||
|
{
|
||||||
|
res->v_type = VAR_FLOAT;
|
||||||
|
res->vval.v_float = 0.0 / 0.0;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
if (STRNICMP((char *)p, "Infinity", 8) == 0)
|
||||||
|
{
|
||||||
|
reader->js_used += 8;
|
||||||
|
if (res != NULL)
|
||||||
|
{
|
||||||
|
res->v_type = VAR_FLOAT;
|
||||||
|
res->vval.v_float = 1.0 / 0.0;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* check for truncated name */
|
/* check for truncated name */
|
||||||
len = (int)(reader->js_end - (reader->js_buf + reader->js_used));
|
len = (int)(reader->js_end - (reader->js_buf + reader->js_used));
|
||||||
if ((len < 5 && STRNICMP((char *)p, "false", len) == 0)
|
if (
|
||||||
|
(len < 5 && STRNICMP((char *)p, "false", len) == 0)
|
||||||
|
#ifdef FEAT_FLOAT
|
||||||
|
|| (len < 8 && STRNICMP((char *)p, "Infinity", len) == 0)
|
||||||
|
|| (len < 3 && STRNICMP((char *)p, "NaN", len) == 0)
|
||||||
|
#endif
|
||||||
|| (len < 4 && (STRNICMP((char *)p, "true", len) == 0
|
|| (len < 4 && (STRNICMP((char *)p, "true", len) == 0
|
||||||
|| STRNICMP((char *)p, "null", len) == 0)))
|
|| STRNICMP((char *)p, "null", len) == 0)))
|
||||||
return MAYBE;
|
return MAYBE;
|
||||||
|
@ -16,8 +16,16 @@ let s:jsonmb = '"s¢cĴgё"'
|
|||||||
let s:varmb = "s¢cĴgё"
|
let s:varmb = "s¢cĴgё"
|
||||||
let s:jsonnr = '1234'
|
let s:jsonnr = '1234'
|
||||||
let s:varnr = 1234
|
let s:varnr = 1234
|
||||||
let s:jsonfl = '12.34'
|
if has('float')
|
||||||
let s:varfl = 12.34
|
let s:jsonfl = '12.34'
|
||||||
|
let s:varfl = 12.34
|
||||||
|
let s:jsoninf = 'null'
|
||||||
|
let s:jsinf = 'Infinity'
|
||||||
|
let s:varinf = 1.0 / 0.0
|
||||||
|
let s:jsonnan = 'null'
|
||||||
|
let s:jsnan = 'NaN'
|
||||||
|
let s:varnan = 0.0 / 0.0
|
||||||
|
endif
|
||||||
|
|
||||||
let s:jsonl1 = '[1,"a",3]'
|
let s:jsonl1 = '[1,"a",3]'
|
||||||
let s:varl1 = [1, "a", 3]
|
let s:varl1 = [1, "a", 3]
|
||||||
@ -68,6 +76,8 @@ func Test_json_encode()
|
|||||||
call assert_equal(s:jsonnr, json_encode(s:varnr))
|
call assert_equal(s:jsonnr, json_encode(s:varnr))
|
||||||
if has('float')
|
if has('float')
|
||||||
call assert_equal(s:jsonfl, json_encode(s:varfl))
|
call assert_equal(s:jsonfl, json_encode(s:varfl))
|
||||||
|
call assert_equal(s:jsoninf, json_encode(s:varinf))
|
||||||
|
call assert_equal(s:jsonnan, json_encode(s:varnan))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call assert_equal(s:jsonl1, json_encode(s:varl1))
|
call assert_equal(s:jsonl1, json_encode(s:varl1))
|
||||||
@ -165,6 +175,8 @@ func Test_js_encode()
|
|||||||
call assert_equal(s:jsonnr, js_encode(s:varnr))
|
call assert_equal(s:jsonnr, js_encode(s:varnr))
|
||||||
if has('float')
|
if has('float')
|
||||||
call assert_equal(s:jsonfl, js_encode(s:varfl))
|
call assert_equal(s:jsonfl, js_encode(s:varfl))
|
||||||
|
call assert_equal(s:jsinf, js_encode(s:varinf))
|
||||||
|
call assert_equal(s:jsnan, js_encode(s:varnan))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call assert_equal(s:jsonl1, js_encode(s:varl1))
|
call assert_equal(s:jsonl1, js_encode(s:varl1))
|
||||||
@ -201,6 +213,8 @@ func Test_js_decode()
|
|||||||
call assert_equal(s:varnr, js_decode(s:jsonnr))
|
call assert_equal(s:varnr, js_decode(s:jsonnr))
|
||||||
if has('float')
|
if has('float')
|
||||||
call assert_equal(s:varfl, js_decode(s:jsonfl))
|
call assert_equal(s:varfl, js_decode(s:jsonfl))
|
||||||
|
call assert_equal(s:varinf, js_decode(s:jsinf))
|
||||||
|
call assert_true(isnan(js_decode(s:jsnan)))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call assert_equal(s:varl1, js_decode(s:jsonl1))
|
call assert_equal(s:varl1, js_decode(s:jsonl1))
|
||||||
|
@ -748,6 +748,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1407,
|
||||||
/**/
|
/**/
|
||||||
1406,
|
1406,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user