Skip to content

Commit bdb88c8

Browse files
committed
core/test: refactors standard reader into lbz2_file_reader to mirror lbz2_file_writer and removes line buffering/handling
1 parent b807a2a commit bdb88c8

7 files changed

+194
-336
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ else
1414
PFLAGS = $(shell pkg-config --cflags lua)
1515
endif
1616

17-
SOURCES = lbz.c lbz2_file_writer.c lbz2_stream.c lbz2_common.c
17+
SOURCES = lbz.c lbz2_file_reader.c lbz2_file_writer.c lbz2_stream.c lbz2_common.c
1818

1919
bz2.so: $(SOURCES)
2020
$(CC) $(SOFLAGS) $(PFLAGS) $(CFLAGS) $(SOURCES) $(LDFLAGS) -o bz2.so

lbz.c

+5-299
Original file line numberDiff line numberDiff line change
@@ -16,320 +16,26 @@
1616
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1717
*/
1818

19-
#include <bzlib.h>
20-
#include <stdio.h>
21-
#include <stdlib.h>
22-
#include <string.h>
2319
#include <lua.h>
2420
#include <lauxlib.h>
2521

26-
#include <assert.h>
27-
22+
#include "lbz2_file_reader.h"
2823
#include "lbz2_file_writer.h"
2924
#include "lbz2_stream.h"
3025

