~ubuntu-branches/ubuntu/jaunty/luatex/jaunty

« back to all changes in this revision

Viewing changes to src/libs/luazlib/lgzip.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2007-09-24 12:56:11 UTC
  • Revision ID: james.westby@ubuntu.com-20070924125611-a8ge689azbptxvla
Tags: upstream-0.11.2
ImportĀ upstreamĀ versionĀ 0.11.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************
 
2
* Author    : Tiago Dionizio (tngd@mega.ist.utl.pt)                     *
 
3
* Library   : lgzip - a gzip file access binding for Lua 5              *
 
4
*             based on liolib.c from Lua 5.0 library                    *
 
5
*                                                                       *
 
6
* Permission is hereby granted, free of charge, to any person obtaining *
 
7
* a copy of this software and associated documentation files (the       *
 
8
* "Software"), to deal in the Software without restriction, including   *
 
9
* without limitation the rights to use, copy, modify, merge, publish,   *
 
10
* distribute, sublicense, and/or sell copies of the Software, and to    *
 
11
* permit persons to whom the Software is furnished to do so, subject to *
 
12
* the following conditions:                                             *
 
13
*                                                                       *
 
14
* The above copyright notice and this permission notice shall be        *
 
15
* included in all copies or substantial portions of the Software.       *
 
16
*                                                                       *
 
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
 
18
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
 
19
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
 
20
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  *
 
21
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  *
 
22
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     *
 
23
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                *
 
24
************************************************************************/
 
25
 
 
26
/************************************************************************
 
27
$Id: lgzip.c,v 1.2 2003/12/28 01:26:16 tngd Exp $
 
28
Changes:
 
29
************************************************************************/
 
30
#include <errno.h>
 
31
#include <stdlib.h>
 
32
#include <string.h>
 
33
 
 
34
#include "zlib.h"
 
35
 
 
36
#include "lua.h"
 
37
#include "lauxlib.h"
 
38
 
 
39
 
 
40
 
 
41
/*
 
42
** {======================================================
 
43
** FILE Operations
 
44
** =======================================================
 
45
*/
 
46
 
 
47
 
 
48
#define FILEHANDLE              "zlib:gzFile"
 
49
 
 
50
 
 
51
static int pushresult (lua_State *L, int i, const char *filename) {
 
52
  if (i) {
 
53
    lua_pushboolean(L, 1);
 
54
    return 1;
 
55
  }
 
56
  else {
 
57
    lua_pushnil(L);
 
58
    if (filename)
 
59
      lua_pushfstring(L, "%s: %s", filename, strerror(errno));
 
60
    else
 
61
      lua_pushfstring(L, "%s", strerror(errno));
 
62
    lua_pushnumber(L, errno);
 
63
    return 3;
 
64
  }
 
65
}
 
66
 
 
67
 
 
68
static gzFile *topfile (lua_State *L, int findex) {
 
69
  gzFile*f = (gzFile*)luaL_checkudata(L, findex, FILEHANDLE);
 
70
  if (f == NULL) luaL_argerror(L, findex, "bad file");
 
71
  return f;
 
72
}
 
73
 
 
74
 
 
75
static gzFile tofile (lua_State *L, int findex) {
 
76
  gzFile*f = topfile(L, findex);
 
77
  if (*f == NULL)
 
78
    luaL_error(L, "attempt to use a closed file");
 
79
  return *f;
 
80
}
 
81
 
 
82
 
 
83
 
 
84
/*
 
85
** When creating file handles, always creates a `closed' file handle
 
86
** before opening the actual file; so, if there is a memory error, the
 
87
** file is not left opened.
 
88
*/
 
89
static gzFile *newfile (lua_State *L) {
 
90
  gzFile *pf = (gzFile*)lua_newuserdata(L, sizeof(gzFile));
 
91
  *pf = NULL;  /* file handle is currently `closed' */
 
92
  luaL_getmetatable(L, FILEHANDLE);
 
93
  lua_setmetatable(L, -2);
 
94
  return pf;
 
95
}
 
96
 
 
97
 
 
98
static int aux_close (lua_State *L) {
 
99
  gzFile f = tofile(L, 1);
 
100
  int ok = (gzclose(f) == Z_OK);
 
101
  if (ok)
 
102
    *(gzFile*)lua_touserdata(L, 1) = NULL;  /* mark file as closed */
 
103
  return ok;
 
104
}
 
105
 
 
106
 
 
107
static int io_close (lua_State *L) {
 
108
  return pushresult(L, aux_close(L), NULL);
 
109
}
 
110
 
 
111
 
 
112
static int io_gc (lua_State *L) {
 
113
  gzFile *f = topfile(L, 1);
 
114
  if (*f != NULL)  /* ignore closed files */
 
115
    aux_close(L);
 
116
  return 0;
 
117
}
 
