Browse Source

use of different buffers for scanner and concatenation

Roberto Ierusalimschy 23 năm trước cách đây
mục cha
commit
b3d0682fb9
15 tập tin đã thay đổi với 136 bổ sung110 xóa
  1. 5 2
      ldo.c
  2. 4 6
      lgc.c
  3. 63 66
      llex.c
  4. 3 2
      llex.h
  5. 7 1
      llimits.h
  6. 1 10
      lobject.c
  7. 1 3
      lobject.h
  8. 3 2
      lparser.c
  9. 2 2
      lparser.h
  10. 3 4
      lstate.c
  11. 3 3
      lstate.h
  12. 2 2
      lundump.c
  13. 2 2
      lvm.c
  14. 13 2
      lzio.c
  15. 24 3
      lzio.h

+ 5 - 2
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.193 2002/08/30 19:09:21 roberto Exp roberto $
+** $Id: ldo.c,v 1.194 2002/09/02 20:00:41 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -420,12 +420,13 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) {
 */
 struct SParser {  /* data to `f_parser' */
   ZIO *z;
+  Mbuffer buff;  /* buffer to be used by the scanner */
   int bin;
 };
 
 static void f_parser (lua_State *L, void *ud) {
   struct SParser *p = cast(struct SParser *, ud);
-  Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z);
+  Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z, &p->buff);
   Closure *cl = luaF_newLclosure(L, 0, gt(L));
   cl->l.p = tf;
   setclvalue(L->top, cl);
@@ -439,11 +440,13 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
   int status;
   ptrdiff_t oldtopr = savestack(L, L->top);  /* save current top */
   p.z = z; p.bin = bin;
+  luaZ_initbuffer(L, &p.buff);
   /* before parsing, give a (good) chance to GC */
   if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold)
     luaC_collectgarbage(L);
   old_blocks = G(L)->nblocks;
   status = luaD_rawrunprotected(L, f_parser, &p);
