[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Function read_line in liolib.c
- From: Shmuel Zeigerman <shmuz@...>
- Date: Fri, 11 Apr 2008 18:16:48 +0300
When reading lines from a binary file, functions io.lines(...)
and file:read("*l") can read multiple lines at once and produce
strings that are not contained in the file.
Here is a test case:
local fname = "temp.tmp"
local f = io.open(fname, "wb")
f:write( "H\0orse\nA\0pple\nT\0ree" )
f:close()
for l in io.lines(fname) do print(#l, l) end
It prints:
3 HAT
We can see that only 1 line is detected in the file, and
that the extracted string "HAT" is not present in the file.
It seems that it'd be more reasonable to see:
6 H
6 A
5 T
The modified function read_line (see below) corrects that behavior
due to using memchr rather than strlen. Unfortunately, it seems to
be about 25% slower than the original function.
static int read_line (lua_State *L, FILE *f) {
luaL_Buffer b;
luaL_buffinit(L, &b);
for (;;) {
char *q, *p = luaL_prepbuffer(&b);
memset(p, '\n', LUAL_BUFFERSIZE);
if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
luaL_pushresult(&b); /* close buffer */
return (lua_objlen(L, -1) > 0); /* check whether read something */
}
if (!(q = memchr(p, '\n', LUAL_BUFFERSIZE-1)))
luaL_addsize(&b, LUAL_BUFFERSIZE-1);
else if (q[1])
luaL_addsize(&b, q-p-1);
else {
luaL_addsize(&b, q-p);
luaL_pushresult(&b); /* close buffer */
return 1; /* read at least an `eol' */
}
}
}
--
Shmuel