lua-users home
lua-l archive

Function read_line in liolib.c

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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( "H0円orse\nA0円pple\nT0円ree" )
 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

AltStyle によって変換されたページ (->オリジナル) /