** convert an hexadecimal numeric string to a number, following ** C99 specification for 'strtod' */
| 191 | ** C99 specification for 'strtod' |
| 192 | */ |
| 193 | static lua_Number lua_strx2number (const char *s, char **endptr) { |
| 194 | int dot = lua_getlocaledecpoint(); |
| 195 | lua_Number r = 0.0; /* result (accumulator) */ |
| 196 | int sigdig = 0; /* number of significant digits */ |
| 197 | int nosigdig = 0; /* number of non-significant digits */ |
| 198 | int e = 0; /* exponent correction */ |
| 199 | int neg; /* 1 if number is negative */ |
| 200 | int hasdot = 0; /* true after seen a dot */ |
| 201 | *endptr = cast(char *, s); /* nothing is valid yet */ |
| 202 | while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ |
| 203 | neg = isneg(&s); /* check signal */ |
| 204 | if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ |
| 205 | return 0.0; /* invalid format (no '0x') */ |
| 206 | for (s += 2; ; s++) { /* skip '0x' and read numeral */ |
| 207 | if (*s == dot) { |
| 208 | if (hasdot) break; /* second dot? stop loop */ |
| 209 | else hasdot = 1; |
| 210 | } |
| 211 | else if (lisxdigit(cast_uchar(*s))) { |
| 212 | if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */ |
| 213 | nosigdig++; |
| 214 | else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ |
| 215 | r = (r * cast_num(16.0)) + luaO_hexavalue(*s); |
| 216 | else e++; /* too many digits; ignore, but still count for exponent */ |
| 217 | if (hasdot) e--; /* decimal digit? correct exponent */ |
| 218 | } |
| 219 | else break; /* neither a dot nor a digit */ |
| 220 | } |
| 221 | if (nosigdig + sigdig == 0) /* no digits? */ |
| 222 | return 0.0; /* invalid format */ |
| 223 | *endptr = cast(char *, s); /* valid up to here */ |
| 224 | e *= 4; /* each digit multiplies/divides value by 2^4 */ |
| 225 | if (*s == 'p' || *s == 'P') { /* exponent part? */ |
| 226 | int exp1 = 0; /* exponent value */ |
| 227 | int neg1; /* exponent signal */ |
| 228 | s++; /* skip 'p' */ |
| 229 | neg1 = isneg(&s); /* signal */ |
| 230 | if (!lisdigit(cast_uchar(*s))) |
| 231 | return 0.0; /* invalid; must have at least one digit */ |
| 232 | while (lisdigit(cast_uchar(*s))) /* read exponent */ |
| 233 | exp1 = exp1 * 10 + *(s++) - '0'; |
| 234 | if (neg1) exp1 = -exp1; |
| 235 | e += exp1; |
| 236 | *endptr = cast(char *, s); /* valid up to here */ |
| 237 | } |
| 238 | if (neg) r = -r; |
| 239 | return l_mathop(ldexp)(r, e); |
| 240 | } |
| 241 | |
| 242 | #endif |
| 243 | /* }====================================================== */ |
no test coverage detected