+  luaZ_freebuffer(L, &p.buff);
   if (status == 0) {
     /* add new memory to threshold (as it probably will stay) */
     lua_assert(G(L)->nblocks >= old_blocks);

+ 4 - 6
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.150 2002/09/05 19:57:40 roberto Exp roberto $
+** $Id: lgc.c,v 1.151 2002/09/19 19:54:22 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -332,17 +332,15 @@ static void sweepstrings (lua_State *L, int all) {
 }
 
 
-#define MINBUFFER	256
 static void checkSizes (lua_State *L) {
   /* check size of string hash */
   if (G(L)->strt.nuse < cast(ls_nstr, G(L)->strt.size/4) &&
       G(L)->strt.size > MINSTRTABSIZE*2)
     luaS_resize(L, G(L)->strt.size/2);  /* table is too big */
   /* check size of buffer */
-  if (G(L)->Mbuffsize > MINBUFFER*2) {  /* is buffer too big? */
-    size_t newsize = G(L)->Mbuffsize/2;  /* still larger than MINBUFFER */
-    luaM_reallocvector(L, G(L)->Mbuffer, G(L)->Mbuffsize, newsize, char);
-    G(L)->Mbuffsize = newsize;
+  if (luaZ_sizebuffer(&G(L)->buff) > LUA_MINBUFFER*2) {  /* buffer too big? */
+    size_t newsize = luaZ_sizebuffer(&G(L)->buff) / 2;
+    luaZ_resizebuffer(L, &G(L)->buff, newsize);
   }
 }
 

+ 63 - 66
llex.c

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.c,v 1.111 2002/09/05 19:45:42 roberto Exp roberto $
+** $Id: llex.c,v 1.112 2002/09/19 13:03:53 roberto Exp roberto $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
@@ -100,7 +100,7 @@ static void luaX_lexerror (LexState *ls, const char *s, int token) {
   if (token == TK_EOS)
     luaX_error(ls, s, luaX_token2str(ls, token));
   else
-    luaX_error(ls, s, cast(char *, G(ls->L)->Mbuffer));
+    luaX_error(ls, s, luaZ_buffer(ls->buff));
 }
 
 
@@ -138,146 +138,143 @@ void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) {
 
 /* use Mbuffer to store names, literal strings and numbers */
 
-#define EXTRABUFF	128
-#define checkbuffer(L, len)	\
-    if (((len)+10)*sizeof(char) > G(L)->Mbuffsize) \
-      luaO_openspace(L, (len)+EXTRABUFF)
+#define EXTRABUFF	32
+#define checkbuffer(LS, len)	\
+    if (((len)+3)*sizeof(char) > luaZ_sizebuffer((LS)->buff)) \
+      luaZ_openspace((LS)->L, (LS)->buff, (len)+EXTRABUFF)
 
-#define save(L, c, l)	(cast(char *, G(L)->Mbuffer)[l++] = cast(char, c))
-#define save_and_next(L, LS, l)  (save(L, LS->current, l), next(LS))
+#define save(LS, c, l) \
+	(cast(char *, luaZ_buffer((LS)->buff))[l++] = cast(char, c))
+#define save_and_next(LS, l)  (save(LS, LS->current, l), next(LS))
 
 
 static size_t readname (LexState *LS) {
-  lua_State *L = LS->L;
   size_t l = 0;
-  checkbuffer(L, l);
+  checkbuffer(LS, l);
   do {
-    checkbuffer(L, l);
-    save_and_next(L, LS, l);
+    checkbuffer(LS, l);
+    save_and_next(LS, l);
   } while (isalnum(LS->current) || LS->current == '_');
-  save(L, '\0', l);
+  save(LS, '\0', l);
   return l-1;
 }
 
 
 /* LUA_NUMBER */
 static void read_numeral (LexState *LS, int comma, SemInfo *seminfo) {
-  lua_State *L = LS->L;
   size_t l = 0;
-  checkbuffer(L, l);
-  if (comma) save(L, '.', l);
+  checkbuffer(LS, l);
+  if (comma) save(LS, '.', l);
   while (isdigit(LS->current)) {
-    checkbuffer(L, l);
-    save_and_next(L, LS, l);
+    checkbuffer(LS, l);
+    save_and_next(LS, l);
   }
   if (LS->current == '.') {
-    save_and_next(L, LS, l);
+    save_and_next(LS, l);
     if (LS->current == '.') {
-      save_and_next(L, LS, l);
-      save(L, '\0', l);
+      save_and_next(LS, l);
+      save(LS, '\0', l);
       luaX_lexerror(LS,
                  "ambiguous syntax (decimal point x string concatenation)",
                  TK_NUMBER);
     }
   }
   while (isdigit(LS->current)) {
-    checkbuffer(L, l);
-    save_and_next(L, LS, l);
+    checkbuffer(LS, l);
+    save_and_next(LS, l);
   }
   if (LS->current == 'e' || LS->current == 'E') {
-    save_and_next(L, LS, l);  /* read `E' */
+    save_and_next(LS, l);  /* read `E' */
     if (LS->current == '+' || LS->current == '-')
-      save_and_next(L, LS, l);  /* optional exponent sign */
+      save_and_next(LS, l);  /* optional exponent sign */
     while (isdigit(LS->current)) {
-      checkbuffer(L, l);
-      save_and_next(L, LS, l);
+      checkbuffer(LS, l);
+      save_and_next(LS, l);
     }
   }
-  save(L, '\0', l);
-  if (!luaO_str2d(cast(char *, G(L)->Mbuffer), &seminfo->r))
+  save(LS, '\0', l);
+  if (!luaO_str2d(cast(char *, luaZ_buffer(LS->buff)), &seminfo->r))
     luaX_lexerror(LS, "malformed number", TK_NUMBER);
 }
 
 
 static void read_long_string (LexState *LS, SemInfo *seminfo) {
-  lua_State *L = LS->L;
   int cont = 0;
   size_t l = 0;
-  checkbuffer(L, l);
-  save(L, '[', l);  /* save first `[' */
-  save_and_next(L, LS, l);  /* pass the second `[' */
+  checkbuffer(LS, l);
+  save(LS, '[', l);  /* save first `[' */
+  save_and_next(LS, l);  /* pass the second `[' */
   if (LS->current == '\n')  /* string starts with a newline? */
     inclinenumber(LS);  /* skip it */
   for (;;) {
-    checkbuffer(L, l);
+    checkbuffer(LS, l);
     switch (LS->current) {
       case EOZ:
-        save(L, '\0', l);
+        save(LS, '\0', l);
         luaX_lexerror(LS, (seminfo) ? "unfinished long string" :
                                    "unfinished long comment", TK_EOS);
         break;  /* to avoid warnings */
       case '[':
-        save_and_next(L, LS, l);
+        save_and_next(LS, l);
         if (LS->current == '[') {
           cont++;
-          save_and_next(L, LS, l);
+          save_and_next(LS, l);
         }
         continue;
       case ']':
-        save_and_next(L, LS, l);
+        save_and_next(LS, l);
         if (LS->current == ']') {
           if (cont == 0) goto endloop;
           cont--;
-          save_and_next(L, LS, l);
+          save_and_next(LS, l);
         }
         continue;
       case '\n':
-        save(L, '\n', l);
+        save(LS, '\n', l);
         inclinenumber(LS);
         if (!seminfo) l = 0;  /* reset buffer to avoid wasting space */
         continue;
       default:
-        save_and_next(L, LS, l);
+        save_and_next(LS, l);
     }
   } endloop:
-  save_and_next(L, LS, l);  /* skip the second `]' */
-  save(L, '\0', l);
+  save_and_next(LS, l);  /* skip the second `]' */
+  save(LS, '\0', l);
   if (seminfo)
-    seminfo->ts = luaS_newlstr(L, cast(char *, G(L)->Mbuffer)+2, l-5);
+    seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 2, l - 5);
 }
 
 
 static void read_string (LexState *LS, int del, SemInfo *seminfo) {
-  lua_State *L = LS->L;
   size_t l = 0;
-  checkbuffer(L, l);
-  save_and_next(L, LS, l);
+  checkbuffer(LS, l);
+  save_and_next(LS, l);
   while (LS->current != del) {
-    checkbuffer(L, l);
+    checkbuffer(LS, l);
     switch (LS->current) {
       case EOZ:
-        save(L, '\0', l);
+        save(LS, '\0', l);
         luaX_lexerror(LS, "unfinished string", TK_EOS);
         break;  /* to avoid warnings */
       case '\n':
-        save(L, '\0', l);
+        save(LS, '\0', l);
         luaX_lexerror(LS, "unfinished string", TK_STRING);
         break;  /* to avoid warnings */
       case '\\':
         next(LS);  /* do not save the `\' */
         switch (LS->current) {
-          case 'a': save(L, '\a', l); next(LS); break;
-          case 'b': save(L, '\b', l); next(LS); break;
-          case 'f': save(L, '\f', l); next(LS); break;
-          case 'n': save(L, '\n', l); next(LS); break;
-          case 'r': save(L, '\r', l); next(LS); break;
-          case 't': save(L, '\t', l); next(LS); break;
-          case 'v': save(L, '\v', l); next(LS); break;
-          case '\n': save(L, '\n', l); inclinenumber(LS); break;
+          case 'a': save(LS, '\a', l); next(LS); break;
+          case 'b': save(LS, '\b', l); next(LS); break;
+          case 'f': save(LS, '\f', l); next(LS); break;
+          case 'n': save(LS, '\n', l); next(LS); break;
+          case 'r': save(LS, '\r', l); next(LS); break;
+          case 't': save(LS, '\t', l); next(LS); break;
+          case 'v': save(LS, '\v', l); next(LS); break;
+          case '\n': save(LS, '\n', l); inclinenumber(LS); break;
           case EOZ: break;  /* will raise an error next loop */
           default: {
             if (!isdigit(LS->current))
-              save_and_next(L, LS, l);  /* handles \\, \", \', and \? */
+              save_and_next(LS, l);  /* handles \\, \", \', and \? */
             else {  /* \xxx */
               int c = 0;
               int i = 0;
@@ -286,21 +283,21 @@ static void read_string (LexState *LS, int del, SemInfo *seminfo) {
                 next(LS);
               } while (++i<3 && isdigit(LS->current));
               if (c > UCHAR_MAX) {
-                save(L, '\0', l);
+                save(LS, '\0', l);
                 luaX_lexerror(LS, "escape sequence too large", TK_STRING);
               }
-              save(L, c, l);
+              save(LS, c, l);
             }
           }
         }
         break;
       default:
-        save_and_next(L, LS, l);
+        save_and_next(LS, l);
     }
   }
-  save_and_next(L, LS, l);  /* skip delimiter */
-  save(L, '\0', l);
-  seminfo->ts = luaS_newlstr(L, cast(char *, G(L)->Mbuffer)+1, l-3);
+  save_and_next(LS, l);  /* skip delimiter */
+  save(LS, '\0', l);
+  seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3);
 }
 
 
