summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2013-02-11 14:50:18 +0100
committerMike Pall <mike>2013-02-11 14:50:18 +0100
commit250b24f93728e04851385cce5665eeae26dc60a1 (patch)
tree00194fcdc054a7bad97a7bedd76c440e20ee3eb7
parent4a44c4ff69a890f98fe116901c803018e27847e3 (diff)
downloadluajit-250b24f93728e04851385cce5665eeae26dc60a1.tar.gz
luajit-250b24f93728e04851385cce5665eeae26dc60a1.tar.bz2
luajit-250b24f93728e04851385cce5665eeae26dc60a1.zip
Improve buffer handling for io.read().
-rw-r--r--src/lib_io.c75
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
142static int io_file_testeof(lua_State *L, FILE *fp) 142static 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
150static int io_file_readline(lua_State *L, FILE *fp, size_t chop) 158static 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
172static int io_file_readchars(lua_State *L, FILE *fp, size_t n) 171static 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
190static int io_file_read(lua_State *L, FILE *fp, int start) 186static 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 }