aboutsummaryrefslogtreecommitdiff
path: root/src/lj_buf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_buf.c')
-rw-r--r--src/lj_buf.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/src/lj_buf.c b/src/lj_buf.c
new file mode 100644
index 00000000..1786c10d
--- /dev/null
+++ b/src/lj_buf.c
@@ -0,0 +1,222 @@
1/*
2** Buffer handling.
3** Copyright (C) 2005-2013 Mike Pall. See Copyright Notice in luajit.h
4*/
5
6#include <stdio.h>
7
8#define lj_buf_c
9#define LUA_CORE
10
11#include "lj_obj.h"
12#include "lj_gc.h"
13#include "lj_err.h"
14#include "lj_buf.h"
15#include "lj_str.h"
16#include "lj_tab.h"
17#include "lj_strfmt.h"
18
19/* -- Buffer management --------------------------------------------------- */
20
21LJ_NOINLINE void LJ_FASTCALL lj_buf_grow(SBuf *sb, char *en)
22{
23 lua_State *L = sbufL(sb);
24 char *b = sbufB(sb);
25 MSize sz = (MSize)(en - b);
26 MSize osz = (MSize)(sbufE(sb) - b), nsz = osz;
27 MSize n = (MSize)(sbufP(sb) - b);
28 if (LJ_UNLIKELY(sz > LJ_MAX_MEM))
29 lj_err_mem(L);
30 if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF;
31 while (nsz < sz) nsz += nsz;
32 b = (char *)lj_mem_realloc(L, b, osz, nsz);
33 setmref(sb->b, b);
34 setmref(sb->p, b + n);
35 setmref(sb->e, b + nsz);
36}
37
38void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb)
39{
40 char *b = sbufB(sb);
41 MSize osz = (MSize)(sbufE(sb) - b);
42 if (osz > 2*LJ_MIN_SBUF) {
43 MSize n = (MSize)(sbufP(sb) - b);
44 b = lj_mem_realloc(L, b, osz, (osz >> 1));
45 setmref(sb->b, b);
46 setmref(sb->p, b + n);
47 setmref(sb->e, b + (osz >> 1));
48 }
49}
50
51char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz)
52{
53 SBuf *sb = &G(L)->tmpbuf;
54 setsbufL(sb, L);
55 return lj_buf_need(sb, sz);
56}
57
58/* -- Low-level buffer put operations ------------------------------------- */
59
60SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len)
61{
62 char *p = lj_buf_more(sb, len);
63 p = lj_buf_wmem(p, q, len);
64 setsbufP(sb, p);
65 return sb;
66}
67
68#if LJ_HASJIT
69SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c)
70{
71 char *p = lj_buf_more(sb, 1);
72 *p++ = (char)c;
73 setsbufP(sb, p);
74 return sb;
75}
76#endif
77
78SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s)
79{
80 MSize len = s->len;
81 char *p = lj_buf_more(sb, len);
82 p = lj_buf_wmem(p, strdata(s), len);
83 setsbufP(sb, p);
84 return sb;
85}
86
87/* -- High-level buffer put operations ------------------------------------ */
88
89SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s)
90{
91 MSize len = s->len;
92 char *p = lj_buf_more(sb, len), *e = p+len;
93 const char *q = strdata(s)+len-1;
94 while (p < e)
95 *p++ = *q--;
96 setsbufP(sb, p);
97 return sb;
98}
99
100SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s)
101{
102 MSize len = s->len;
103 char *p = lj_buf_more(sb, len), *e = p+len;
104 const char *q = strdata(s);
105 for (; p < e; p++, q++) {
106 uint32_t c = *(unsigned char *)q;
107#if LJ_TARGET_PPC
108 *p = c + ((c >= 'A' && c <= 'Z') << 5);
109#else
110 if (c >= 'A' && c <= 'Z') c += 0x20;
111 *p = c;
112#endif
113 }
114 setsbufP(sb, p);
115 return sb;
116}
117
118SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s)
119{
120 MSize len = s->len;
121 char *p = lj_buf_more(sb, len), *e = p+len;
122 const char *q = strdata(s);
123 for (; p < e; p++, q++) {
124 uint32_t c = *(unsigned char *)q;
125#if LJ_TARGET_PPC
126 *p = c - ((c >= 'a' && c <= 'z') << 5);
127#else
128 if (c >= 'a' && c <= 'z') c -= 0x20;
129 *p = c;
130#endif
131 }
132 setsbufP(sb, p);
133 return sb;
134}
135
136SBuf *lj_buf_putstr_rep(SBuf *sb, GCstr *s, int32_t rep)
137{
138 MSize len = s->len;
139 if (rep > 0 && len) {
140 uint64_t tlen = (uint64_t)rep * len;
141 char *p;
142 if (LJ_UNLIKELY(tlen > LJ_MAX_STR))
143 lj_err_mem(sbufL(sb));
144 p = lj_buf_more(sb, (MSize)tlen);
145 if (len == 1) { /* Optimize a common case. */
146 uint32_t c = strdata(s)[0];
147 do { *p++ = c; } while (--rep > 0);
148 } else {
149 const char *e = strdata(s) + len;
150 do {
151 const char *q = strdata(s);
152 do { *p++ = *q++; } while (q < e);
153 } while (--rep > 0);
154 }
155 setsbufP(sb, p);
156 }
157 return sb;
158}
159
160SBuf *lj_buf_puttab(SBuf *sb, GCtab *t, GCstr *sep, int32_t i, int32_t e)
161{
162 MSize seplen = sep ? sep->len : 0;
163 if (i <= e) {
164 for (;;) {
165 cTValue *o = lj_tab_getint(t, i);
166 char *p;
167 if (!o) {
168 badtype: /* Error: bad element type. */
169 setsbufP(sb, (intptr_t)i); /* Store failing index. */
170 return NULL;
171 } else if (tvisstr(o)) {
172 MSize len = strV(o)->len;
173 p = lj_buf_wmem(lj_buf_more(sb, len + seplen), strVdata(o), len);
174 } else if (tvisint(o)) {
175 p = lj_strfmt_wint(lj_buf_more(sb, STRFMT_MAXBUF_INT+seplen), intV(o));
176 } else if (tvisnum(o)) {
177 p = lj_strfmt_wnum(lj_buf_more(sb, STRFMT_MAXBUF_NUM+seplen), o);
178 } else {
179 goto badtype;
180 }
181 if (i++ == e) {
182 setsbufP(sb, p);
183 break;
184 }
185 if (seplen) p = lj_buf_wmem(p, strdata(sep), seplen);
186 setsbufP(sb, p);
187 }
188 }
189 return sb;
190}
191
192/* -- Miscellaneous buffer operations ------------------------------------- */
193
194GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb)
195{
196 return lj_str_new(sbufL(sb), sbufB(sb), sbuflen(sb));
197}
198
199/* Concatenate two strings. */
200GCstr *lj_buf_cat2str(lua_State *L, GCstr *s1, GCstr *s2)
201{
202 MSize len1 = s1->len, len2 = s2->len;
203 char *buf = lj_buf_tmp(L, len1 + len2);
204 memcpy(buf, strdata(s1), len1);
205 memcpy(buf+len1, strdata(s2), len2);
206 return lj_str_new(L, buf, len1 + len2);
207}
208
209/* Read ULEB128 from buffer. */
210uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp)
211{
212 const uint8_t *p = (const uint8_t *)*pp;
213 uint32_t v = *p++;
214 if (LJ_UNLIKELY(v >= 0x80)) {
215 int sh = 0;
216 v &= 0x7f;
217 do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
218 }
219 *pp = (const char *)p;
220 return v;
221}
222