@@ -388,7 +385,7 @@ int luaX_lex (LexState *LS, SemInfo *seminfo) {
         else if (isalpha(LS->current) || LS->current == '_') {
           /* identifier or reserved word */
           size_t l = readname(LS);
-          TString *ts = luaS_newlstr(LS->L, cast(char *, G(LS->L)->Mbuffer), l);
+          TString *ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff), l);
           if (ts->tsv.reserved > 0)  /* reserved word? */
             return ts->tsv.reserved - 1 + FIRST_RESERVED;
           seminfo->ts = ts;

+ 3 - 2
llex.h

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.h,v 1.43 2002/05/07 17:36:56 roberto Exp roberto $
+** $Id: llex.h,v 1.44 2002/09/03 11:57:38 roberto Exp roberto $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
@@ -56,7 +56,8 @@ typedef struct LexState {
   Token lookahead;  /* look ahead token */
   struct FuncState *fs;  /* `FuncState' is private to the parser */
   struct lua_State *L;
-  struct zio *z;  /* input stream */
+  ZIO *z;  /* input stream */
+  Mbuffer *buff;  /* buffer for tokens */
   TString *source;  /* current source name */
 } LexState;
 

+ 7 - 1
llimits.h

@@ -1,5 +1,5 @@
 /*
-** $Id: llimits.h,v 1.44 2002/06/13 13:45:31 roberto Exp roberto $
+** $Id: llimits.h,v 1.45 2002/07/08 20:22:08 roberto Exp roberto $
 ** Limits, basic types, and some other `installation-dependent' definitions
 ** See Copyright Notice in lua.h
 */
