src/lj_buf.c - luajit-2.0-src

Functions defined

Macros defined

Source code

  1. /*
  2. ** Buffer handling.
  3. ** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
  4. */

  5. #define lj_buf_c
  6. #define LUA_CORE

  7. #include "lj_obj.h"
  8. #include "lj_gc.h"
  9. #include "lj_err.h"
  10. #include "lj_buf.h"
  11. #include "lj_str.h"
  12. #include "lj_tab.h"
  13. #include "lj_strfmt.h"

  14. /* -- Buffer management --------------------------------------------------- */

  15. static void buf_grow(SBuf *sb, MSize sz)
  16. {
  17.   MSize osz = sbufsz(sb), len = sbuflen(sb), nsz = osz;
  18.   char *b;
  19.   if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF;
  20.   while (nsz < sz) nsz += nsz;
  21.   b = (char *)lj_mem_realloc(sbufL(sb), sbufB(sb), osz, nsz);
  22.   setmref(sb->b, b);
  23.   setmref(sb->p, b + len);
  24.   setmref(sb->e, b + nsz);
  25. }

  26. LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz)
  27. {
  28.   lua_assert(sz > sbufsz(sb));
  29.   if (LJ_UNLIKELY(sz > LJ_MAX_BUF))
  30.     lj_err_mem(sbufL(sb));
  31.   buf_grow(sb, sz);
  32.   return sbufB(sb);
  33. }

  34. LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz)
  35. {
  36.   MSize len = sbuflen(sb);
  37.   lua_assert(sz > sbufleft(sb));
  38.   if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF))
  39.     lj_err_mem(sbufL(sb));
  40.   buf_grow(sb, len + sz);
  41.   return sbufP(sb);
  42. }

  43. void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb)
  44. {
  45.   char *b = sbufB(sb);
  46.   MSize osz = (MSize)(sbufE(sb) - b);
  47.   if (osz > 2*LJ_MIN_SBUF) {
  48.     MSize n = (MSize)(sbufP(sb) - b);
  49.     b = lj_mem_realloc(L, b, osz, (osz >> 1));
  50.     setmref(sb->b, b);
  51.     setmref(sb->p, b + n);
  52.     setmref(sb->e, b + (osz >> 1));
  53.   }
  54. }

  55. char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz)
  56. {
  57.   SBuf *sb = &G(L)->tmpbuf;
  58.   setsbufL(sb, L);
  59.   return lj_buf_need(sb, sz);
  60. }

  61. /* -- Low-level buffer put operations ------------------------------------- */

  62. SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len)
  63. {
  64.   char *p = lj_buf_more(sb, len);
  65.   p = lj_buf_wmem(p, q, len);
  66.   setsbufP(sb, p);
  67.   return sb;
  68. }

  69. #if LJ_HASJIT
  70. SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c)
  71. {
  72.   char *p = lj_buf_more(sb, 1);
  73.   *p++ = (char)c;
  74.   setsbufP(sb, p);
  75.   return sb;
  76. }
  77. #endif

  78. SBuf * 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. /* -- High-level buffer put operations ------------------------------------ */

  87. SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s)
  88. {
  89.   MSize len = s->len;
  90.   char *p = lj_buf_more(sb, len), *e = p+len;
  91.   const char *q = strdata(s)+len-1;
  92.   while (p < e)
  93.     *p++ = *q--;
  94.   setsbufP(sb, p);
  95.   return sb;
  96. }

  97. SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s)
  98. {
  99.   MSize len = s->len;
  100.   char *p = lj_buf_more(sb, len), *e = p+len;
  101.   const char *q = strdata(s);
  102.   for (; p < e; p++, q++) {
  103.     uint32_t c = *(unsigned char *)q;
  104. #if LJ_TARGET_PPC
  105.     *p = c + ((c >= 'A' && c <= 'Z') << 5);
  106. #else
  107.     if (c >= 'A' && c <= 'Z') c += 0x20;
  108.     *p = c;
  109. #endif
  110.   }
  111.   setsbufP(sb, p);
  112.   return sb;
  113. }

  114. SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s)
  115. {
  116.   MSize len = s->len;
  117.   char *p = lj_buf_more(sb, len), *e = p+len;
  118.   const char *q = strdata(s);
  119.   for (; p < e; p++, q++) {
  120.     uint32_t c = *(unsigned char *)q;
  121. #if LJ_TARGET_PPC
  122.     *p = c - ((c >= 'a' && c <= 'z') << 5);
  123. #else
  124.     if (c >= 'a' && c <= 'z') c -= 0x20;
  125.     *p = c;
  126. #endif
  127.   }
  128.   setsbufP(sb, p);
  129.   return sb;
  130. }

  131. SBuf *lj_buf_putstr_rep(SBuf *sb, GCstr *s, int32_t rep)
  132. {
  133.   MSize len = s->len;
  134.   if (rep > 0 && len) {
  135.     uint64_t tlen = (uint64_t)rep * len;
  136.     char *p;
  137.     if (LJ_UNLIKELY(tlen > LJ_MAX_STR))
  138.       lj_err_mem(sbufL(sb));
  139.     p = lj_buf_more(sb, (MSize)tlen);
  140.     if (len == 1) {  /* Optimize a common case. */
  141.       uint32_t c = strdata(s)[0];
  142.       do { *p++ = c; } while (--rep > 0);
  143.     } else {
  144.       const char *e = strdata(s) + len;
  145.       do {
  146.         const char *q = strdata(s);
  147.         do { *p++ = *q++; } while (q < e);
  148.       } while (--rep > 0);
  149.     }
  150.     setsbufP(sb, p);
  151.   }
  152.   return sb;
  153. }

  154. SBuf *lj_buf_puttab(SBuf *sb, GCtab *t, GCstr *sep, int32_t i, int32_t e)
  155. {
  156.   MSize seplen = sep ? sep->len : 0;
  157.   if (i <= e) {
  158.     for (;;) {
  159.       cTValue *o = lj_tab_getint(t, i);
  160.       char *p;
  161.       if (!o) {
  162.       badtype:  /* Error: bad element type. */
  163.         setsbufP(sb, (void *)(intptr_t)i);  /* Store failing index. */
  164.         return NULL;
  165.       } else if (tvisstr(o)) {
  166.         MSize len = strV(o)->len;
  167.         p = lj_buf_wmem(lj_buf_more(sb, len + seplen), strVdata(o), len);
  168.       } else if (tvisint(o)) {
  169.         p = lj_strfmt_wint(lj_buf_more(sb, STRFMT_MAXBUF_INT+seplen), intV(o));
  170.       } else if (tvisnum(o)) {
  171.         p = lj_strfmt_wnum(lj_buf_more(sb, STRFMT_MAXBUF_NUM+seplen), o);
  172.       } else {
  173.         goto badtype;
  174.       }
  175.       if (i++ == e) {
  176.         setsbufP(sb, p);
  177.         break;
  178.       }
  179.       if (seplen) p = lj_buf_wmem(p, strdata(sep), seplen);
  180.       setsbufP(sb, p);
  181.     }
  182.   }
  183.   return sb;
  184. }

  185. /* -- Miscellaneous buffer operations ------------------------------------- */

  186. GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb)
  187. {
  188.   return lj_str_new(sbufL(sb), sbufB(sb), sbuflen(sb));
  189. }

  190. /* Concatenate two strings. */
  191. GCstr *lj_buf_cat2str(lua_State *L, GCstr *s1, GCstr *s2)
  192. {
  193.   MSize len1 = s1->len, len2 = s2->len;
  194.   char *buf = lj_buf_tmp(L, len1 + len2);
  195.   memcpy(buf, strdata(s1), len1);
  196.   memcpy(buf+len1, strdata(s2), len2);
  197.   return lj_str_new(L, buf, len1 + len2);
  198. }

  199. /* Read ULEB128 from buffer. */
  200. uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp)
  201. {
  202.   const uint8_t *p = (const uint8_t *)*pp;
  203.   uint32_t v = *p++;
  204.   if (LJ_UNLIKELY(v >= 0x80)) {
  205.     int sh = 0;
  206.     v &= 0x7f;
  207.     do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
  208.   }
  209.   *pp = (const char *)p;
  210.   return v;
  211. }