118
 
 
119
 
 
120
static int io_tostring (lua_State *L) {
 
121
  char buff[128];
 
122
  gzFile *f = topfile(L, 1);
 
123
  if (*f == NULL)
 
124
    strcpy(buff, "closed");
 
125
  else
 
126
    sprintf(buff, "%p", lua_touserdata(L, 1));
 
127
  lua_pushfstring(L, "gzip file (%s)", buff);
 
128
  return 1;
 
129
}
 
130
 
 
131
 
 
132
static int io_open (lua_State *L) {
 
133
  const char *filename = luaL_checkstring(L, 1);
 
134
  const char *mode = luaL_optstring(L, 2, "rb");
 
135
  gzFile *pf = newfile(L);
 
136
  *pf = gzopen(filename, mode);
 
137
  return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
 
138
}
 
139
 
 
140
 
 
141
static int io_readline (lua_State *L);
 
142
 
 
143
static void aux_lines (lua_State *L, int idx, int close) {
 
144
  lua_pushliteral(L, FILEHANDLE);
 
145
  lua_rawget(L, LUA_REGISTRYINDEX);
 
146
  lua_pushvalue(L, idx);
 
147
  lua_pushboolean(L, close);  /* close/not close file when finished */
 
148
  lua_pushcclosure(L, io_readline, 3);
 
149
}
 
150
 
 
151
 
 
152
static int f_lines (lua_State *L) {
 
153
  tofile(L, 1);  /* check that it's a valid file handle */
 
154
  aux_lines(L, 1, 0);
 
155
  return 1;
 
156
}
 
157
 
 
158
 
 
159
static int io_lines (lua_State *L) {
 
160
  const char *filename = luaL_checkstring(L, 1);
 
161
  gzFile *pf = newfile(L);
 
162
  *pf = gzopen(filename, "rb");
 
163
  luaL_argcheck(L, *pf, 1,  strerror(errno));
 
164
  aux_lines(L, lua_gettop(L), 1);
 
165
  return 1;
 
166
}
 
167
 
 
168
 
 
169
/*
 
170
** {======================================================
 
171
** READ
 
172
** =======================================================
 
173
*/
 
174
 
 
175
 
 
176
static int test_eof (lua_State *L, gzFile f) {
 
177
  lua_pushlstring(L, NULL, 0);
 
178
  return (gzeof(f) != 1);
 
179
}
 
180
 
 
181
 
 
182
static int read_line (lua_State *L, gzFile f) {
 
183
  luaL_Buffer b;
 
184
  luaL_buffinit(L, &b);
 
185
  for (;;) {
 
186
    size_t l;
 
187
    char *p = luaL_prepbuffer(&b);
 
188
    if (gzgets(f, p, LUAL_BUFFERSIZE) == NULL) {  /* eof? */
 
189
      luaL_pushresult(&b);  /* close buffer */
 
190
      return (lua_strlen(L, -1) > 0);  /* check whether read something */
 
191
    }
 
192
    l = strlen(p);
 
193
    if (p[l-1] != '\n')
 
194
      luaL_addsize(&b, l);
 
195
    else {
 
196
      luaL_addsize(&b, l - 1);  /* do not include `eol' */
 
197
      luaL_pushresult(&b);  /* close buffer */
 
198
      return 1;  /* read at least an `eol' */
 
199
    }
 
200
  }
 
201
}
 
202
 
 
203
 
 
204
static int read_chars (lua_State *L, gzFile f, size_t n) {
 
205
  size_t rlen;  /* how much to read */
 
206
  size_t nr;  /* number of chars actually read */
 
207
  luaL_Buffer b;
 
208
  luaL_buffinit(L, &b);
 
209
  rlen = LUAL_BUFFERSIZE;  /* try to read that much each time */
 
210
  do {
 
211
    char *p = luaL_prepbuffer(&b);
 
212
    if (rlen > n) rlen = n;  /* cannot read more than asked */
 
213
    nr = gzread(f, p, rlen);
 
214
    luaL_addsize(&b, nr);
 
215
    n -= nr;  /* still have to read `n' chars */
 
216
  } while (n > 0 && nr == rlen);  /* until end of count or eof */
 
217
  luaL_pushresult(&b);  /* close buffer */
 
218
  return (n == 0 || lua_strlen(L, -1) > 0);
 
219
}
 
220
 
 
221
 
 
222
static int g_read (lua_State *L, gzFile f, int first) {
 
223
  int nargs = lua_gettop(L) - 1;
 
224
  int success;
 
225
  int n;
 
226
  if (nargs == 0) {  /* no arguments? */
 
227
    success = read_line(L, f);
 
228
    n = first+1;  /* to return 1 result */
 
229
  }
 
230
  else {  /* ensure stack space for all results and for auxlib's buffer */
 
231
    luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
 
232
    success = 1;
 
233
    for (n = first; nargs-- && success; n++) {
 
234
      if (lua_type(L, n) == LUA_TNUMBER) {
 
235
        size_t l = (size_t)lua_tonumber(L, n);
 
236
        success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
 
237
      }
 
238
      else {
 
239
        const char *p = lua_tostring(L, n);
 
240
        luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
 
241
        switch (p[1]) {
 
242
          case 'l':  /* line */
 
243
            success = read_line(L, f);
 
244
            break;
 
245
          case 'a':  /* file */
 
246
            read_chars(L, f, ~((size_t)0));  /* read MAX_SIZE_T chars */
 
247
            success = 1; /* always success */
 
248
            break;
 
249
          default:
 
250
            return luaL_argerror(L, n, "invalid format");
 
251
        }
 
252
      }
 
253
    }
 
254
  }
 
255
  if (!success) {
 
256
    lua_pop(L, 1);  /* remove last result */
 
257
    lua_pushnil(L);  /* push nil instead */
 
258
  }
 
259
  return n - first;
 
260
}
 
