ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

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