diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2016-05-02 11:00:32 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2016-05-02 11:00:32 -0300 |
commit | ed110f66c5af4fd804567a3cd5a7250eb5eb239b (patch) | |
tree | 5c42ce39d025ae11c6da2938985f1677fa27f8ed /lobject.c | |
parent | 22093f9c6ef0e21244603883eed740d34d9fd63f (diff) | |
download | lua-ed110f66c5af4fd804567a3cd5a7250eb5eb239b.tar.gz lua-ed110f66c5af4fd804567a3cd5a7250eb5eb239b.tar.bz2 lua-ed110f66c5af4fd804567a3cd5a7250eb5eb239b.zip |
'luaO_str2num' (and, therefore, 'lua_stringtonumber', 'number',
and coercions) accepts both the locale point and a dot as its
radix character
Diffstat (limited to 'lobject.c')
-rw-r--r-- | lobject.c | 56 |
1 files changed, 46 insertions, 10 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.c,v 2.108 2015/11/02 16:09:30 roberto Exp roberto $ | 2 | ** $Id: lobject.c,v 2.109 2015/12/14 11:53:27 roberto Exp roberto $ |
3 | ** Some generic functions over Lua objects | 3 | ** Some generic functions over Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -243,17 +243,53 @@ static lua_Number lua_strx2number (const char *s, char **endptr) { | |||
243 | /* }====================================================== */ | 243 | /* }====================================================== */ |
244 | 244 | ||
245 | 245 | ||
246 | static const char *l_str2d (const char *s, lua_Number *result) { | 246 | /* maximum length of a numeral */ |
247 | #if !defined (L_MAXLENNUM) | ||
248 | #define L_MAXLENNUM 200 | ||
249 | #endif | ||
250 | |||
251 | static const char *l_str2dloc (const char *s, lua_Number *result, int mode) { | ||
247 | char *endptr; | 252 | char *endptr; |
248 | if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ | 253 | *result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */ |
254 | : lua_str2number(s, &endptr); | ||
255 | if (endptr == s) return NULL; /* nothing recognized? */ | ||
256 | while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */ | ||
257 | return (*endptr == '\0') ? endptr : NULL; /* OK if no trailing characters */ | ||
258 | } | ||
259 | |||
260 | |||
261 | /* | ||
262 | ** Convert string 's' to a Lua number (put in 'result'). Return NULL | ||
263 | ** on fail or the address of the ending '\0' on success. | ||
264 | ** 'pmode' points to (and 'mode' contains) special things in the string: | ||
265 | ** - 'x'/'X' means an hexadecimal numeral | ||
266 | ** - 'n'/'N' means 'inf' or 'nan' (which should be rejected) | ||
267 | ** - '.' just optimizes the search for the common case (nothing special) | ||
268 | ** This function accepts both the current locale or a dot as the radix | ||
269 | ** mark. If the convertion fails, it may mean number has a dot but | ||
270 | ** locale accepts something else. In that case, the code copies 's' | ||
271 | ** to a buffer (because 's' is read-only), changes the dot to the | ||
272 | ** current locale radix mark, and tries to convert again. | ||
273 | */ | ||
274 | static const char *l_str2d (const char *s, lua_Number *result) { | ||
275 | const char *endptr; | ||
276 | const char *pmode = strpbrk(s, ".xXnN"); | ||
277 | int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0; | ||
278 | if (mode == 'n') /* reject 'inf' and 'nan' */ | ||
249 | return NULL; | 279 | return NULL; |
250 | else if (strpbrk(s, "xX")) /* hex? */ | 280 | endptr = l_str2dloc(s, result, mode); /* try to convert */ |
251 | *result = lua_strx2number(s, &endptr); | 281 | if (endptr == NULL) { /* failed? may be a different locale */ |
252 | else | 282 | char buff[L_MAXLENNUM + 1]; |
253 | *result = lua_str2number(s, &endptr); | 283 | char *pdot = strchr(s, '.'); |
254 | if (endptr == s) return NULL; /* nothing recognized */ | 284 | if (strlen(s) > L_MAXLENNUM || pdot == NULL) |
255 | while (lisspace(cast_uchar(*endptr))) endptr++; | 285 | return NULL; /* string too long or no dot; fail */ |
256 | return (*endptr == '\0' ? endptr : NULL); /* OK if no trailing characters */ | 286 | strcpy(buff, s); /* copy string to buffer */ |
287 | buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */ | ||
288 | endptr = l_str2dloc(buff, result, mode); /* try again */ | ||
289 | if (endptr != NULL) | ||
290 | endptr = s + (endptr - buff); /* make relative to 's' */ | ||
291 | } | ||
292 | return endptr; | ||
257 | } | 293 | } |
258 | 294 | ||
259 | 295 | ||