diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-06-22 10:49:42 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-06-22 10:49:42 -0300 |
commit | 9559c111a32479794acc59fba2cbeab365a567f3 (patch) | |
tree | a50b83d107e14acac00530f758b80419c527d4ab /liolib.c | |
parent | 777061e441ecbb9e3522aa5c88d9204decc9ff81 (diff) | |
download | lua-9559c111a32479794acc59fba2cbeab365a567f3.tar.gz lua-9559c111a32479794acc59fba2cbeab365a567f3.tar.bz2 lua-9559c111a32479794acc59fba2cbeab365a567f3.zip |
new `read' option `*u' (read-until) + simpler implementation for `read'
Diffstat (limited to 'liolib.c')
-rw-r--r-- | liolib.c | 162 |
1 files changed, 84 insertions, 78 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: liolib.c,v 1.114 2001/06/07 13:46:29 roberto Exp roberto $ | 2 | ** $Id: liolib.c,v 1.115 2001/06/08 16:48:32 roberto Exp roberto $ |
3 | ** Standard I/O (and system) library | 3 | ** Standard I/O (and system) library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -205,115 +205,114 @@ static int io_appendto (lua_State *L) { | |||
205 | */ | 205 | */ |
206 | 206 | ||
207 | 207 | ||
208 | static int read_number (lua_State *L, FILE *f) { | 208 | #ifndef LUA_MAXUNTIL |
209 | double d; | 209 | #define LUA_MAXUNTIL 100 |
210 | if (fscanf(f, l_s("%lf"), &d) == 1) { | 210 | #endif |
211 | lua_pushnumber(L, d); | 211 | |
212 | return 1; | 212 | |
213 | /* | ||
214 | ** Knuth-Morris-Pratt algorithm for string searching | ||
215 | ** (based on `Algorithms in MODULA-3', Robert Sedgewick; | ||
216 | ** Addison-Wesley, 1993.) | ||
217 | */ | ||
218 | |||
219 | static void prep_read_until (int next[], const l_char *p, int pl) { | ||
220 | int i = 0; | ||
221 | int j = -1; | ||
222 | next[0] = -1; | ||
223 | while (i < pl) { | ||
224 | if (j == -1 || p[i] == p[j]) { | ||
225 | i++; j++; next[i] = j; | ||
226 | } | ||
227 | else j = next[j]; | ||
213 | } | 228 | } |
214 | else return 0; /* read fails */ | ||
215 | } | 229 | } |
216 | 230 | ||
217 | 231 | ||
218 | static int read_word (lua_State *L, FILE *f) { | 232 | static int read_until (lua_State *L, FILE *f, const l_char *p, int pl) { |
219 | l_charint c; | 233 | l_charint c; |
234 | int j; | ||
235 | int next[LUA_MAXUNTIL+1]; | ||
220 | luaL_Buffer b; | 236 | luaL_Buffer b; |
221 | luaL_buffinit(L, &b); | 237 | luaL_buffinit(L, &b); |
222 | do { c = fgetc(f); } while (isspace(c)); /* skip spaces */ | 238 | prep_read_until(next, p, pl); |
223 | while (c != EOF && !isspace(c)) { | 239 | j = 0; |
224 | luaL_putchar(&b, c); | 240 | while ((c = fgetc(f)) != EOF) { |
225 | c = fgetc(f); | 241 | NoRead: |
242 | if (c == p[j]) { | ||
243 | j++; /* go to next char in pattern */ | ||
244 | if (j == pl) { /* complete match? */ | ||
245 | luaL_pushresult(&b); /* close buffer */ | ||
246 | return 1; /* always success */ | ||
247 | } | ||
248 | } | ||
249 | else if (j == 0) | ||
250 | luaL_putchar(&b, c); | ||
251 | else { /* match fail */ | ||
252 | luaL_addlstring(&b, p, j - next[j]); /* put failed part on result */ | ||
253 | j = next[j]; /* backtrack pattern index */ | ||
254 | goto NoRead; /* repeat without reading next char */ | ||
255 | } | ||
226 | } | 256 | } |
227 | ungetc(c, f); | 257 | /* end of file without a match */ |
258 | luaL_addlstring(&b, p, j); /* put failed part on result */ | ||
228 | luaL_pushresult(&b); /* close buffer */ | 259 | luaL_pushresult(&b); /* close buffer */ |
229 | return (lua_strlen(L, -1) > 0); | 260 | return (lua_strlen(L, -1) > 0); |
230 | } | 261 | } |
231 | 262 | ||
232 | 263 | ||
233 | static int read_line (lua_State *L, FILE *f) { | 264 | static int read_number (lua_State *L, FILE *f) { |
234 | int n = 0; | 265 | double d; |
235 | luaL_Buffer b; | 266 | if (fscanf(f, l_s("%lf"), &d) == 1) { |
236 | luaL_buffinit(L, &b); | 267 | lua_pushnumber(L, d); |
237 | for (;;) { | 268 | return 1; |
238 | l_char *p = luaL_prepbuffer(&b); | ||
239 | if (!fgets(p, LUAL_BUFFERSIZE, f)) /* read fails? */ | ||
240 | break; | ||
241 | n = strlen(p); | ||
242 | if (p[n-1] != l_c('\n')) | ||
243 | luaL_addsize(&b, n); | ||
244 | else { | ||
245 | luaL_addsize(&b, n-1); /* do not add the `\n' */ | ||
246 | break; | ||
247 | } | ||
248 | } | 269 | } |
249 | luaL_pushresult(&b); /* close buffer */ | 270 | else return 0; /* read fails */ |
250 | return (n > 0); /* read something? */ | ||
251 | } | 271 | } |
252 | 272 | ||
253 | 273 | ||
254 | static void read_file (lua_State *L, FILE *f) { | 274 | static int test_eof (lua_State *L, FILE *f) { |
255 | size_t len = 0; | 275 | l_charint c = fgetc(f); |
256 | size_t size = LUAL_BUFFERSIZE; | 276 | ungetc(c, f); |
257 | size_t oldsize = 0; | 277 | lua_pushlstring(L, NULL, 0); |
258 | l_char *buffer = NULL; | 278 | return (c != EOF); |
259 | for (;;) { | ||
260 | l_char *newbuffer = (l_char *)l_realloc(buffer, oldsize, size); | ||
261 | if (newbuffer == NULL) { | ||
262 | l_free(buffer, oldsize); | ||
263 | lua_error(L, l_s("not enough memory to read a file")); | ||
264 | } | ||
265 | buffer = newbuffer; | ||
266 | len += fread(buffer+len, sizeof(l_char), size-len, f); | ||
267 | if (len < size) break; /* did not read all it could */ | ||
268 | oldsize = size; | ||
269 | size *= 2; | ||
270 | } | ||
271 | lua_pushlstring(L, buffer, len); | ||
272 | l_free(buffer, size); | ||
273 | } | 279 | } |
274 | 280 | ||
275 | 281 | ||
276 | static int read_chars (lua_State *L, FILE *f, size_t n) { | 282 | static int read_chars (lua_State *L, FILE *f, size_t n) { |
277 | if (n == 0) { /* test eof? */ | 283 | size_t rlen; |
278 | l_charint c = fgetc(f); | 284 | luaL_Buffer b; |
279 | ungetc(c, f); | 285 | luaL_buffinit(L, &b); |
280 | lua_pushlstring(L, NULL, 0); | 286 | rlen = LUAL_BUFFERSIZE; |
281 | return (c != EOF); | 287 | do { |
282 | } | 288 | l_char *p = luaL_prepbuffer(&b); |
283 | else { | 289 | if (rlen > n) rlen = n; |
284 | l_char *buffer; | 290 | rlen = fread(p, sizeof(l_char), rlen, f); |
285 | size_t n1; | 291 | luaL_addsize(&b, rlen); |
286 | l_char statbuff[LUAL_BUFFERSIZE]; | 292 | n -= rlen; |
287 | if (n <= LUAL_BUFFERSIZE) | 293 | } while (n > 0 && rlen > 0); /* until end of count or eof */ |
288 | buffer = statbuff; | 294 | luaL_pushresult(&b); /* close buffer */ |
289 | else { | 295 | return (n == 0 || lua_strlen(L, -1) > 0); |
290 | buffer = (l_char *)l_malloc(n); | ||
291 | if (buffer == NULL) | ||
292 | lua_error(L, l_s("not enough memory to read a file")); | ||
293 | } | ||
294 | n1 = fread(buffer, sizeof(l_char), n, f); | ||
295 | lua_pushlstring(L, buffer, n1); | ||
296 | if (buffer != statbuff) l_free(buffer, n); | ||
297 | return (n1 > 0 || n == 0); | ||
298 | } | ||
299 | } | 296 | } |
300 | 297 | ||
301 | 298 | ||
302 | static int io_read (lua_State *L) { | 299 | static int io_read (lua_State *L) { |
303 | FILE *f = getopthandle(L, INFILE); | 300 | FILE *f = getopthandle(L, INFILE); |
304 | int nargs = lua_gettop(L)-1; | 301 | int nargs = lua_gettop(L) - 1; |
305 | int success; | 302 | int success; |
306 | int n; | 303 | int n; |
307 | if (nargs == 0) { /* no arguments? */ | 304 | if (nargs == 0) { /* no arguments? */ |
308 | success = read_line(L, f); | 305 | success = read_until(L, f, l_s("\n"), 1); /* read until \n (a line) */ |
309 | n = 2; /* will return n-1 results */ | 306 | n = 2; /* will return n-1 results */ |
310 | } | 307 | } |
311 | else { /* ensure stack space for all results and for auxlib's buffer */ | 308 | else { /* ensure stack space for all results and for auxlib's buffer */ |
312 | luaL_checkstack(L, nargs+LUA_MINSTACK, l_s("too many arguments")); | 309 | luaL_checkstack(L, nargs+LUA_MINSTACK, l_s("too many arguments")); |
313 | success = 1; | 310 | success = 1; |
314 | for (n = 1; n<=nargs && success; n++) { | 311 | for (n = 1; n<=nargs && success; n++) { |
315 | if (lua_type(L, n) == LUA_TNUMBER) | 312 | if (lua_type(L, n) == LUA_TNUMBER) { |
316 | success = read_chars(L, f, (size_t)lua_tonumber(L, n)); | 313 | size_t l = (size_t)lua_tonumber(L, n); |
314 | success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); | ||
315 | } | ||
317 | else { | 316 | else { |
318 | const l_char *p = lua_tostring(L, n); | 317 | const l_char *p = lua_tostring(L, n); |
319 | if (!p || p[0] != l_c('*')) | 318 | if (!p || p[0] != l_c('*')) |
@@ -323,15 +322,22 @@ static int io_read (lua_State *L) { | |||
323 | success = read_number(L, f); | 322 | success = read_number(L, f); |
324 | break; | 323 | break; |
325 | case l_c('l'): /* line */ | 324 | case l_c('l'): /* line */ |
326 | success = read_line(L, f); | 325 | success = read_until(L, f, l_s("\n"), 1); /* read until \n */ |
327 | break; | 326 | break; |
328 | case l_c('a'): /* file */ | 327 | case l_c('a'): /* file */ |
329 | read_file(L, f); | 328 | read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ |
330 | success = 1; /* always success */ | 329 | success = 1; /* always success */ |
331 | break; | 330 | break; |
332 | case l_c('w'): /* word */ | 331 | case l_c('w'): /* word */ |
333 | success = read_word(L, f); | 332 | lua_error(L, "option `*w' is deprecated"); |
333 | break; | ||
334 | case l_c('u'): { /* read until */ | ||
335 | size_t pl = lua_strlen(L, n) - 2; | ||
336 | luaL_arg_check(L, 0 < pl && pl <= LUA_MAXUNTIL, n, | ||
337 | l_s("invalid read-until length")); | ||
338 | success = read_until(L, f, p+2, (int)pl); | ||
334 | break; | 339 | break; |
340 | } | ||
335 | default: | 341 | default: |
336 | luaL_argerror(L, n, l_s("invalid format")); | 342 | luaL_argerror(L, n, l_s("invalid format")); |
337 | success = 0; /* to avoid warnings */ | 343 | success = 0; /* to avoid warnings */ |