aboutsummaryrefslogtreecommitdiff
path: root/src/lj_str.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_str.c')
-rw-r--r--src/lj_str.c140
1 files changed, 65 insertions, 75 deletions
diff --git a/src/lj_str.c b/src/lj_str.c
index 6548ee4d..9eb04c57 100644
--- a/src/lj_str.c
+++ b/src/lj_str.c
@@ -1,9 +1,6 @@
1/* 1/*
2** String handling. 2** String handling.
3** Copyright (C) 2005-2013 Mike Pall. See Copyright Notice in luajit.h 3** Copyright (C) 2005-2013 Mike Pall. See Copyright Notice in luajit.h
4**
5** Portions taken verbatim or adapted from the Lua interpreter.
6** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
7*/ 4*/
8 5
9#include <stdio.h> 6#include <stdio.h>
@@ -14,6 +11,7 @@
14#include "lj_obj.h" 11#include "lj_obj.h"
15#include "lj_gc.h" 12#include "lj_gc.h"
16#include "lj_err.h" 13#include "lj_err.h"
14#include "lj_buf.h"
17#include "lj_str.h" 15#include "lj_str.h"
18#include "lj_state.h" 16#include "lj_state.h"
19#include "lj_char.h" 17#include "lj_char.h"
@@ -170,14 +168,14 @@ void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s)
170/* -- Type conversions ---------------------------------------------------- */ 168/* -- Type conversions ---------------------------------------------------- */
171 169
172/* Print number to buffer. Canonicalizes non-finite values. */ 170/* Print number to buffer. Canonicalizes non-finite values. */
173size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o) 171MSize LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o)
174{ 172{
175 if (LJ_LIKELY((o->u32.hi << 1) < 0xffe00000)) { /* Finite? */ 173 if (LJ_LIKELY((o->u32.hi << 1) < 0xffe00000)) { /* Finite? */
176 lua_Number n = o->n; 174 lua_Number n = o->n;
177#if __BIONIC__ 175#if __BIONIC__
178 if (tvismzero(o)) { s[0] = '-'; s[1] = '0'; return 2; } 176 if (tvismzero(o)) { s[0] = '-'; s[1] = '0'; return 2; }
179#endif 177#endif
180 return (size_t)lua_number2str(s, n); 178 return (MSize)lua_number2str(s, n);
181 } else if (((o->u32.hi & 0x000fffff) | o->u32.lo) != 0) { 179 } else if (((o->u32.hi & 0x000fffff) | o->u32.lo) != 0) {
182 s[0] = 'n'; s[1] = 'a'; s[2] = 'n'; return 3; 180 s[0] = 'n'; s[1] = 'a'; s[2] = 'n'; return 3;
183 } else if ((o->u32.hi & 0x80000000) == 0) { 181 } else if ((o->u32.hi & 0x80000000) == 0) {
@@ -187,30 +185,68 @@ size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o)
187 } 185 }
188} 186}
189 187
190/* Print integer to buffer. Returns pointer to start. */ 188/* Print integer to buffer. Returns pointer to start (!= buffer start). */
191char * LJ_FASTCALL lj_str_bufint(char *p, int32_t k) 189static char *str_bufint(char *p, int32_t k)
192{ 190{
193 uint32_t u = (uint32_t)(k < 0 ? -k : k); 191 uint32_t u = (uint32_t)(k < 0 ? -k : k);
194 p += 1+10; 192 p += LJ_STR_INTBUF;
195 do { *--p = (char)('0' + u % 10); } while (u /= 10); 193 do { *--p = (char)('0' + u % 10); } while (u /= 10);
196 if (k < 0) *--p = '-'; 194 if (k < 0) *--p = '-';
197 return p; 195 return p;
198} 196}
199 197
198/* Print pointer to buffer. */
199MSize LJ_FASTCALL lj_str_bufptr(char *p, const void *v)
200{
201 ptrdiff_t x = (ptrdiff_t)v;
202 MSize i, n = LJ_STR_PTRBUF;
203 if (x == 0) {
204 p[0] = 'N'; p[1] = 'U'; p[2] = 'L'; p[3] = 'L';
205 return 4;
206 }
207#if LJ_64
208 /* Shorten output for 64 bit pointers. */
209 n = 2+2*4+((x >> 32) ? 2+2*(lj_fls((uint32_t)(x >> 32))>>3) : 0);
210#endif
211 p[0] = '0';
212 p[1] = 'x';
213 for (i = n-1; i >= 2; i--, x >>= 4)
214 p[i] = "0123456789abcdef"[(x & 15)];
215 return n;
216}
217
218/* Print TValue to buffer (only for numbers) and return pointer to start. */
219const char *lj_str_buftv(char *buf, cTValue *o, MSize *lenp)
220{
221 if (tvisstr(o)) {
222 *lenp = strV(o)->len;
223 return strVdata(o);
224 } else if (tvisint(o)) {
225 char *p = str_bufint(buf, intV(o));
226 *lenp = (MSize)(buf+LJ_STR_INTBUF-p);
227 return p;
228 } else if (tvisnum(o)) {
229 *lenp = lj_str_bufnum(buf, o);
230 return buf;
231 } else {
232 return NULL;
233 }
234}
235
200/* Convert number to string. */ 236/* Convert number to string. */
201GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np) 237GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np)
202{ 238{
203 char buf[LJ_STR_NUMBUF]; 239 char buf[LJ_STR_NUMBUF];
204 size_t len = lj_str_bufnum(buf, (TValue *)np); 240 MSize len = lj_str_bufnum(buf, (TValue *)np);
205 return lj_str_new(L, buf, len); 241 return lj_str_new(L, buf, len);
206} 242}
207 243
208/* Convert integer to string. */ 244/* Convert integer to string. */
209GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k) 245GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k)
210{ 246{
211 char s[1+10]; 247 char buf[LJ_STR_INTBUF];
212 char *p = lj_str_bufint(s, k); 248 char *p = str_bufint(buf, k);
213 return lj_str_new(L, p, (size_t)(s+sizeof(s)-p)); 249 return lj_str_new(L, p, (size_t)(buf+sizeof(buf)-p));
214} 250}
215 251
216GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o) 252GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o)
@@ -220,54 +256,32 @@ GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o)
220 256
221/* -- String formatting --------------------------------------------------- */ 257/* -- String formatting --------------------------------------------------- */
222 258
223static void addstr(lua_State *L, SBuf *sb, const char *str, MSize len)
224{
225 char *p;
226 MSize i;
227 if (sb->n + len > sb->sz) {
228 MSize sz = sb->sz * 2;
229 while (sb->n + len > sz) sz = sz * 2;
230 lj_str_resizebuf(L, sb, sz);
231 }
232 p = sb->buf + sb->n;
233 sb->n += len;
234 for (i = 0; i < len; i++) p[i] = str[i];
235}
236
237static void addchar(lua_State *L, SBuf *sb, int c)
238{
239 if (sb->n + 1 > sb->sz) {
240 MSize sz = sb->sz * 2;
241 lj_str_resizebuf(L, sb, sz);
242 }
243 sb->buf[sb->n++] = (char)c;
244}
245
246/* Push formatted message as a string object to Lua stack. va_list variant. */ 259/* Push formatted message as a string object to Lua stack. va_list variant. */
247const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp) 260const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
248{ 261{
249 SBuf *sb = &G(L)->tmpbuf; 262 SBuf *sb = &G(L)->tmpbuf;
250 lj_str_needbuf(L, sb, (MSize)strlen(fmt)); 263 setsbufL(sb, L);
251 lj_str_resetbuf(sb); 264 lj_buf_need(sb, (MSize)strlen(fmt));
265 lj_buf_reset(sb);
252 for (;;) { 266 for (;;) {
253 const char *e = strchr(fmt, '%'); 267 const char *e = strchr(fmt, '%');
254 if (e == NULL) break; 268 if (e == NULL) break;
255 addstr(L, sb, fmt, (MSize)(e-fmt)); 269 lj_buf_putmem(sb, fmt, (MSize)(e-fmt));
256 /* This function only handles %s, %c, %d, %f and %p formats. */ 270 /* This function only handles %s, %c, %d, %f and %p formats. */
257 switch (e[1]) { 271 switch (e[1]) {
258 case 's': { 272 case 's': {
259 const char *s = va_arg(argp, char *); 273 const char *s = va_arg(argp, char *);
260 if (s == NULL) s = "(null)"; 274 if (s == NULL) s = "(null)";
261 addstr(L, sb, s, (MSize)strlen(s)); 275 lj_buf_putmem(sb, s, (MSize)strlen(s));
262 break; 276 break;
263 } 277 }
264 case 'c': 278 case 'c':
265 addchar(L, sb, va_arg(argp, int)); 279 lj_buf_putb(sb, va_arg(argp, int));
266 break; 280 break;
267 case 'd': { 281 case 'd': {
268 char buf[LJ_STR_INTBUF]; 282 char buf[LJ_STR_INTBUF];
269 char *p = lj_str_bufint(buf, va_arg(argp, int32_t)); 283 char *p = str_bufint(buf, va_arg(argp, int32_t));
270 addstr(L, sb, p, (MSize)(buf+LJ_STR_INTBUF-p)); 284 lj_buf_putmem(sb, p, (MSize)(buf+LJ_STR_INTBUF-p));
271 break; 285 break;
272 } 286 }
273 case 'f': { 287 case 'f': {
@@ -276,41 +290,28 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
276 MSize len; 290 MSize len;
277 tv.n = (lua_Number)(va_arg(argp, LUAI_UACNUMBER)); 291 tv.n = (lua_Number)(va_arg(argp, LUAI_UACNUMBER));
278 len = (MSize)lj_str_bufnum(buf, &tv); 292 len = (MSize)lj_str_bufnum(buf, &tv);
279 addstr(L, sb, buf, len); 293 lj_buf_putmem(sb, buf, len);
280 break; 294 break;
281 } 295 }
282 case 'p': { 296 case 'p': {
283#define FMTP_CHARS (2*sizeof(ptrdiff_t)) 297#define FMTP_CHARS (2*sizeof(ptrdiff_t))
284 char buf[2+FMTP_CHARS]; 298 char buf[LJ_STR_PTRBUF];
285 ptrdiff_t p = (ptrdiff_t)(va_arg(argp, void *)); 299 MSize len = lj_str_bufptr(buf, va_arg(argp, void *));
286 ptrdiff_t i, lasti = 2+FMTP_CHARS; 300 lj_buf_putmem(sb, buf, len);
287 if (p == 0) {
288 addstr(L, sb, "NULL", 4);
289 break;
290 }
291#if LJ_64
292 /* Shorten output for 64 bit pointers. */
293 lasti = 2+2*4+((p >> 32) ? 2+2*(lj_fls((uint32_t)(p >> 32))>>3) : 0);
294#endif
295 buf[0] = '0';
296 buf[1] = 'x';
297 for (i = lasti-1; i >= 2; i--, p >>= 4)
298 buf[i] = "0123456789abcdef"[(p & 15)];
299 addstr(L, sb, buf, (MSize)lasti);
300 break; 301 break;
301 } 302 }
302 case '%': 303 case '%':
303 addchar(L, sb, '%'); 304 lj_buf_putb(sb, '%');
304 break; 305 break;
305 default: 306 default:
306 addchar(L, sb, '%'); 307 lj_buf_putb(sb, '%');
307 addchar(L, sb, e[1]); 308 lj_buf_putb(sb, e[1]);
308 break; 309 break;
309 } 310 }
310 fmt = e+2; 311 fmt = e+2;
311 } 312 }
312 addstr(L, sb, fmt, (MSize)strlen(fmt)); 313 lj_buf_putmem(sb, fmt, (MSize)strlen(fmt));
313 setstrV(L, L->top, lj_str_new(L, sb->buf, sb->n)); 314 setstrV(L, L->top, lj_buf_str(L, sb));
314 incr_top(L); 315 incr_top(L);
315 return strVdata(L->top - 1); 316 return strVdata(L->top - 1);
316} 317}
@@ -326,14 +327,3 @@ const char *lj_str_pushf(lua_State *L, const char *fmt, ...)
326 return msg; 327 return msg;
327} 328}
328 329
329/* -- Buffer handling ----------------------------------------------------- */
330
331char *lj_str_needbuf(lua_State *L, SBuf *sb, MSize sz)
332{
333 if (sz > sb->sz) {
334 if (sz < LJ_MIN_SBUF) sz = LJ_MIN_SBUF;
335 lj_str_resizebuf(L, sb, sz);
336 }
337 return sb->buf;
338}
339