31-
#define LBZ_STATE_META "LuaBook.bz2"
32-
33-
typedef struct {
34-
BZFILE *bz_stream;
35-
FILE *f;
36-
37-
/* getline related stuff */
38-
char *buf;
39-
size_t buf_size; /* max == LUAL_BUFFERSIZE */
40-
} lbz_state;
41-
42-
/* Forward declarations */
43-
static lbz_state *lbz_check_state(lua_State *L, int index);
44-
45-
static int lbz_read_open(lua_State *L);
46-
static int lbz_read(lua_State *L);
47-
static void lbz_perform_close(lbz_state *state, int keep_extra_buf);
48-
static int lbz_read_close(lua_State *L);
49-
static int lbz_getline(lua_State *L);
50-
static int lbz_getline_read(lua_State *L, luaL_Buffer *b, lbz_state *state, int keep_eol);
51-
52-
static int lbz_lines(lua_State *L);
53-
54-
static void lbz_buffer_init(lbz_state *state);
55-
static void lbz_buffer_free(lbz_state *state);
56-
57-
static void lbz_buffer_append(lbz_state *state, const char *data, size_t data_len);
58-
static void lbz_buffer_drain(lbz_state *state, size_t amount);
59-
static void lbz_buffer_drain_all(lbz_state *state);
60-
61-
static const struct luaL_reg bzlib_f [] = {
62-
{"open", lbz_read_open},
63-
{NULL, NULL} /* Sentinel */
26+
static luaL_Reg lbz2_global[] = {
27+
{ NULL, NULL }
6428
};
6529

66-
static const struct luaL_reg bzlib_m [] = {
67-
{"read", lbz_read},
68-
{"getline", lbz_getline},
69-
{"close", lbz_read_close},
70-
{"lines", lbz_lines},
71-
{NULL, NULL} /* Sentinel */
72-
};
73-
74-
lbz_state *lbz_check_state(lua_State *L, int index) {
75-
return (lbz_state *)luaL_checkudata(L, index, LBZ_STATE_META);
76-
}
77-
78-
/* Binding to libbzip2's BZ2_bzReadOpen method */
79-
int lbz_read_open(lua_State *L) {
80-
size_t len;
81-
const char *fname = lua_tolstring(L, 1, &len);
82-
FILE *f = fopen(fname, "rb");
83-
84-
if (f == NULL)
85-
return luaL_error(L, "Failed to fopen %s", fname);
86-
87-
int bzerror;
88-
lbz_state *state = (lbz_state *) lua_newuserdata(L, sizeof(lbz_state));
89-
state->bz_stream = BZ2_bzReadOpen(&bzerror, f, 0, 0, NULL, 0);
90-
state->f = f;
91-
92-
lbz_buffer_init(state);
93-
94-
luaL_getmetatable(L, LBZ_STATE_META);
95-
lua_setmetatable(L, -2);
96-
97-
if (bzerror != BZ_OK)
98-
lua_pushnil(L);
99-
100-
return 1;
101-
}
102-
103-
void lbz_buffer_init(lbz_state *state) {
104-
state->buf = malloc(LUAL_BUFFERSIZE);
105-
state->buf_size = 0;
106-
}
107-
108-
void lbz_buffer_free(lbz_state *state) {
109-
if(!state->buf) return;
110-
state->buf_size = 0;
111-
free(state->buf);
112-
state->buf = NULL;
113-
}
114-
115-
void lbz_buffer_append(lbz_state *state, const char *data, size_t data_size) {
116-
assert(state->buf_size + data_size < LUAL_BUFFERSIZE);
117-
memmove(state->buf + state->buf_size, data, data_size);
118-
state->buf_size += data_size;
119-
}
120-
121-
void lbz_buffer_drain(lbz_state *state, size_t amount) {
122-
memmove(state->buf, state->buf + amount, state->buf_size - amount);
123-
state->buf_size -= amount;
124-
}
125-
126-
void lbz_buffer_drain_all(lbz_state *state) {
127-
state->buf_size = 0;
128-
}
129-
130-
/* Binding to libbzip2's BZ2_bzReadOpen method */
131-
static int lbz_read(lua_State *L) {
132-
int bzerror = BZ_OK;
133-
int len;
134-
luaL_Buffer b;
135-
lbz_state *state = lbz_check_state(L, 1);
136-
len = luaL_checkint(L, 2);
137-
138-
if (!state->bz_stream && !state->buf) {
139-
/* The logical end of file has been reached -- there's no more data to
140-
* return, and the user should call the read_close method. */
141-
lua_pushnil(L);
142-
lua_pushstring(L, "CLOSED");
143-
return 2;
144-
}
145-
luaL_buffinit(L, &b);
146-
147-
/* In case this function is being used alongsize the getline method, we
148-
* should use the buffers that getline is using */
149-
if (state->buf_size) {
150-
int used_len = (state->buf_size < len) ? state->buf_size : len;
151-
luaL_addlstring(&b, state->buf, used_len);
152-
lbz_buffer_drain(state, used_len);
153-
len -= used_len;
154-
}
155-
156-
/* Pull in chunks until all data read */
157-
while(len > 0) {
158-
char *buf = luaL_prepbuffer(&b);
159-
int nextRead = len > LUAL_BUFFERSIZE ? LUAL_BUFFERSIZE : len;
160-
int read = BZ2_bzRead(&bzerror, state->bz_stream, buf, nextRead);
161-
if (read > 0) {
162-
luaL_addsize(&b, read);
163-
len -= read;
164-
}
165-
if (bzerror != BZ_OK)
166-
goto handle_error;
167-
}
168-
luaL_pushresult(&b);
169-
return 1;
170-
handle_error:
171-
if(BZ_STREAM_END == bzerror) {
172-
/* Push the data read already and mark the stream done */
173-
luaL_pushresult(&b);
174-
lbz_perform_close(state, 0);
175-
return 1;
176-
} else {
177-
lua_pushnil(L);
178-
lua_pushstring(L, BZ2_bzerror(state->bz_stream, &bzerror));
179-
return 2;
180-
}
181-
}
182-
183-
void lbz_perform_close(lbz_state *state, int keep_extra_buf) {
184-
int bzerror;
185-
if(!keep_extra_buf)
186-
lbz_buffer_free(state);
187-
if(!state->bz_stream)
188-
return;
189-
BZ2_bzReadClose(&bzerror, state->bz_stream);
190-
fclose(state->f);
191-
state->bz_stream = NULL;
192-
state->f = NULL;
193-
}
194-
195-
/* Binding to libbzip2's BZ2_bzReadClose method */
196-
static int lbz_read_close(lua_State *L) {
197-
lbz_state *state = lbz_check_state(L, 1);
198-
lbz_perform_close(state, 0);
199-
return 0;
200-
}
201-
202-
/*
203-
* GETLINE STUFF
204-
* This code is considerably more complicated... if you know of a simpler way
205-
* to do it that doesn't sacrifice speed, please let me know.
206-
*/
207-
208-
static int lbz_handle_eol(luaL_Buffer *b, char *buf, size_t buf_len, lbz_state *state, int in_buffer, int keep_eol) {
209-
char *eol = memchr(buf, '\n', buf_len);
210-
size_t chars_to_return;
211-
212-
/* If a newline hasn't been found, keep iterating while building up
213-
* the buffer */
214-
if(eol == NULL) {
215-
if(in_buffer)
216-
luaL_addsize(b, buf_len);
217-
else
218-
luaL_addlstring(b, buf, buf_len);
219-
return 0;
220-
}
221-
chars_to_return = eol - buf;
222-
eol++;
223-
if(keep_eol)
224-
chars_to_return++;
225-
if(in_buffer)
226-
luaL_addsize(b, chars_to_return);
227-
else
228-
luaL_addlstring(b, buf, chars_to_return);
229-
/* Save the remaining data end of data - position of beginning */
230-
lbz_buffer_append(state, eol, buf_len - (eol - buf));
231-
luaL_pushresult(b);
232-
return 1;
233-
}
234-
/* This is an auxilliary function that lbz_getline calls when it needs to
235-
* actually use the BZ2_bzRead method to read more data from the bzipped file.
236-
**/
237-
static int lbz_getline_read(lua_State *L, luaL_Buffer *b, lbz_state *state, int keep_eol) {
238-
int bzerror;
239-
240-
/* The entire 'extra_buf' buffer is needed */
241-
luaL_addlstring(b, state->buf, state->buf_size);
242-
lbz_buffer_drain_all(state);
243-
244-
if (!state->bz_stream) { /* No more data left at all - return data is 'success' */
245-
lbz_perform_close(state, 0); // Completely close it out now
246-
luaL_pushresult(b);
247-
return 1;
248-
}
249-
while(1) {
250-
char *buf = luaL_prepbuffer(b);
251-
int len = BZ2_bzRead(&bzerror, state->bz_stream, buf, LUAL_BUFFERSIZE);
252-
253-
if ((bzerror != BZ_OK) && (bzerror != BZ_STREAM_END)) {
254-
/* Error happened, data thrown */
255-
lua_pushnil(L);
256-
lua_pushstring(L, BZ2_bzerror(state->bz_stream, &bzerror));
257-
return 2;
258-
}
259-
if (!lbz_handle_eol(b, buf, len, state, 1, keep_eol))
260-
continue;
261-
262-
/* Kill the stream, keep the remaining buffer */
263-
if (bzerror == BZ_STREAM_END)
264-
lbz_perform_close(state, state->buf_size ? 1 : 0);
265-
return 1;
266-
}
267-
return 0;
268-
}
269-
270-
static int lbz_getline(lua_State *L) {
271-
lbz_state *state = lbz_check_state(L, 1);
272-
int skip_eol = lua_toboolean(L, 2);
273-
luaL_Buffer b;
274-
275-
if (!state->bz_stream && !state->buf) {
276-
lua_pushnil(L);
277-
lua_pushstring(L, "CLOSED");
278-
return 2;
279-
}
280-
281-
luaL_buffinit(L, &b);
282-
if (state->buf_size) {
283-
size_t data_size = state->buf_size;
284-
lbz_buffer_drain_all(state);
285-
/* Drain entire buffer so that remaining data can be appropriately added */
286-
if (!lbz_handle_eol(&b, state->buf, data_size, state, 0, !skip_eol))
287-
return lbz_getline_read(L, &b, state, !skip_eol);
288-
return 1;
289-
}
290-
291-
/* If there was no extra data from the last pass then we need to call
292-
* lbz_getline_read directly to get more data and find the newline. */
293-
return lbz_getline_read(L, &b, state, !skip_eol);
294-
}
295-
296-
static int lbz_line_iter(lua_State *L) {
297-
lua_settop(L, 0);
298-
lua_pushvalue(L, lua_upvalueindex(1));
299-
lua_pushvalue(L, lua_upvalueindex(2));
300-
return lbz_getline(L);
301-
}
302-
303-
/* (bz):lines(keep_eol) */
304-
int lbz_lines(lua_State *L) {
305-
int skip_eol = !lua_toboolean(L, 2);
306-
lua_pushvalue(L, 1);
307-
lua_pushboolean(L, skip_eol);
308-
lua_pushcclosure(L, lbz_line_iter, 2);
309-
return 1;
310-
}
311-
312-
static int lbz_gc(lua_State *L) {
313-
lbz_read_close(L);
314-
return 0;
315-
}
316-
31730
int luaopen_bz2(lua_State *L) {
318-
luaL_newmetatable(L, LBZ_STATE_META);
319-
lua_newtable(L);
320-
luaL_register(L, NULL, bzlib_m);
321-
lua_setfield(L, -2, "__index");
322-
323-
lua_pushcfunction(L, lbz_gc);
324-
lua_setfield(L, -2, "__gc");
325-
lua_pop(L, 1);
31+
luaL_register(L, "bz2", lbz2_global);
32632

32733
lua_pushliteral(L, "bz2");
32834
lua_setfield(L, -2, "_NAME");
32935
lua_pushliteral(L, "0.1");
33036
lua_setfield(L, -2, "_VERSION");
331-
luaL_register(L, "bz2", bzlib_f);
33237

38+
register_lbz2_file_reader(L);
33339
register_lbz2_file_writer(L);
33440
register_lbz2_stream(L);
33541

0 commit comments

Comments
 (0)