Skip to content

Commit a6864a1

Browse files
committed
extmod/moduzlib: Implement zlib stream decompressor class, DecompIO.
1 parent c51c883 commit a6864a1

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

extmod/moduzlib.c

+82-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* The MIT License (MIT)
55
*
6-
* Copyright (c) 2014 Paul Sokolovsky
6+
* Copyright (c) 2014-2016 Paul Sokolovsky
77
*
88
* Permission is hereby granted, free of charge, to any person obtaining a copy
99
* of this software and associated documentation files (the "Software"), to deal
@@ -29,6 +29,7 @@
2929

3030
#include "py/nlr.h"
3131
#include "py/runtime.h"
32+
#include "py/stream.h"
3233

3334
#if MICROPY_PY_UZLIB
3435

@@ -40,6 +41,85 @@
4041
#define DEBUG_printf(...) (void)0
4142
#endif
4243

44+
typedef struct _mp_obj_decompio_t {
45+
mp_obj_base_t base;
46+
mp_obj_t src_stream;
47+
TINF_DATA decomp;
48+
bool eof;
49+
} mp_obj_decompio_t;
50+
51+
STATIC unsigned char read_src_stream(TINF_DATA *data) {
52+
byte *p = (void*)data;
53+
p -= offsetof(mp_obj_decompio_t, decomp);
54+
mp_obj_decompio_t *self = (mp_obj_decompio_t*)p;
55+
56+
const mp_stream_p_t *stream = mp_get_stream_raise(self->src_stream, MP_STREAM_OP_READ);
57+
int err;
58+
byte c;
59+
mp_uint_t out_sz = stream->read(self->src_stream, &c, 1, &err);
60+
if (out_sz == MP_STREAM_ERROR) {
61+
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(err)));
62+
}
63+
if (out_sz == 0) {
64+
nlr_raise(mp_obj_new_exception(&mp_type_EOFError));
65+
}
66+
return c;
67+
}
68+
69+
#define DICT_SIZE 32768
70+
71+
STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
72+
mp_arg_check_num(n_args, n_kw, 1, 1, false);
73+
mp_obj_decompio_t *o = m_new_obj(mp_obj_decompio_t);
74+
o->base.type = type;
75+
memset(&o->decomp, 0, sizeof(o->decomp));
76+
uzlib_uncompress_init(&o->decomp, m_new(byte, DICT_SIZE), DICT_SIZE);
77+
o->decomp.readSource = read_src_stream;
78+
o->src_stream = args[0];
79+
o->eof = false;
80+
return MP_OBJ_FROM_PTR(o);
81+
}
82+
83+
STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
84+
mp_obj_decompio_t *o = MP_OBJ_TO_PTR(o_in);
85+
if (o->eof) {
86+
return 0;
87+
}
88+
89+
o->decomp.dest = buf;
90+
o->decomp.destSize = size;
91+
int st = uzlib_uncompress_chksum(&o->decomp);
92+
if (st == TINF_DONE) {
93+
o->eof = true;
94+
}
95+
if (st < 0) {
96+
*errcode = EINVAL;
97+
return MP_STREAM_ERROR;
98+
}
99+
return o->decomp.dest - (byte*)buf;
100+
}
101+
102+
STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = {
103+
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
104+
{ MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_obj) },
105+
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
106+
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
107+
};
108+
109+
STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
110+
111+
STATIC const mp_stream_p_t decompio_stream_p = {
112+
.read = decompio_read,
113+
};
114+
115+
STATIC const mp_obj_type_t decompio_type = {
116+
{ &mp_type_type },
117+
.name = MP_QSTR_DecompIO,
118+
.make_new = decompio_make_new,
119+
.protocol = &decompio_stream_p,
120+
.locals_dict = (void*)&decompio_locals_dict,
121+
};
122+
43123
STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
44124
(void)n_args;
45125
mp_obj_t data = args[0];
@@ -102,6 +182,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_uzlib_decompress_obj, 1, 3, mod_u
102182
STATIC const mp_rom_map_elem_t mp_module_uzlib_globals_table[] = {
103183
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uzlib) },
104184
{ MP_ROM_QSTR(MP_QSTR_decompress), MP_ROM_PTR(&mod_uzlib_decompress_obj) },
185+
{ MP_ROM_QSTR(MP_QSTR_DecompIO), MP_ROM_PTR(&decompio_type) },
105186
};
106187

107188
STATIC MP_DEFINE_CONST_DICT(mp_module_uzlib_globals, mp_module_uzlib_globals_table);

0 commit comments

Comments
 (0)