diff options
Diffstat (limited to 'src/lj_str.c')
-rw-r--r-- | src/lj_str.c | 79 |
1 files changed, 55 insertions, 24 deletions
diff --git a/src/lj_str.c b/src/lj_str.c index 20049ab3..dea02858 100644 --- a/src/lj_str.c +++ b/src/lj_str.c | |||
@@ -172,13 +172,25 @@ void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s) | |||
172 | /* Convert string object to number. */ | 172 | /* Convert string object to number. */ |
173 | int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n) | 173 | int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n) |
174 | { | 174 | { |
175 | int ok = lj_str_numconv(strdata(str), n); | ||
176 | if (ok && tvisint(n)) | ||
177 | setnumV(n, (lua_Number)intV(n)); | ||
178 | return ok; | ||
179 | } | ||
180 | |||
181 | int LJ_FASTCALL lj_str_tonumber(GCstr *str, TValue *n) | ||
182 | { | ||
175 | return lj_str_numconv(strdata(str), n); | 183 | return lj_str_numconv(strdata(str), n); |
176 | } | 184 | } |
177 | 185 | ||
178 | /* Convert string to number. */ | 186 | /* Convert string to number. */ |
179 | int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n) | 187 | int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n) |
180 | { | 188 | { |
189 | #if LJ_DUALNUM | ||
190 | int sign = 0; | ||
191 | #else | ||
181 | lua_Number sign = 1; | 192 | lua_Number sign = 1; |
193 | #endif | ||
182 | const uint8_t *p = (const uint8_t *)s; | 194 | const uint8_t *p = (const uint8_t *)s; |
183 | while (lj_char_isspace(*p)) p++; | 195 | while (lj_char_isspace(*p)) p++; |
184 | if (*p == '-') { p++; sign = -1; } else if (*p == '+') { p++; } | 196 | if (*p == '-') { p++; sign = -1; } else if (*p == '+') { p++; } |
@@ -189,21 +201,34 @@ int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n) | |||
189 | if (!lj_char_isxdigit(*p)) | 201 | if (!lj_char_isxdigit(*p)) |
190 | return 0; /* Don't accept '0x' without hex digits. */ | 202 | return 0; /* Don't accept '0x' without hex digits. */ |
191 | do { | 203 | do { |
192 | if (k >= 0x10000000) goto parsedbl; | 204 | if (k >= 0x10000000u) goto parsedbl; |
193 | k = (k << 4) + (*p & 15u); | 205 | k = (k << 4) + (*p & 15u); |
194 | if (!lj_char_isdigit(*p)) k += 9; | 206 | if (!lj_char_isdigit(*p)) k += 9; |
195 | p++; | 207 | p++; |
196 | } while (lj_char_isxdigit(*p)); | 208 | } while (lj_char_isxdigit(*p)); |
197 | } else { | 209 | } else { |
198 | while ((uint32_t)(*p - '0') < 10) { | 210 | while ((uint32_t)(*p - '0') < 10) { |
199 | if (k >= 0x19999999) goto parsedbl; | 211 | if (LJ_UNLIKELY(k >= 429496729) && (k != 429496729 || *p > '5')) |
212 | goto parsedbl; | ||
200 | k = k * 10u + (uint32_t)(*p++ - '0'); | 213 | k = k * 10u + (uint32_t)(*p++ - '0'); |
201 | } | 214 | } |
202 | } | 215 | } |
203 | while (LJ_UNLIKELY(lj_char_isspace(*p))) p++; | 216 | while (LJ_UNLIKELY(lj_char_isspace(*p))) p++; |
204 | if (LJ_LIKELY(*p == '\0')) { | 217 | if (LJ_LIKELY(*p == '\0')) { |
205 | setnumV(n, sign * cast_num(k)); | 218 | #if LJ_DUALNUM |
219 | if (!sign) { | ||
220 | if (k < 0x80000000u) { | ||
221 | setintV(n, (int32_t)k); | ||
222 | return 1; | ||
223 | } | ||
224 | } else if (k <= 0x80000000u) { | ||
225 | setintV(n, -(int32_t)k); | ||
226 | return 1; | ||
227 | } | ||
228 | #else | ||
229 | setnumV(n, sign * (lua_Number)k); | ||
206 | return 1; | 230 | return 1; |
231 | #endif | ||
207 | } | 232 | } |
208 | } | 233 | } |
209 | parsedbl: | 234 | parsedbl: |
@@ -239,26 +264,36 @@ size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o) | |||
239 | } | 264 | } |
240 | } | 265 | } |
241 | 266 | ||
267 | /* Print integer to buffer. Returns pointer to start. */ | ||
268 | char * LJ_FASTCALL lj_str_bufint(char *p, int32_t k) | ||
269 | { | ||
270 | uint32_t u = (uint32_t)(k < 0 ? -k : k); | ||
271 | p += 1+10; | ||
272 | do { *--p = (char)('0' + u % 10); } while (u /= 10); | ||
273 | if (k < 0) *--p = '-'; | ||
274 | return p; | ||
275 | } | ||
276 | |||
242 | /* Convert number to string. */ | 277 | /* Convert number to string. */ |
243 | GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np) | 278 | GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np) |
244 | { | 279 | { |
245 | char buf[LUAI_MAXNUMBER2STR]; | 280 | char buf[LJ_STR_NUMBUF]; |
246 | size_t len = lj_str_bufnum(buf, (TValue *)np); | 281 | size_t len = lj_str_bufnum(buf, (TValue *)np); |
247 | return lj_str_new(L, buf, len); | 282 | return lj_str_new(L, buf, len); |
248 | } | 283 | } |
249 | 284 | ||
250 | #if LJ_HASJIT | ||
251 | /* Convert integer to string. */ | 285 | /* Convert integer to string. */ |
252 | GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k) | 286 | GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k) |
253 | { | 287 | { |
254 | char s[1+10]; | 288 | char s[1+10]; |
255 | char *p = s+sizeof(s); | 289 | char *p = lj_str_bufint(s, k); |
256 | uint32_t i = (uint32_t)(k < 0 ? -k : k); | ||
257 | do { *--p = (char)('0' + i % 10); } while (i /= 10); | ||
258 | if (k < 0) *--p = '-'; | ||
259 | return lj_str_new(L, p, (size_t)(s+sizeof(s)-p)); | 290 | return lj_str_new(L, p, (size_t)(s+sizeof(s)-p)); |
260 | } | 291 | } |
261 | #endif | 292 | |
293 | GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o) | ||
294 | { | ||
295 | return tvisint(o) ? lj_str_fromint(L, intV(o)) : lj_str_fromnum(L, &o->n); | ||
296 | } | ||
262 | 297 | ||
263 | /* -- String formatting --------------------------------------------------- */ | 298 | /* -- String formatting --------------------------------------------------- */ |
264 | 299 | ||
@@ -307,38 +342,34 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp) | |||
307 | addchar(L, sb, va_arg(argp, int)); | 342 | addchar(L, sb, va_arg(argp, int)); |
308 | break; | 343 | break; |
309 | case 'd': { | 344 | case 'd': { |
310 | char buff[1+10]; | 345 | char buf[LJ_STR_INTBUF]; |
311 | char *p = buff+sizeof(buff); | 346 | char *p = lj_str_bufint(buf, va_arg(argp, int32_t)); |
312 | int32_t k = va_arg(argp, int32_t); | 347 | addstr(L, sb, p, (MSize)(buf+LJ_STR_INTBUF-p)); |
313 | uint32_t i = (uint32_t)(k < 0 ? -k : k); | ||
314 | do { *--p = (char)('0' + i % 10); } while (i /= 10); | ||
315 | if (k < 0) *--p = '-'; | ||
316 | addstr(L, sb, p, (MSize)(buff+sizeof(buff)-p)); | ||
317 | break; | 348 | break; |
318 | } | 349 | } |
319 | case 'f': { | 350 | case 'f': { |
320 | char buf[LUAI_MAXNUMBER2STR]; | 351 | char buf[LJ_STR_NUMBUF]; |
321 | TValue tv; | 352 | TValue tv; |
322 | MSize len; | 353 | MSize len; |
323 | tv.n = cast_num(va_arg(argp, LUAI_UACNUMBER)); | 354 | tv.n = (lua_Number)(va_arg(argp, LUAI_UACNUMBER)); |
324 | len = (MSize)lj_str_bufnum(buf, &tv); | 355 | len = (MSize)lj_str_bufnum(buf, &tv); |
325 | addstr(L, sb, buf, len); | 356 | addstr(L, sb, buf, len); |
326 | break; | 357 | break; |
327 | } | 358 | } |
328 | case 'p': { | 359 | case 'p': { |
329 | #define FMTP_CHARS (2*sizeof(ptrdiff_t)) | 360 | #define FMTP_CHARS (2*sizeof(ptrdiff_t)) |
330 | char buff[2+FMTP_CHARS]; | 361 | char buf[2+FMTP_CHARS]; |
331 | ptrdiff_t p = (ptrdiff_t)(va_arg(argp, void *)); | 362 | ptrdiff_t p = (ptrdiff_t)(va_arg(argp, void *)); |
332 | ptrdiff_t i, lasti = 2+FMTP_CHARS; | 363 | ptrdiff_t i, lasti = 2+FMTP_CHARS; |
333 | #if LJ_64 | 364 | #if LJ_64 |
334 | if ((p >> 32) == 0) /* Shorten output for true 32 bit pointers. */ | 365 | if ((p >> 32) == 0) /* Shorten output for true 32 bit pointers. */ |
335 | lasti = 2+2*4; | 366 | lasti = 2+2*4; |
336 | #endif | 367 | #endif |
337 | buff[0] = '0'; | 368 | buf[0] = '0'; |
338 | buff[1] = 'x'; | 369 | buf[1] = 'x'; |
339 | for (i = lasti-1; i >= 2; i--, p >>= 4) | 370 | for (i = lasti-1; i >= 2; i--, p >>= 4) |
340 | buff[i] = "0123456789abcdef"[(p & 15)]; | 371 | buf[i] = "0123456789abcdef"[(p & 15)]; |
341 | addstr(L, sb, buff, (MSize)lasti); | 372 | addstr(L, sb, buf, (MSize)lasti); |
342 | break; | 373 | break; |
343 | } | 374 | } |
344 | case '%': | 375 | case '%': |