diff --git a/src/lib_string.c b/src/lib_string.c index 09010b15..eb2ae226 100644 --- a/src/lib_string.c +++ b/src/lib_string.c @@ -881,14 +881,10 @@ LJLIB_CF(string_format) tv.n = lj_lib_checknum(L, arg); if (LJ_UNLIKELY((tv.u32.hi << 1) >= 0xffe00000)) { /* Canonicalize output of non-finite values. */ - char *p, nbuf[LJ_STR_NUMBUF]; - MSize n = lj_str_bufnum(nbuf, &tv); - if (fmt[-1] < 'a') { - nbuf[n-3] = nbuf[n-3] - 0x20; - nbuf[n-2] = nbuf[n-2] - 0x20; - nbuf[n-1] = nbuf[n-1] - 0x20; - } - nbuf[n] = '\0'; + char nbuf[LJ_STR_NUMBUF]; + char *p = lj_str_bufnum(nbuf, &tv); + if (fmt[-1] < 'a') { *(p-3) -= 0x20; *(p-2) -= 0x20; *(p-1) -= 0x20; } + *p = '\0'; for (p = spec; *p < 'A' && *p != '.'; p++) ; *p++ = 's'; *p = '\0'; len = (MSize)sprintf(buf, spec, nbuf); @@ -901,8 +897,9 @@ LJLIB_CF(string_format) string_fmt_quoted(sb, lj_lib_checkstr(L, arg)); continue; case 'p': - len = lj_str_bufptr(buf, lua_topointer(L, arg)); - break; + setsbufP(sb, lj_str_bufptr(lj_buf_more(sb, LJ_STR_PTRBUF), + lua_topointer(L, arg))); + continue; case 's': { GCstr *str = string_fmt_tostring(L, arg); if (!strchr(spec, '.') && str->len >= 100) { /* Format overflow? */ diff --git a/src/lj_ctype.c b/src/lj_ctype.c index 69ba76d1..f9e75fd1 100644 --- a/src/lj_ctype.c +++ b/src/lj_ctype.c @@ -568,19 +568,19 @@ GCstr *lj_ctype_repr_int64(lua_State *L, uint64_t n, int isunsigned) /* Convert complex to string with 'i' or 'I' suffix. */ GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size) { - char buf[2*LJ_STR_NUMBUF+2+1]; + char buf[2*LJ_STR_NUMBUF+2+1], *p = buf; TValue re, im; - MSize len; if (size == 2*sizeof(double)) { re.n = *(double *)sp; im.n = ((double *)sp)[1]; } else { re.n = (double)*(float *)sp; im.n = (double)((float *)sp)[1]; } - len = lj_str_bufnum(buf, &re); - if (!(im.u32.hi & 0x80000000u) || im.n != im.n) buf[len++] = '+'; - len += lj_str_bufnum(buf+len, &im); - buf[len] = buf[len-1] >= 'a' ? 'I' : 'i'; - return lj_str_new(L, buf, len+1); + p = lj_str_bufnum(p, &re); + if (!(im.u32.hi & 0x80000000u) || im.n != im.n) *p++ = '+'; + p = lj_str_bufnum(p, &im); + *p = *(p-1) >= 'a' ? 'I' : 'i'; + p++; + return lj_str_new(L, buf, p-buf); } /* -- C type state -------------------------------------------------------- */ diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index 4f6aeb37..32346d22 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c @@ -79,10 +79,7 @@ static GCstr *argv2str(jit_State *J, TValue *o) GCstr *s; if (!tvisnumber(o)) lj_trace_err(J, LJ_TRERR_BADTYPE); - if (tvisint(o)) - s = lj_str_fromint(J->L, intV(o)); - else - s = lj_str_fromnum(J->L, &o->n); + s = lj_str_fromnumber(J->L, o); setstrV(J->L, o, s); return s; } diff --git a/src/lj_str.c b/src/lj_str.c index 9eb04c57..a0080e31 100644 --- a/src/lj_str.c +++ b/src/lj_str.c @@ -168,41 +168,62 @@ void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s) /* -- Type conversions ---------------------------------------------------- */ /* Print number to buffer. Canonicalizes non-finite values. */ -MSize LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o) +char * LJ_FASTCALL lj_str_bufnum(char *p, cTValue *o) { if (LJ_LIKELY((o->u32.hi << 1) < 0xffe00000)) { /* Finite? */ - lua_Number n = o->n; #if __BIONIC__ - if (tvismzero(o)) { s[0] = '-'; s[1] = '0'; return 2; } + if (tvismzero(o)) { *p++ = '-'; *p++ = '0'; return p; } #endif - return (MSize)lua_number2str(s, n); + return p + lua_number2str(p, o->n); } else if (((o->u32.hi & 0x000fffff) | o->u32.lo) != 0) { - s[0] = 'n'; s[1] = 'a'; s[2] = 'n'; return 3; + *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; } else if ((o->u32.hi & 0x80000000) == 0) { - s[0] = 'i'; s[1] = 'n'; s[2] = 'f'; return 3; + *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; } else { - s[0] = '-'; s[1] = 'i'; s[2] = 'n'; s[3] = 'f'; return 4; + *p++ = '-'; *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; } + return p; } -/* Print integer to buffer. Returns pointer to start (!= buffer start). */ -static char *str_bufint(char *p, int32_t k) +#define STR_BUFINT_R(x, sh, sc) \ + { uint32_t d = (x*(((1<>sh; x -= d*sc; *p++ = (char)('0'+d); } + +/* Print integer to buffer. */ +char * LJ_FASTCALL lj_str_bufint(char *p, int32_t k) { - uint32_t u = (uint32_t)(k < 0 ? -k : k); - p += LJ_STR_INTBUF; - do { *--p = (char)('0' + u % 10); } while (u /= 10); - if (k < 0) *--p = '-'; + uint32_t u = (uint32_t)k; + if (k < 0) { u = (uint32_t)-k; *p++ = '-'; } + if (u < 10000) { + if (u < 10) goto dig1; if (u < 100) goto dig2; if (u < 1000) goto dig3; + } else { + uint32_t v = u / 10000; u -= v * 10000; + if (v < 10000) { + if (v < 10) goto dig5; if (v < 100) goto dig6; if (v < 1000) goto dig7; + } else { + uint32_t w = v / 10000; v -= w * 10000; + if (w >= 10) STR_BUFINT_R(w, 10, 10) + *p++ = (char)('0'+w); + } + STR_BUFINT_R(v, 23, 1000) + dig7: STR_BUFINT_R(v, 12, 100) + dig6: STR_BUFINT_R(v, 10, 10) + dig5: *p++ = (char)('0'+v); + } + STR_BUFINT_R(u, 23, 1000) + dig3: STR_BUFINT_R(u, 12, 100) + dig2: STR_BUFINT_R(u, 10, 10) + dig1: *p++ = (char)('0'+u); return p; } /* Print pointer to buffer. */ -MSize LJ_FASTCALL lj_str_bufptr(char *p, const void *v) +char * LJ_FASTCALL lj_str_bufptr(char *p, const void *v) { ptrdiff_t x = (ptrdiff_t)v; MSize i, n = LJ_STR_PTRBUF; if (x == 0) { - p[0] = 'N'; p[1] = 'U'; p[2] = 'L'; p[3] = 'L'; - return 4; + *p++ = 'N'; *p++ = 'U'; *p++ = 'L'; *p++ = 'L'; + return p; } #if LJ_64 /* Shorten output for 64 bit pointers. */ @@ -212,7 +233,7 @@ MSize LJ_FASTCALL lj_str_bufptr(char *p, const void *v) p[1] = 'x'; for (i = n-1; i >= 2; i--, x >>= 4) p[i] = "0123456789abcdef"[(x & 15)]; - return n; + return p+n; } /* Print TValue to buffer (only for numbers) and return pointer to start. */ @@ -222,11 +243,10 @@ const char *lj_str_buftv(char *buf, cTValue *o, MSize *lenp) *lenp = strV(o)->len; return strVdata(o); } else if (tvisint(o)) { - char *p = str_bufint(buf, intV(o)); - *lenp = (MSize)(buf+LJ_STR_INTBUF-p); - return p; + *lenp = (MSize)(lj_str_bufint(buf, intV(o)) - buf); + return buf; } else if (tvisnum(o)) { - *lenp = lj_str_bufnum(buf, o); + *lenp = (MSize)(lj_str_bufnum(buf, o) - buf); return buf; } else { return NULL; @@ -237,7 +257,7 @@ const char *lj_str_buftv(char *buf, cTValue *o, MSize *lenp) GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np) { char buf[LJ_STR_NUMBUF]; - MSize len = lj_str_bufnum(buf, (TValue *)np); + MSize len = (MSize)(lj_str_bufnum(buf, (TValue *)np) - buf); return lj_str_new(L, buf, len); } @@ -245,8 +265,8 @@ GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np) GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k) { char buf[LJ_STR_INTBUF]; - char *p = str_bufint(buf, k); - return lj_str_new(L, p, (size_t)(buf+sizeof(buf)-p)); + MSize len = (MSize)(lj_str_bufint(buf, k) - buf); + return lj_str_new(L, buf, len); } GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o) @@ -278,28 +298,20 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp) case 'c': lj_buf_putb(sb, va_arg(argp, int)); break; - case 'd': { - char buf[LJ_STR_INTBUF]; - char *p = str_bufint(buf, va_arg(argp, int32_t)); - lj_buf_putmem(sb, p, (MSize)(buf+LJ_STR_INTBUF-p)); + case 'd': + setsbufP(sb, lj_str_bufint(lj_buf_more(sb, LJ_STR_INTBUF), + va_arg(argp, int32_t))); break; - } case 'f': { - char buf[LJ_STR_NUMBUF]; TValue tv; - MSize len; - tv.n = (lua_Number)(va_arg(argp, LUAI_UACNUMBER)); - len = (MSize)lj_str_bufnum(buf, &tv); - lj_buf_putmem(sb, buf, len); + tv.n = va_arg(argp, lua_Number); + setsbufP(sb, lj_str_bufnum(lj_buf_more(sb, LJ_STR_NUMBUF), &tv)); break; } - case 'p': { -#define FMTP_CHARS (2*sizeof(ptrdiff_t)) - char buf[LJ_STR_PTRBUF]; - MSize len = lj_str_bufptr(buf, va_arg(argp, void *)); - lj_buf_putmem(sb, buf, len); + case 'p': + setsbufP(sb, lj_str_bufptr(lj_buf_more(sb, LJ_STR_PTRBUF), + va_arg(argp, void *))); break; - } case '%': lj_buf_putb(sb, '%'); break; diff --git a/src/lj_str.h b/src/lj_str.h index 6317e794..61666a2a 100644 --- a/src/lj_str.h +++ b/src/lj_str.h @@ -20,8 +20,9 @@ LJ_FUNC void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s); #define lj_str_newlit(L, s) (lj_str_new(L, "" s, sizeof(s)-1)) /* Type conversions. */ -LJ_FUNC MSize LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o); -LJ_FUNC MSize LJ_FASTCALL lj_str_bufptr(char *p, const void *v); +LJ_FUNC char * LJ_FASTCALL lj_str_bufint(char *buf, int32_t k); +LJ_FUNC char * LJ_FASTCALL lj_str_bufnum(char *p, cTValue *o); +LJ_FUNC char * LJ_FASTCALL lj_str_bufptr(char *p, const void *v); LJ_FUNC const char *lj_str_buftv(char *buf, cTValue *o, MSize *lenp); LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np); LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k);