** convert a hexadecimal numeric string to a number, following ** C99 specification for 'strtod' */
| 163 | ** C99 specification for 'strtod' |
| 164 | */ |
| 165 | static lua_Number lua_strx2number (const char *s, char **endptr) { |
| 166 | int dot = lua_getlocaledecpoint(); |
| 167 | lua_Number r = 0.0; /* result (accumulator) */ |
| 168 | int sigdig = 0; /* number of significant digits */ |
| 169 | int nosigdig = 0; /* number of non-significant digits */ |
| 170 | int e = 0; /* exponent correction */ |
| 171 | int neg; /* 1 if number is negative */ |
| 172 | int hasdot = 0; /* true after seen a dot */ |
| 173 | *endptr = cast_charp(s); /* nothing is valid yet */ |
| 174 | while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ |
| 175 | neg = isneg(&s); /* check sign */ |
| 176 | if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ |
| 177 | return 0.0; /* invalid format (no '0x') */ |
| 178 | for (s += 2; ; s++) { /* skip '0x' and read numeral */ |
| 179 | if (*s == dot) { |
| 180 | if (hasdot) break; /* second dot? stop loop */ |
| 181 | else hasdot = 1; |
| 182 | } |
| 183 | else if (lisxdigit(cast_uchar(*s))) { |
| 184 | if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */ |
| 185 | nosigdig++; |
| 186 | else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ |
| 187 | r = (r * cast_num(16.0)) + luaO_hexavalue(*s); |
| 188 | else e++; /* too many digits; ignore, but still count for exponent */ |
| 189 | if (hasdot) e--; /* decimal digit? correct exponent */ |
| 190 | } |
| 191 | else break; /* neither a dot nor a digit */ |
| 192 | } |
| 193 | if (nosigdig + sigdig == 0) /* no digits? */ |
| 194 | return 0.0; /* invalid format */ |
| 195 | *endptr = cast_charp(s); /* valid up to here */ |
| 196 | e *= 4; /* each digit multiplies/divides value by 2^4 */ |
| 197 | if (*s == 'p' || *s == 'P') { /* exponent part? */ |
| 198 | int exp1 = 0; /* exponent value */ |
| 199 | int neg1; /* exponent sign */ |
| 200 | s++; /* skip 'p' */ |
| 201 | neg1 = isneg(&s); /* sign */ |
| 202 | if (!lisdigit(cast_uchar(*s))) |
| 203 | return 0.0; /* invalid; must have at least one digit */ |
| 204 | while (lisdigit(cast_uchar(*s))) /* read exponent */ |
| 205 | exp1 = exp1 * 10 + *(s++) - '0'; |
| 206 | if (neg1) exp1 = -exp1; |
| 207 | e += exp1; |
| 208 | *endptr = cast_charp(s); /* valid up to here */ |
| 209 | } |
| 210 | if (neg) r = -r; |
| 211 | return l_mathop(ldexp)(r, e); |
| 212 | } |
| 213 | |
| 214 | #endif |
| 215 | /* }====================================================== */ |
no test coverage detected