diff options
| -rw-r--r-- | liolib.c | 91 |
1 files changed, 25 insertions, 66 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: liolib.c,v 2.1 2002/04/04 20:24:56 roberto Exp roberto $ | 2 | ** $Id: liolib.c,v 2.2 2002/04/05 18:54:31 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 | */ |
| @@ -180,62 +180,6 @@ static int io_output (lua_State *L) { | |||
| 180 | */ | 180 | */ |
| 181 | 181 | ||
| 182 | 182 | ||
| 183 | #ifndef LUA_MAXUNTIL | ||
| 184 | #define LUA_MAXUNTIL 100 | ||
| 185 | #endif | ||
| 186 | |||
| 187 | |||
| 188 | /* | ||
| 189 | ** Knuth-Morris-Pratt algorithm for string searching | ||
| 190 | ** (based on `Algorithms in MODULA-3', Robert Sedgewick; | ||
| 191 | ** Addison-Wesley, 1993.) | ||
| 192 | */ | ||
| 193 | |||
| 194 | static void prep_read_until (int next[], const char *p, int pl) { | ||
| 195 | int i = 0; | ||
| 196 | int j = -1; | ||
| 197 | next[0] = -1; | ||
| 198 | while (i < pl) { | ||
| 199 | if (j == -1 || p[i] == p[j]) { | ||
| 200 | i++; j++; next[i] = j; | ||
| 201 | } | ||
| 202 | else j = next[j]; | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | |||
| 207 | static int read_until (lua_State *L, FILE *f, const char *p, int pl) { | ||
| 208 | int c; | ||
| 209 | int j; | ||
| 210 | int next[LUA_MAXUNTIL+1]; | ||
| 211 | luaL_Buffer b; | ||
| 212 | luaL_buffinit(L, &b); | ||
| 213 | prep_read_until(next, p, pl); | ||
| 214 | j = 0; | ||
| 215 | while ((c = getc(f)) != EOF) { | ||
| 216 | NoRead: | ||
| 217 | if (c == p[j]) { | ||
| 218 | j++; /* go to next char in pattern */ | ||
| 219 | if (j == pl) { /* complete match? */ | ||
| 220 | luaL_pushresult(&b); /* close buffer */ | ||
| 221 | return 1; /* always success */ | ||
| 222 | } | ||
| 223 | } | ||
| 224 | else if (j == 0) | ||
| 225 | luaL_putchar(&b, c); | ||
| 226 | else { /* match fail */ | ||
| 227 | luaL_addlstring(&b, p, j - next[j]); /* put failed part on result */ | ||
| 228 | j = next[j]; /* backtrack pattern index */ | ||
| 229 | goto NoRead; /* repeat without reading next char */ | ||
| 230 | } | ||
| 231 | } | ||
| 232 | /* end of file without a match */ | ||
| 233 | luaL_addlstring(&b, p, j); /* put failed part on result */ | ||
| 234 | luaL_pushresult(&b); /* close buffer */ | ||
| 235 | return (lua_strlen(L, -1) > 0); | ||
| 236 | } | ||
| 237 | |||
| 238 | |||
| 239 | static int read_number (lua_State *L, FILE *f) { | 183 | static int read_number (lua_State *L, FILE *f) { |
| 240 | lua_Number d; | 184 | lua_Number d; |
| 241 | if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { | 185 | if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { |
| @@ -254,6 +198,28 @@ static int test_eof (lua_State *L, FILE *f) { | |||
| 254 | } | 198 | } |
| 255 | 199 | ||
| 256 | 200 | ||
| 201 | static int read_line (lua_State *L, FILE *f) { | ||
| 202 | luaL_Buffer b; | ||
| 203 | luaL_buffinit(L, &b); | ||
| 204 | for (;;) { | ||
| 205 | size_t l; | ||
| 206 | char *p = luaL_prepbuffer(&b); | ||
| 207 | if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ | ||
| 208 | luaL_pushresult(&b); /* close buffer */ | ||
| 209 | return (lua_strlen(L, -1) > 0); /* check whether read something */ | ||
| 210 | } | ||
| 211 | l = strlen(p); | ||
| 212 | if (p[l-1] != '\n') | ||
| 213 | luaL_addsize(&b, l); | ||
| 214 | else { | ||
| 215 | luaL_addsize(&b, l - 1); /* do not include `eol' */ | ||
| 216 | luaL_pushresult(&b); /* close buffer */ | ||
| 217 | return 1; /* read at least an `eol' */ | ||
| 218 | } | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | |||
| 257 | static int read_chars (lua_State *L, FILE *f, size_t n) { | 223 | static int read_chars (lua_State *L, FILE *f, size_t n) { |
| 258 | size_t rlen; /* how much to read */ | 224 | size_t rlen; /* how much to read */ |
| 259 | size_t nr; /* number of chars actually read */ | 225 | size_t nr; /* number of chars actually read */ |
| @@ -277,7 +243,7 @@ static int g_read (lua_State *L, FILE *f, int first) { | |||
| 277 | int success; | 243 | int success; |
| 278 | int n; | 244 | int n; |
| 279 | if (nargs == 0) { /* no arguments? */ | 245 | if (nargs == 0) { /* no arguments? */ |
| 280 | success = read_until(L, f, "\n", 1); /* read until \n (a line) */ | 246 | success = read_line(L, f); |
| 281 | n = first+1; /* to return 1 result */ | 247 | n = first+1; /* to return 1 result */ |
| 282 | } | 248 | } |
| 283 | else { /* ensure stack space for all results and for auxlib's buffer */ | 249 | else { /* ensure stack space for all results and for auxlib's buffer */ |
| @@ -297,7 +263,7 @@ static int g_read (lua_State *L, FILE *f, int first) { | |||
| 297 | success = read_number(L, f); | 263 | success = read_number(L, f); |
| 298 | break; | 264 | break; |
| 299 | case 'l': /* line */ | 265 | case 'l': /* line */ |
| 300 | success = read_until(L, f, "\n", 1); /* read until \n */ | 266 | success = read_line(L, f); |
| 301 | break; | 267 | break; |
| 302 | case 'a': /* file */ | 268 | case 'a': /* file */ |
| 303 | read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ | 269 | read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ |
| @@ -306,13 +272,6 @@ static int g_read (lua_State *L, FILE *f, int first) { | |||
| 306 | case 'w': /* word */ | 272 | case 'w': /* word */ |
| 307 | lua_error(L, "obsolete option `*w'"); | 273 | lua_error(L, "obsolete option `*w'"); |
| 308 | break; | 274 | break; |
| 309 | case 'u': { /* read until */ | ||
| 310 | size_t pl = lua_strlen(L, n) - 2; | ||
| 311 | luaL_arg_check(L, 0 < pl && pl <= LUA_MAXUNTIL, n, | ||
| 312 | "invalid read-until length"); | ||
| 313 | success = read_until(L, f, p+2, (int)(pl)); | ||
| 314 | break; | ||
| 315 | } | ||
| 316 | default: | 275 | default: |
| 317 | luaL_argerror(L, n, "invalid format"); | 276 | luaL_argerror(L, n, "invalid format"); |
| 318 | success = 0; /* to avoid warnings */ | 277 | success = 0; /* to avoid warnings */ |
