Improve buffer handling for io.read().

This commit is contained in:
Mike Pall 2013-02-11 14:50:18 +01:00
parent 4a44c4ff69
commit 250b24f937

View File

@ -139,52 +139,48 @@ static int io_file_readnum(lua_State *L, FILE *fp)
} }
} }
static int io_file_testeof(lua_State *L, FILE *fp) static int io_file_readline(lua_State *L, FILE *fp, MSize chop)
{ {
int c = getc(fp); MSize m = LUAL_BUFFERSIZE, n = 0, ok = 0;
ungetc(c, fp); char *buf;
lua_pushlstring(L, NULL, 0); for (;;) {
return (c != EOF); buf = lj_str_needbuf(L, &G(L)->tmpbuf, m);
if (fgets(buf+n, m-n, fp) == NULL) break;
n += (MSize)strlen(buf+n);
ok |= n;
if (n && buf[n-1] == '\n') { n -= chop; break; }
if (n >= m - 64) m += m;
}
setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
return (int)ok;
} }
static int io_file_readline(lua_State *L, FILE *fp, size_t chop) static void io_file_readall(lua_State *L, FILE *fp)
{ {
luaL_Buffer b; MSize m, n;
luaL_buffinit(L, &b); for (m = LUAL_BUFFERSIZE, n = 0; ; m += m) {
for (;;) { char *buf = lj_str_needbuf(L, &G(L)->tmpbuf, m);
size_t len; n += (MSize)fread(buf+n, 1, m-n, fp);
char *p = luaL_prepbuffer(&b); if (n != m) {
if (fgets(p, LUAL_BUFFERSIZE, fp) == NULL) { /* EOF? */ setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
luaL_pushresult(&b); return;
return (strV(L->top-1)->len > 0); /* Anything read? */
}
len = strlen(p);
if (len == 0 || p[len-1] != '\n') { /* Partial line? */
luaL_addsize(&b, len);
} else {
luaL_addsize(&b, len - chop); /* Keep or remove EOL. */
luaL_pushresult(&b);
return 1; /* Got at least an EOL. */
} }
} }
} }
static int io_file_readchars(lua_State *L, FILE *fp, size_t n) static int io_file_readlen(lua_State *L, FILE *fp, MSize m)
{ {
size_t rlen; /* how much to read */ if (m) {
size_t nr; /* number of chars actually read */ char *buf = lj_str_needbuf(L, &G(L)->tmpbuf, m);
luaL_Buffer b; MSize n = (MSize)fread(buf, 1, m, fp);
luaL_buffinit(L, &b); setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ return (n > 0 || m == 0);
do { } else {
char *p = luaL_prepbuffer(&b); int c = getc(fp);
if (rlen > n) rlen = n; /* cannot read more than asked */ ungetc(c, fp);
nr = fread(p, 1, rlen, fp); setstrV(L, L->top++, &G(L)->strempty);
luaL_addsize(&b, nr); return (c != EOF);
n -= nr; /* still have to read `n' chars */ }
} while (n > 0 && nr == rlen); /* until end of count or eof */
luaL_pushresult(&b); /* close buffer */
return (n == 0 || strV(L->top-1)->len > 0);
} }
static int io_file_read(lua_State *L, FILE *fp, int start) static int io_file_read(lua_State *L, FILE *fp, int start)
@ -208,12 +204,11 @@ static int io_file_read(lua_State *L, FILE *fp, int start)
else if ((p[1] & ~0x20) == 'L') else if ((p[1] & ~0x20) == 'L')
ok = io_file_readline(L, fp, (p[1] == 'l')); ok = io_file_readline(L, fp, (p[1] == 'l'));
else if (p[1] == 'a') else if (p[1] == 'a')
io_file_readchars(L, fp, ~((size_t)0)); io_file_readall(L, fp);
else else
lj_err_arg(L, n+1, LJ_ERR_INVFMT); lj_err_arg(L, n+1, LJ_ERR_INVFMT);
} else if (tvisnumber(L->base+n)) { } else if (tvisnumber(L->base+n)) {
size_t len = (size_t)lj_lib_checkint(L, n+1); ok = io_file_readlen(L, fp, (MSize)lj_lib_checkint(L, n+1));
ok = len ? io_file_readchars(L, fp, len) : io_file_testeof(L, fp);
} else { } else {
lj_err_arg(L, n+1, LJ_ERR_INVOPT); lj_err_arg(L, n+1, LJ_ERR_INVOPT);
} }