mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 23:24:09 +00:00
Improve buffer handling for io.read().
This commit is contained in:
parent
4a44c4ff69
commit
250b24f937
75
src/lib_io.c
75
src/lib_io.c
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user