261
 
 
262
 
 
263
static int f_read (lua_State *L) {
 
264
  return g_read(L, tofile(L, 1), 2);
 
265
}
 
266
 
 
267
 
 
268
static int io_readline (lua_State *L) {
 
269
  gzFile f = *(gzFile*)lua_touserdata(L, lua_upvalueindex(2));
 
270
  if (f == NULL)  /* file is already closed? */
 
271
    luaL_error(L, "file is already closed");
 
272
  if (read_line(L, f)) return 1;
 
273
  else {  /* EOF */
 
274
    if (lua_toboolean(L, lua_upvalueindex(3))) {  /* generator created file? */
 
275
      lua_settop(L, 0);
 
276
      lua_pushvalue(L, lua_upvalueindex(2));
 
277
      aux_close(L);  /* close it */
 
278
    }
 
279
    return 0;
 
280
  }
 
281
}
 
282
 
 
283
/* }====================================================== */
 
284
 
 
285
 
 
286
static int g_write (lua_State *L, gzFile f, int arg) {
 
287
  int nargs = lua_gettop(L) - 1;
 
288
  int status = 1;
 
289
  for (; nargs--; arg++) {
 
290
    if (lua_type(L, arg) == LUA_TNUMBER) {
 
291
      /* optimization: could be done exactly as for strings */
 
292
      status = status &&
 
293
          gzprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
 
294
    }
 
295
    else {
 
296
      size_t l;
 
297
      const char *s = luaL_checklstring(L, arg, &l);
 
298
      status = status && (gzwrite(f, (char*)s, l) == l);
 
299
    }
 
300
  }
 
301
  return pushresult(L, status, NULL);
 
302
}
 
303
 
 
304
 
 
305
static int f_write (lua_State *L) {
 
306
  return g_write(L, tofile(L, 1), 2);
 
307
}
 
308
 
 
309
 
 
310
static int f_seek (lua_State *L) {
 
311
  static const int mode[] = {SEEK_SET, SEEK_CUR};
 
312
  static const char *const modenames[] = {"set", "cur", NULL};
 
313
  gzFile f = tofile(L, 1);
 
314
  int op = luaL_checkoption(L, 2, "cur", modenames);
 
315
  long offset = luaL_optlong(L, 3, 0);
 
316
  luaL_argcheck(L, op != -1, 2, "invalid mode");
 
317
  op = gzseek(f, offset, mode[op]);
 
318
  if (op == -1)
 
319
    return pushresult(L, 0, NULL);  /* error */
 
320
  else {
 
321
    lua_pushnumber(L, op);
 
322
    return 1;
 
323
  }
 
324
}
 
325
 
 
326
 
 
327
static int f_flush (lua_State *L) {
 
328
  return pushresult(L, gzflush(tofile(L, 1), Z_FINISH) == Z_OK, NULL);
 
329
}
 
330
 
 
331
 
 
332
static const luaL_reg iolib[] = {
 
333
  {"lines", io_lines},
 
334
  {"close", io_close},
 
335
  {"open", io_open},
 
336
  {NULL, NULL}
 
337
};
 
338
 
 
339
 
 
340
static const luaL_reg flib[] = {
 
341
  {"flush", f_flush},
 
342
  {"read", f_read},
 
343
  {"lines", f_lines},
 
344
  {"seek", f_seek},
 
345
  {"write", f_write},
 
346
  {"close", io_close},
 
347
  {"__gc", io_gc},
 
348
  {"__tostring", io_tostring},
 
349
  {NULL, NULL}
 
350
};
 
351
 
 
352
 
 
353
static void createmeta (lua_State *L) {
 
354
  luaL_newmetatable(L, FILEHANDLE);  /* create new metatable for file handles */
 
355
  /* file methods */
 
356
  lua_pushliteral(L, "__index");
 
357
  lua_pushvalue(L, -2);  /* push metatable */
 
358
  lua_rawset(L, -3);  /* metatable.__index = metatable */
 
359
  luaL_openlib(L, NULL, flib, 0);
 
360
}
 
361
 
 
362
 
 
363
/* }====================================================== */
 
364
 
 
365
 
 
366
 
 
367
LUALIB_API int luaopen_gzip (lua_State *L) {
 
368
  createmeta(L);
 
369
  lua_pushvalue(L, -1);
 
370
  luaL_openlib(L, "gzip", iolib, 1);
 
371
  return 1;
 
372
}
 
373