root/lj_buf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. buf_grow
  2. lj_buf_need2
  3. lj_buf_more2
  4. lj_buf_shrink
  5. lj_buf_tmp
  6. lj_buf_putmem
  7. lj_buf_putchar
  8. lj_buf_putstr
  9. lj_buf_putstr_reverse
  10. lj_buf_putstr_lower
  11. lj_buf_putstr_upper
  12. lj_buf_putstr_rep
  13. lj_buf_puttab
  14. lj_buf_tostr
  15. lj_buf_cat2str
  16. lj_buf_ruleb128

   1 /*
   2 ** Buffer handling.
   3 ** Copyright (C) 2005-2017 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 

/* [<][>][^][v][top][bottom][index][help] */