diff options
author | Mike Pall <mike> | 2013-02-11 14:50:18 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2013-02-11 14:50:18 +0100 |
commit | 250b24f93728e04851385cce5665eeae26dc60a1 (patch) | |
tree | 00194fcdc054a7bad97a7bedd76c440e20ee3eb7 | |
parent | 4a44c4ff69a890f98fe116901c803018e27847e3 (diff) | |
download | luajit-250b24f93728e04851385cce5665eeae26dc60a1.tar.gz luajit-250b24f93728e04851385cce5665eeae26dc60a1.tar.bz2 luajit-250b24f93728e04851385cce5665eeae26dc60a1.zip |
Improve buffer handling for io.read().
-rw-r--r-- | src/lib_io.c | 75 |
1 files changed, 35 insertions, 40 deletions
diff --git a/src/lib_io.c b/src/lib_io.c index b49526bc..8858683f 100644 --- a/src/lib_io.c +++ b/src/lib_io.c | |||
@@ -139,52 +139,48 @@ static int io_file_readnum(lua_State *L, FILE *fp) | |||
139 | } | 139 | } |
140 | } | 140 | } |
141 | 141 | ||
142 | static int io_file_testeof(lua_State *L, FILE *fp) | 142 | static int io_file_readline(lua_State *L, FILE *fp, MSize chop) |
143 | { | 143 | { |
144 | int c = getc(fp); | 144 | MSize m = LUAL_BUFFERSIZE, n = 0, ok = 0; |
145 | ungetc(c, fp); | 145 | char *buf; |
146 | lua_pushlstring(L, NULL, 0); | 146 | for (;;) { |
147 | return (c != EOF); | 147 | buf = lj_str_needbuf(L, &G(L)->tmpbuf, m); |
148 | if (fgets(buf+n, m-n, fp) == NULL) break; | ||
149 | n += (MSize)strlen(buf+n); | ||
150 | ok |= n; | ||
151 | if (n && buf[n-1] == '\n') { n -= chop; break; } | ||
152 | if (n >= m - 64) m += m; | ||
153 | } | ||
154 | setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n)); | ||
155 | return (int)ok; | ||
148 | } | 156 | } |
149 | 157 | ||
150 | static int io_file_readline(lua_State *L, FILE *fp, size_t chop) | 158 | static void io_file_readall(lua_State *L, FILE *fp) |
151 | { | 159 | { |
152 | luaL_Buffer b; | 160 | MSize m, n; |
153 | luaL_buffinit(L, &b); | 161 | for (m = LUAL_BUFFERSIZE, n = 0; ; m += m) { |
154 | for (;;) { | 162 | char *buf = lj_str_needbuf(L, &G(L)->tmpbuf, m); |
155 | size_t len; | 163 | n += (MSize)fread(buf+n, 1, m-n, fp); |
156 | char *p = luaL_prepbuffer(&b); | 164 | if (n != m) { |
157 | if (fgets(p, LUAL_BUFFERSIZE, fp) == NULL) { /* EOF? */ | 165 | setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n)); |
158 | luaL_pushresult(&b); | 166 | return; |
159 | return (strV(L->top-1)->len > 0); /* Anything read? */ | ||
160 | } | ||
161 | len = strlen(p); | ||
162 | if (len == 0 || p[len-1] != '\n') { /* Partial line? */ | ||
163 | luaL_addsize(&b, len); | ||
164 | } else { | ||
165 | luaL_addsize(&b, len - chop); /* Keep or remove EOL. */ | ||
166 | luaL_pushresult(&b); | ||
167 | return 1; /* Got at least an EOL. */ | ||
168 | } | 167 | } |
169 | } | 168 | } |
170 | } | 169 | } |
171 | 170 | ||
172 | static int io_file_readchars(lua_State *L, FILE *fp, size_t n) | 171 | static int io_file_readlen(lua_State *L, FILE *fp, MSize m) |
173 | { | 172 | { |
174 | size_t rlen; /* how much to read */ | 173 | if (m) { |
175 | size_t nr; /* number of chars actually read */ | 174 | char *buf = lj_str_needbuf(L, &G(L)->tmpbuf, m); |
176 | luaL_Buffer b; | 175 | MSize n = (MSize)fread(buf, 1, m, fp); |
177 | luaL_buffinit(L, &b); | 176 | setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n)); |
178 | rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ | 177 | return (n > 0 || m == 0); |
179 | do { | 178 | } else { |
180 | char *p = luaL_prepbuffer(&b); | 179 | int c = getc(fp); |
181 | if (rlen > n) rlen = n; /* cannot read more than asked */ | 180 | ungetc(c, fp); |
182 | nr = fread(p, 1, rlen, fp); | 181 | setstrV(L, L->top++, &G(L)->strempty); |
183 | luaL_addsize(&b, nr); | 182 | return (c != EOF); |
184 | n -= nr; /* still have to read `n' chars */ | 183 | } |
185 | } while (n > 0 && nr == rlen); /* until end of count or eof */ | ||
186 | luaL_pushresult(&b); /* close buffer */ | ||
187 | return (n == 0 || strV(L->top-1)->len > 0); | ||
188 | } | 184 | } |
189 | 185 | ||
190 | static int io_file_read(lua_State *L, FILE *fp, int start) | 186 | 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) | |||
208 | else if ((p[1] & ~0x20) == 'L') | 204 | else if ((p[1] & ~0x20) == 'L') |
209 | ok = io_file_readline(L, fp, (p[1] == 'l')); | 205 | ok = io_file_readline(L, fp, (p[1] == 'l')); |
210 | else if (p[1] == 'a') | 206 | else if (p[1] == 'a') |
211 | io_file_readchars(L, fp, ~((size_t)0)); | 207 | io_file_readall(L, fp); |
212 | else | 208 | else |
213 | lj_err_arg(L, n+1, LJ_ERR_INVFMT); | 209 | lj_err_arg(L, n+1, LJ_ERR_INVFMT); |
214 | } else if (tvisnumber(L->base+n)) { | 210 | } else if (tvisnumber(L->base+n)) { |
215 | size_t len = (size_t)lj_lib_checkint(L, n+1); | 211 | ok = io_file_readlen(L, fp, (MSize)lj_lib_checkint(L, n+1)); |
216 | ok = len ? io_file_readchars(L, fp, len) : io_file_testeof(L, fp); | ||
217 | } else { | 212 | } else { |
218 | lj_err_arg(L, n+1, LJ_ERR_INVOPT); | 213 | lj_err_arg(L, n+1, LJ_ERR_INVOPT); |
219 | } | 214 | } |