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