@@ -150,4 +150,10 @@ typedef unsigned long Instruction;
 #endif
 
 
+/* minimum size for string buffer */
+#ifndef LUA_MINBUFFER
+#define LUA_MINBUFFER	32
+#endif
+
+
 #endif

+ 1 - 10
lobject.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.c,v 1.88 2002/09/19 13:03:53 roberto Exp roberto $
+** $Id: lobject.c,v 1.89 2002/10/04 14:31:03 roberto Exp roberto $
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -73,15 +73,6 @@ int luaO_rawequalObj (const TObject *t1, const TObject *t2) {
 }
 
 
-char *luaO_openspace (lua_State *L, size_t n) {
-  if (n > G(L)->Mbuffsize) {
-    luaM_reallocvector(L, G(L)->Mbuffer, G(L)->Mbuffsize, n, char);
-    G(L)->Mbuffsize = n;
-  }
-  return G(L)->Mbuffer;
-}
-
-
 int luaO_str2d (const char *s, lua_Number *result) {
   char *endptr;
   lua_Number res = lua_str2number(s, &endptr);

+ 1 - 3
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 1.145 2002/09/02 19:54:49 roberto Exp roberto $
+** $Id: lobject.h,v 1.146 2002/09/19 13:03:53 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -316,8 +316,6 @@ extern const TObject luaO_nilobject;
 int luaO_log2 (unsigned int x);
 
 
-char *luaO_openspace (lua_State *L, size_t n);
-
 int luaO_rawequalObj (const TObject *t1, const TObject *t2);
 int luaO_str2d (const char *s, lua_Number *result);
 

+ 3 - 2
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.193 2002/08/22 19:51:08 roberto Exp roberto $
+** $Id: lparser.c,v 1.194 2002/08/30 19:09:21 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -351,9 +351,10 @@ static void close_func (LexState *ls) {
 }
 
 
-Proto *luaY_parser (lua_State *L, ZIO *z) {
+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) {
   struct LexState lexstate;
   struct FuncState funcstate;
+  lexstate.buff = buff;
   luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z)));
   open_func(&lexstate, &funcstate);
   next(&lexstate);  /* read first token */

+ 2 - 2
lparser.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.h,v 1.43 2002/05/10 19:22:11 roberto Exp roberto $
+** $Id: lparser.h,v 1.44 2002/05/14 17:52:22 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -65,7 +65,7 @@ typedef struct FuncState {
 } FuncState;
 
 
-Proto *luaY_parser (lua_State *L, ZIO *z);
+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff);
 
 
 #endif

+ 3 - 4
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 1.104 2002/08/16 20:00:28 roberto Exp roberto $
+** $Id: lstate.c,v 1.105 2002/08/30 19:09:21 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -61,8 +61,7 @@ static void f_luaopen (lua_State *L, void *ud) {
   G(L)->strt.size = 0;
   G(L)->strt.nuse = 0;
   G(L)->strt.hash = NULL;
-  G(L)->Mbuffer = NULL;
-  G(L)->Mbuffsize = 0;
+  luaZ_initbuffer(L, &G(L)->buff);
   G(L)->panic = &default_panic;
   G(L)->rootgc = NULL;
   G(L)->rootudata = NULL;
@@ -160,7 +159,7 @@ static void close_state (lua_State *L) {
     lua_assert(G(L)->rootgc == NULL);
     lua_assert(G(L)->rootudata == NULL);
     luaS_freeall(L);
-    luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char);
+    luaZ_freebuffer(L, &G(L)->buff);
     luaM_freelem(NULL, L->l_G);
   }
   luaE_closethread(NULL, L);

