summaryrefslogtreecommitdiff
path: root/src/lj_str.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_str.c')
-rw-r--r--src/lj_str.c79
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. */
173int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n) 173int 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
181int 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. */
179int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n) 187int 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 }
209parsedbl: 234parsedbl:
@@ -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. */
268char * 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. */
243GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np) 278GCstr * 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. */
252GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k) 286GCstr * 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
293GCstr * 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 '%':