3 ** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
15 #include "lj_strfmt.h"
17 /* -- Buffer management --------------------------------------------------- */
19 static void buf_grow(SBuf
*sb
, MSize sz
)
21 MSize osz
= sbufsz(sb
), len
= sbuflen(sb
), nsz
= osz
;
23 if (nsz
< LJ_MIN_SBUF
) nsz
= LJ_MIN_SBUF
;
24 while (nsz
< sz
) nsz
+= nsz
;
25 b
= (char *)lj_mem_realloc(sbufL(sb
), sbufB(sb
), osz
, nsz
);
27 setmref(sb
->p
, b
+ len
);
28 setmref(sb
->e
, b
+ nsz
);
31 LJ_NOINLINE
char *LJ_FASTCALL
lj_buf_need2(SBuf
*sb
, MSize sz
)
33 lua_assert(sz
> sbufsz(sb
));
34 if (LJ_UNLIKELY(sz
> LJ_MAX_BUF
))
35 lj_err_mem(sbufL(sb
));
40 LJ_NOINLINE
char *LJ_FASTCALL
lj_buf_more2(SBuf
*sb
, MSize sz
)
42 MSize len
= sbuflen(sb
);
43 lua_assert(sz
> sbufleft(sb
));
44 if (LJ_UNLIKELY(sz
> LJ_MAX_BUF
|| len
+ sz
> LJ_MAX_BUF
))
45 lj_err_mem(sbufL(sb
));
46 buf_grow(sb
, len
+ sz
);
50 void LJ_FASTCALL
lj_buf_shrink(lua_State
*L
, SBuf
*sb
)
53 MSize osz
= (MSize
)(sbufE(sb
) - b
);
54 if (osz
> 2*LJ_MIN_SBUF
) {
55 MSize n
= (MSize
)(sbufP(sb
) - b
);
56 b
= lj_mem_realloc(L
, b
, osz
, (osz
>> 1));
58 setmref(sb
->p
, b
+ n
);
59 setmref(sb
->e
, b
+ (osz
>> 1));
63 char * LJ_FASTCALL
lj_buf_tmp(lua_State
*L
, MSize sz
)
65 SBuf
*sb
= &G(L
)->tmpbuf
;
67 return lj_buf_need(sb
, sz
);
70 /* -- Low-level buffer put operations ------------------------------------- */
72 SBuf
*lj_buf_putmem(SBuf
*sb
, const void *q
, MSize len
)
74 char *p
= lj_buf_more(sb
, len
);
75 p
= lj_buf_wmem(p
, q
, len
);
81 SBuf
* LJ_FASTCALL
lj_buf_putchar(SBuf
*sb
, int c
)
83 char *p
= lj_buf_more(sb
, 1);
90 SBuf
* LJ_FASTCALL
lj_buf_putstr(SBuf
*sb
, GCstr
*s
)
93 char *p
= lj_buf_more(sb
, len
);
94 p
= lj_buf_wmem(p
, strdata(s
), len
);
99 /* -- High-level buffer put operations ------------------------------------ */
101 SBuf
* LJ_FASTCALL
lj_buf_putstr_reverse(SBuf
*sb
, GCstr
*s
)
104 char *p
= lj_buf_more(sb
, len
), *e
= p
+len
;
105 const char *q
= strdata(s
)+len
-1;
112 SBuf
* LJ_FASTCALL
lj_buf_putstr_lower(SBuf
*sb
, GCstr
*s
)
115 char *p
= lj_buf_more(sb
, len
), *e
= p
+len
;
116 const char *q
= strdata(s
);
117 for (; p
< e
; p
++, q
++) {
118 uint32_t c
= *(unsigned char *)q
;
120 *p
= c
+ ((c
>= 'A' && c
<= 'Z') << 5);
122 if (c
>= 'A' && c
<= 'Z') c
+= 0x20;
130 SBuf
* LJ_FASTCALL
lj_buf_putstr_upper(SBuf
*sb
, GCstr
*s
)
133 char *p
= lj_buf_more(sb
, len
), *e
= p
+len
;
134 const char *q
= strdata(s
);
135 for (; p
< e
; p
++, q
++) {
136 uint32_t c
= *(unsigned char *)q
;
138 *p
= c
- ((c
>= 'a' && c
<= 'z') << 5);
140 if (c
>= 'a' && c
<= 'z') c
-= 0x20;
148 SBuf
*lj_buf_putstr_rep(SBuf
*sb
, GCstr
*s
, int32_t rep
)
151 if (rep
> 0 && len
) {
152 uint64_t tlen
= (uint64_t)rep
* len
;
154 if (LJ_UNLIKELY(tlen
> LJ_MAX_STR
))
155 lj_err_mem(sbufL(sb
));
156 p
= lj_buf_more(sb
, (MSize
)tlen
);
157 if (len
== 1) { /* Optimize a common case. */
158 uint32_t c
= strdata(s
)[0];
159 do { *p
++ = c
; } while (--rep
> 0);
161 const char *e
= strdata(s
) + len
;
163 const char *q
= strdata(s
);
164 do { *p
++ = *q
++; } while (q
< e
);
172 SBuf
*lj_buf_puttab(SBuf
*sb
, GCtab
*t
, GCstr
*sep
, int32_t i
, int32_t e
)
174 MSize seplen
= sep
? sep
->len
: 0;
177 cTValue
*o
= lj_tab_getint(t
, i
);
180 badtype
: /* Error: bad element type. */
181 setsbufP(sb
, (void *)(intptr_t)i
); /* Store failing index. */
183 } else if (tvisstr(o
)) {
184 MSize len
= strV(o
)->len
;
185 p
= lj_buf_wmem(lj_buf_more(sb
, len
+ seplen
), strVdata(o
), len
);
186 } else if (tvisint(o
)) {
187 p
= lj_strfmt_wint(lj_buf_more(sb
, STRFMT_MAXBUF_INT
+seplen
), intV(o
));
188 } else if (tvisnum(o
)) {
189 p
= lj_strfmt_wnum(lj_buf_more(sb
, STRFMT_MAXBUF_NUM
+seplen
), o
);
197 if (seplen
) p
= lj_buf_wmem(p
, strdata(sep
), seplen
);
204 /* -- Miscellaneous buffer operations ------------------------------------- */
206 GCstr
* LJ_FASTCALL
lj_buf_tostr(SBuf
*sb
)
208 return lj_str_new(sbufL(sb
), sbufB(sb
), sbuflen(sb
));
211 /* Concatenate two strings. */
212 GCstr
*lj_buf_cat2str(lua_State
*L
, GCstr
*s1
, GCstr
*s2
)
214 MSize len1
= s1
->len
, len2
= s2
->len
;
215 char *buf
= lj_buf_tmp(L
, len1
+ len2
);
216 memcpy(buf
, strdata(s1
), len1
);
217 memcpy(buf
+len1
, strdata(s2
), len2
);
218 return lj_str_new(L
, buf
, len1
+ len2
);
221 /* Read ULEB128 from buffer. */
222 uint32_t LJ_FASTCALL
lj_buf_ruleb128(const char **pp
)
224 const uint8_t *p
= (const uint8_t *)*pp
;
226 if (LJ_UNLIKELY(v
>= 0x80)) {
229 do { v
|= ((*p
& 0x7f) << (sh
+= 7)); } while (*p
++ >= 0x80);
231 *pp
= (const char *)p
;