** convert a hexadecimal numeric string to a number, following ** C99 specification for 'strtod' */
| 226 | ** C99 specification for 'strtod' |
| 227 | */ |
| 228 | static lua_Number lua_strx2number (const char *s, char **endptr) { |
| 229 | int dot = lua_getlocaledecpoint(); |
| 230 | lua_Number r = l_mathop(0.0); /* result (accumulator) */ |
| 231 | int sigdig = 0; /* number of significant digits */ |
| 232 | int nosigdig = 0; /* number of non-significant digits */ |
| 233 | int e = 0; /* exponent correction */ |
| 234 | int neg; /* 1 if number is negative */ |
| 235 | int hasdot = 0; /* true after seen a dot */ |
| 236 | *endptr = cast_charp(s); /* nothing is valid yet */ |
| 237 | while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ |
| 238 | neg = isneg(&s); /* check sign */ |
| 239 | if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ |
| 240 | return l_mathop(0.0); /* invalid format (no '0x') */ |
| 241 | for (s += 2; ; s++) { /* skip '0x' and read numeral */ |
| 242 | if (*s == dot) { |
| 243 | if (hasdot) break; /* second dot? stop loop */ |
| 244 | else hasdot = 1; |
| 245 | } |
| 246 | else if (lisxdigit(cast_uchar(*s))) { |
| 247 | if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */ |
| 248 | nosigdig++; |
| 249 | else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ |
| 250 | r = (r * l_mathop(16.0)) + luaO_hexavalue(*s); |
| 251 | else e++; /* too many digits; ignore, but still count for exponent */ |
| 252 | if (hasdot) e--; /* decimal digit? correct exponent */ |
| 253 | } |
| 254 | else break; /* neither a dot nor a digit */ |
| 255 | } |
| 256 | if (nosigdig + sigdig == 0) /* no digits? */ |
| 257 | return l_mathop(0.0); /* invalid format */ |
| 258 | *endptr = cast_charp(s); /* valid up to here */ |
| 259 | e *= 4; /* each digit multiplies/divides value by 2^4 */ |
| 260 | if (*s == 'p' || *s == 'P') { /* exponent part? */ |
| 261 | int exp1 = 0; /* exponent value */ |
| 262 | int neg1; /* exponent sign */ |
| 263 | s++; /* skip 'p' */ |
| 264 | neg1 = isneg(&s); /* sign */ |
| 265 | if (!lisdigit(cast_uchar(*s))) |
| 266 | return l_mathop(0.0); /* invalid; must have at least one digit */ |
| 267 | while (lisdigit(cast_uchar(*s))) /* read exponent */ |
| 268 | exp1 = exp1 * 10 + *(s++) - '0'; |
| 269 | if (neg1) exp1 = -exp1; |
| 270 | e += exp1; |
| 271 | *endptr = cast_charp(s); /* valid up to here */ |
| 272 | } |
| 273 | if (neg) r = -r; |
| 274 | return l_mathop(ldexp)(r, e); |
| 275 | } |
| 276 | |
| 277 | #endif |
| 278 | /* }====================================================== */ |
no test coverage detected