+ 3 - 3
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.95 2002/08/30 19:09:21 roberto Exp roberto $
+** $Id: lstate.h,v 1.96 2002/09/19 13:03:53 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -11,6 +11,7 @@
 
 #include "lobject.h"
 #include "ltm.h"
+#include "lzio.h"
 
 
 /*
@@ -124,8 +125,7 @@ typedef struct global_State {
   GCObject *rootgc;  /* list of (almost) all collectable objects */
   GCObject *rootudata;   /* (separated) list of all userdata */
   GCObject *tmudata;  /* list of userdata to be GC */
-  char *Mbuffer;  /* global buffer */
-  size_t Mbuffsize;  /* size of Mbuffer */
+  Mbuffer buff;  /* temporary buffer for string concatentation */
   lu_mem GCthreshold;
   lu_mem nblocks;  /* number of `bytes' currently allocated */
   lua_CFunction panic;  /* to be called in unprotected errors */

+ 2 - 2
lundump.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.c,v 1.52 2002/08/12 13:37:19 roberto Exp roberto $
+** $Id: lundump.c,v 1.53 2002/09/19 13:03:53 roberto Exp roberto $
 ** load pre-compiled Lua chunks
 ** See Copyright Notice in lua.h
 */
@@ -99,7 +99,7 @@ static TString* LoadString (LoadState* S)
   return NULL;
  else
  {
-  char* s=luaO_openspace(S->L,size);
+  char* s=luaZ_openspace(S->L,&G(S->L)->buff,size);
   ezread(S,s,size);
   return luaS_newlstr(S->L,s,size-1);	/* remove trailing '\0' */
  }

+ 2 - 2
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.255 2002/09/19 13:03:53 roberto Exp roberto $
+** $Id: lvm.c,v 1.256 2002/09/19 20:12:47 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -303,7 +303,7 @@ void luaV_concat (lua_State *L, int total, int last) {
         n++;
       }
       if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow");
-      buffer = luaO_openspace(L, tl);
+      buffer = luaZ_openspace(L, &G(L)->buff, tl);
       tl = 0;
       for (i=n; i>0; i--) {  /* concat all strings */
         size_t l = tsvalue(top-i)->tsv.len;

+ 13 - 2
lzio.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lzio.c,v 1.20 2002/08/05 18:45:02 roberto Exp roberto $
+** $Id: lzio.c,v 1.21 2002/08/06 17:26:45 roberto Exp roberto $
 ** a generic input stream interface
 ** See Copyright Notice in lua.h
 */
@@ -10,10 +10,10 @@
 #include "lua.h"
 
 #include "llimits.h"
+#include "lmem.h"
 #include "lzio.h"
 
 
-
 int luaZ_fill (ZIO *z) {
   size_t size;
   const char *buff = z->reader(NULL, z->data, &size);
@@ -66,3 +66,14 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) {
   return 0;
 }
 
+/* ------------------------------------------------------------------------ */
+char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
+  if (n > buff->buffsize) {
+    if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
+    luaM_reallocvector(L, buff->buffer, buff->buffsize, n, char);
+    buff->buffsize = n;
+  }
+  return buff->buffer;
+}
+
+

+ 24 - 3
lzio.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lzio.h,v 1.12 2002/06/06 12:40:22 roberto Exp roberto $
+** $Id: lzio.h,v 1.13 2002/08/05 18:45:02 roberto Exp roberto $
 ** Buffered streams
 ** See Copyright Notice in lua.h
 */
@@ -13,7 +13,7 @@
 
 #define EOZ	(-1)			/* end of stream */
 
-typedef struct zio ZIO;
+typedef struct Zio ZIO;
 
 #define zgetc(z)  (((z)->n--)>0 ? \
 			cast(int, cast(unsigned char, *(z)->p++)) : \
@@ -26,9 +26,30 @@ size_t luaZ_read (ZIO* z, void* b, size_t n);	/* read next n bytes */
 int luaZ_lookahead (ZIO *z);
 
 
+
+typedef struct Mbuffer {
+  char *buffer;
+  size_t buffsize;
+} Mbuffer;
+
+
+char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
+
+#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
+
+#define luaZ_sizebuffer(buff)	((buff)->buffsize)
+#define luaZ_buffer(buff)	((buff)->buffer)
+
+#define luaZ_resizebuffer(L, buff, size) \
+	(luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
+	(buff)->buffsize = size)
+
+#define luaZ_freebuffer(L, buff)	luaZ_resizebuffer(L, buff, 0)
+
+
 /* --------- Private Part ------------------ */
 
-struct zio {
+struct Zio {
   size_t n;			/* bytes still unread */
   const char *p;		/* current position in buffer */
   lua_Chunkreader reader;