To: vim_dev@googlegroups.com Subject: Patch 7.4.1407 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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(). Files: src/eval.c, src/json.c, src/testdir/test_json.vim *** ../vim-7.4.1406/src/eval.c 2016-02-23 17:13:56.877032330 +0100 --- src/eval.c 2016-02-23 21:19:22.203128950 +0100 *************** *** 628,633 **** --- 628,636 ---- static void f_invert(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); + #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); #ifdef FEAT_JOB # ifdef FEAT_CHANNEL *************** *** 8320,8325 **** --- 8323,8331 ---- {"invert", 1, 1, f_invert}, {"isdirectory", 1, 1, f_isdirectory}, {"islocked", 1, 1, f_islocked}, + #if defined(FEAT_FLOAT) && defined(HAVE_MATH_H) + {"isnan", 1, 1, f_isnan}, + #endif {"items", 1, 1, f_items}, #ifdef FEAT_JOB # ifdef FEAT_CHANNEL *************** *** 14740,14745 **** --- 14746,14763 ---- 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); /* *** ../vim-7.4.1406/src/json.c 2016-02-20 15:26:38.299827771 +0100 --- src/json.c 2016-02-23 21:11:39.991974796 +0100 *************** *** 16,21 **** --- 16,27 ---- #include "vim.h" #if defined(FEAT_EVAL) || defined(PROTO) + + #if defined(FEAT_FLOAT) && defined(HAVE_MATH_H) + /* for isnan() and isinf() */ + # include + #endif + 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); *************** *** 267,274 **** case VAR_FLOAT: #ifdef FEAT_FLOAT ! vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", val->vval.v_float); ! ga_concat(gap, numbuf); break; #endif case VAR_UNKNOWN: --- 273,292 ---- case VAR_FLOAT: #ifdef FEAT_FLOAT ! # if defined(HAVE_MATH_H) ! 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; #endif case VAR_UNKNOWN: *************** *** 720,728 **** } return OK; } /* check for truncated name */ len = (int)(reader->js_end - (reader->js_buf + reader->js_used)); ! if ((len < 5 && STRNICMP((char *)p, "false", len) == 0) || (len < 4 && (STRNICMP((char *)p, "true", len) == 0 || STRNICMP((char *)p, "null", len) == 0))) return MAYBE; --- 738,773 ---- } 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 */ len = (int)(reader->js_end - (reader->js_buf + reader->js_used)); ! 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 || STRNICMP((char *)p, "null", len) == 0))) return MAYBE; *** ../vim-7.4.1406/src/testdir/test_json.vim 2016-02-11 21:08:27.544531244 +0100 --- src/testdir/test_json.vim 2016-02-23 21:25:52.651035682 +0100 *************** *** 16,23 **** let s:varmb = "s¢cĴgё" let s:jsonnr = '1234' let s:varnr = 1234 ! let s:jsonfl = '12.34' ! let s:varfl = 12.34 let s:jsonl1 = '[1,"a",3]' let s:varl1 = [1, "a", 3] --- 16,31 ---- let s:varmb = "s¢cĴgё" let s:jsonnr = '1234' let s:varnr = 1234 ! if has('float') ! 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:varl1 = [1, "a", 3] *************** *** 68,73 **** --- 76,83 ---- call assert_equal(s:jsonnr, json_encode(s:varnr)) if has('float') 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 call assert_equal(s:jsonl1, json_encode(s:varl1)) *************** *** 165,170 **** --- 175,182 ---- call assert_equal(s:jsonnr, js_encode(s:varnr)) if has('float') 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 call assert_equal(s:jsonl1, js_encode(s:varl1)) *************** *** 201,206 **** --- 213,220 ---- call assert_equal(s:varnr, js_decode(s:jsonnr)) if has('float') 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 call assert_equal(s:varl1, js_decode(s:jsonl1)) *** ../vim-7.4.1406/src/version.c 2016-02-23 20:43:58.725419739 +0100 --- src/version.c 2016-02-23 21:24:12.216088576 +0100 *************** *** 750,751 **** --- 750,753 ---- { /* Add new patch number below this line */ + /**/ + 1407, /**/ -- Two cows are standing together in a field. One asks the other: "So what do you think about this Mad Cow Disease?" The other replies: "That doesn't concern me. I'm a helicopter." /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///