aboutsummaryrefslogtreecommitdiff
path: root/liolib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-06-22 10:49:42 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-06-22 10:49:42 -0300
commit9559c111a32479794acc59fba2cbeab365a567f3 (patch)
treea50b83d107e14acac00530f758b80419c527d4ab /liolib.c
parent777061e441ecbb9e3522aa5c88d9204decc9ff81 (diff)
downloadlua-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.c162
1 files changed, 84 insertions, 78 deletions
diff --git a/liolib.c b/liolib.c
index 179e5ce3..00b14921 100644
--- a/liolib.c
+++ b/liolib.c
@@ -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
208static 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
219static 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
218static int read_word (lua_State *L, FILE *f) { 232static 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
233static int read_line (lua_State *L, FILE *f) { 264static 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
254static void read_file (lua_State *L, FILE *f) { 274static 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
276static int read_chars (lua_State *L, FILE *f, size_t n) { 282static 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
302static int io_read (lua_State *L) { 299static 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 */