diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-05-19 13:29:40 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-05-19 13:29:40 -0300 |
commit | 01c96ad12e1e45d6a36a07ae8ec97c09fd0ff913 (patch) | |
tree | 9517d358c0df8f97a0f336b4dcdfdeb84ef52faa /lstrlib.c | |
parent | 1bdc328c7542fac5101684a4ac31a25be3dff112 (diff) | |
download | lua-01c96ad12e1e45d6a36a07ae8ec97c09fd0ff913.tar.gz lua-01c96ad12e1e45d6a36a07ae8ec97c09fd0ff913.tar.bz2 lua-01c96ad12e1e45d6a36a07ae8ec97c09fd0ff913.zip |
handling of inf, -inf, and NaN by string.format'%q'
Diffstat (limited to 'lstrlib.c')
-rw-r--r-- | lstrlib.c | 42 |
1 files changed, 28 insertions, 14 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstrlib.c,v 1.254 2016/12/22 13:08:50 roberto Exp roberto $ | 2 | ** $Id: lstrlib.c,v 1.255 2017/03/14 12:40:44 roberto Exp roberto $ |
3 | ** Standard library for string operations and pattern-matching | 3 | ** Standard library for string operations and pattern-matching |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -14,6 +14,7 @@ | |||
14 | #include <float.h> | 14 | #include <float.h> |
15 | #include <limits.h> | 15 | #include <limits.h> |
16 | #include <locale.h> | 16 | #include <locale.h> |
17 | #include <math.h> | ||
17 | #include <stddef.h> | 18 | #include <stddef.h> |
18 | #include <stdio.h> | 19 | #include <stdio.h> |
19 | #include <stdlib.h> | 20 | #include <stdlib.h> |
@@ -813,8 +814,6 @@ static int str_gsub (lua_State *L) { | |||
813 | ** Hexadecimal floating-point formatter | 814 | ** Hexadecimal floating-point formatter |
814 | */ | 815 | */ |
815 | 816 | ||
816 | #include <math.h> | ||
817 | |||
818 | #define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) | 817 | #define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) |
819 | 818 | ||
820 | 819 | ||
@@ -929,14 +928,32 @@ static void addquoted (luaL_Buffer *b, const char *s, size_t len) { | |||
929 | 928 | ||
930 | 929 | ||
931 | /* | 930 | /* |
932 | ** Ensures the 'buff' string uses a dot as the radix character. | 931 | ** Serialize a floating-point number in such a way that it can be |
932 | ** scanned back by Lua. Use hexadecimal format for "common" numbers | ||
933 | ** (to preserve precision); inf, -inf, and NaN are handled separately. | ||
934 | ** (NaN cannot be expressed as a numeral, so we write '(0/0)' for it.) | ||
933 | */ | 935 | */ |
934 | static void checkdp (char *buff, int nb) { | 936 | static int quotefloat (lua_State *L, char *buff, lua_Number n) { |
935 | if (memchr(buff, '.', nb) == NULL) { /* no dot? */ | 937 | const char *s; /* for the fixed representations */ |
936 | char point = lua_getlocaledecpoint(); /* try locale point */ | 938 | if (n == (lua_Number)HUGE_VAL) /* inf? */ |
937 | char *ppoint = (char *)memchr(buff, point, nb); | 939 | s = "1e9999"; |
938 | if (ppoint) *ppoint = '.'; /* change it to a dot */ | 940 | else if (n == -(lua_Number)HUGE_VAL) /* -inf? */ |
941 | s = "-1e9999"; | ||
942 | else if (n != n) /* NaN? */ | ||
943 | s = "(0/0)"; | ||
944 | else { /* format number as hexadecimal */ | ||
945 | int nb = lua_number2strx(L, buff, MAX_ITEM, | ||
946 | "%" LUA_NUMBER_FRMLEN "a", n); | ||
947 | /* ensures that 'buff' string uses a dot as the radix character */ | ||
948 | if (memchr(buff, '.', nb) == NULL) { /* no dot? */ | ||
949 | char point = lua_getlocaledecpoint(); /* try locale point */ | ||
950 | char *ppoint = (char *)memchr(buff, point, nb); | ||
951 | if (ppoint) *ppoint = '.'; /* change it to a dot */ | ||
952 | } | ||
953 | return nb; | ||
939 | } | 954 | } |
955 | /* for the fixed representations */ | ||
956 | return l_sprintf(buff, MAX_ITEM, "%s", s); | ||
940 | } | 957 | } |
941 | 958 | ||
942 | 959 | ||
@@ -951,11 +968,8 @@ static void addliteral (lua_State *L, luaL_Buffer *b, int arg) { | |||
951 | case LUA_TNUMBER: { | 968 | case LUA_TNUMBER: { |
952 | char *buff = luaL_prepbuffsize(b, MAX_ITEM); | 969 | char *buff = luaL_prepbuffsize(b, MAX_ITEM); |
953 | int nb; | 970 | int nb; |
954 | if (!lua_isinteger(L, arg)) { /* float? */ | 971 | if (!lua_isinteger(L, arg)) /* float? */ |
955 | lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */ | 972 | nb = quotefloat(L, buff, lua_tonumber(L, arg)); |
956 | nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n); | ||
957 | checkdp(buff, nb); /* ensure it uses a dot */ | ||
958 | } | ||
959 | else { /* integers */ | 973 | else { /* integers */ |
960 | lua_Integer n = lua_tointeger(L, arg); | 974 | lua_Integer n = lua_tointeger(L, arg); |
961 | const char *format = (n == LUA_MININTEGER) /* corner case? */ | 975 | const char *format = (n == LUA_MININTEGER) /* corner case? */ |