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 /src | |
| parent | 4a44c4ff69a890f98fe116901c803018e27847e3 (diff) | |
| download | luajit-250b24f93728e04851385cce5665eeae26dc60a1.tar.gz luajit-250b24f93728e04851385cce5665eeae26dc60a1.tar.bz2 luajit-250b24f93728e04851385cce5665eeae26dc60a1.zip | |
Improve buffer handling for io.read().
Diffstat (limited to 'src')
| -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 | } |
