Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zlib Module #6069

Merged
merged 13 commits into from
Apr 6, 2022
2 changes: 2 additions & 0 deletions lib/uzlib/uzlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ typedef struct {
} TINF_TREE;

struct uzlib_uncomp {
/* Point to the CircuitPython object that owns this decompression stream */
void *self;
/* Pointer to the next byte in the input buffer */
const unsigned char *source;
/* Pointer to the next byte past the input buffer (source_limit = source + len) */
Expand Down
16 changes: 16 additions & 0 deletions py/circuitpy_defns.mk
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ endif
ifeq ($(CIRCUITPY_USTACK),1)
SRC_PATTERNS += ustack/%
endif
ifeq ($(CIRCUITPY_UZLIB),1)
SRC_PATTERNS += uzlib/%
endif
ifeq ($(CIRCUITPY_VIDEOCORE),1)
SRC_PATTERNS += videocore/%
endif
Expand Down Expand Up @@ -578,6 +581,8 @@ SRC_SHARED_MODULE_ALL = \
traceback/__init__.c \
uheap/__init__.c \
ustack/__init__.c \
uzlib/__init__.c \
uzlib/DecompIO.c \
vectorio/Circle.c \
vectorio/Polygon.c \
vectorio/Rectangle.c \
Expand Down Expand Up @@ -634,6 +639,17 @@ SRC_MOD += $(addprefix lib/protomatter/src/, \
$(BUILD)/lib/protomatter/src/core.o: CFLAGS += -include "shared-module/rgbmatrix/allocator.h" -DCIRCUITPY -Wno-missing-braces -Wno-missing-prototypes
endif

ifeq ($(CIRCUITPY_UZLIB),1)
SRC_MOD += $(addprefix lib/uzlib/, \
tinflate.c \
tinfzlib.c \
tinfgzip.c \
adler32.c \
crc32.c \
)
$(BUILD)/lib/uzlib/tinflate.o: CFLAGS += -Wno-missing-braces -Wno-missing-prototypes
endif

# All possible sources are listed here, and are filtered by SRC_PATTERNS.
SRC_SHARED_MODULE_INTERNAL = \
$(filter $(SRC_PATTERNS), \
Expand Down
4 changes: 4 additions & 0 deletions py/circuitpy_mpconfig.mk
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,10 @@ CFLAGS += -DUSB_NUM_ENDPOINT_PAIRS=$(USB_NUM_ENDPOINT_PAIRS)
CIRCUITPY_USTACK ?= 0
CFLAGS += -DCIRCUITPY_USTACK=$(CIRCUITPY_USTACK)

# for decompressing utlities
CIRCUITPY_UZLIB ?= 1
CFLAGS += -DCIRCUITPY_UZLIB=$(CIRCUITPY_UZLIB)

# ulab numerics library
CIRCUITPY_ULAB ?= $(CIRCUITPY_FULL_BUILD)
CFLAGS += -DCIRCUITPY_ULAB=$(CIRCUITPY_ULAB)
Expand Down
86 changes: 86 additions & 0 deletions shared-bindings/uzlib/DecompIO.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Mark Komus
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include <string.h>
#include "py/obj.h"
#include "py/stream.h"
#include "py/runtime.h"
#include "shared-bindings/uzlib/DecompIO.h"
#include "shared-module/uzlib/DecompIO.h"

STATIC mp_obj_t uzlib_decompio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, 2, false);
mp_get_stream_raise(args[0], MP_STREAM_OP_READ);

mp_obj_decompio_t *self = m_new_obj(mp_obj_decompio_t);
self->base.type = type;
memset(&self->decomp, 0, sizeof(self->decomp));

mp_int_t dict_opt = 0;
if (n_args > 1) {
dict_opt = mp_obj_get_int(args[1]);
}

common_hal_uzlib_decompio_construct(self, args[0], dict_opt);

return MP_OBJ_FROM_PTR(self);
}

STATIC mp_uint_t uzlib_decompio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
mp_obj_decompio_t *self = MP_OBJ_TO_PTR(self_in);
if (self->eof) {
return 0;
}

return common_hal_uzlib_decompio_read(self, buf, size, errcode);
}

STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
};

STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);

STATIC const mp_stream_p_t decompio_stream_p = {
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = uzlib_decompio_read,
.write = NULL,
.ioctl = NULL,
.is_text = false,
};

const mp_obj_type_t decompio_type = {
{ &mp_type_type },
.flags = MP_TYPE_FLAG_EXTENDED,
.name = MP_QSTR_DecompIO,
.make_new = uzlib_decompio_make_new,
.locals_dict = (void *)&decompio_locals_dict,
MP_TYPE_EXTENDED_FIELDS(
.protocol = &decompio_stream_p,
),
};
37 changes: 37 additions & 0 deletions shared-bindings/uzlib/DecompIO.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Mark Komus
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_UZLIB_DECOMPIO_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_UZLIB_DECOMPIO_H

#include "shared-module/uzlib/DecompIO.h"

extern const mp_obj_type_t decompio_type;

extern void common_hal_uzlib_decompio_construct(mp_obj_decompio_t *self, mp_obj_t src_stream, mp_int_t dict_opt);
extern mp_uint_t common_hal_uzlib_decompio_read(mp_obj_decompio_t *self, void *buf, mp_uint_t size, int *errcode);

#endif // MICROPY_INCLUDED_SHARED_BINDINGS_UZLIB_DECOMPIO_H
72 changes: 72 additions & 0 deletions shared-bindings/uzlib/__init__.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Mark Komus
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include <stdint.h>
#include <assert.h>
#include <string.h>

#include "py/obj.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mperrno.h"
#include "py/builtin.h"
#include "py/objtuple.h"
#include "py/binary.h"
#include "py/parsenum.h"

#include "shared-bindings/uzlib/DecompIO.h"

#include "supervisor/shared/translate.h"

#include "shared-bindings/uzlib/__init__.h"
#include "shared-bindings/uzlib/DecompIO.h"

STATIC mp_obj_t uzlib_decompress(size_t n_args, const mp_obj_t *args) {
// TODO: Check number of args

bool is_zlib = true;
if (n_args > 1 && MP_OBJ_SMALL_INT_VALUE(args[1]) < 0) {
is_zlib = false;
}

return common_hal_uzlib_decompress(args[0], is_zlib);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(uzlib_decompress_obj, 1, 3, uzlib_decompress);

STATIC const mp_rom_map_elem_t uzlib_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uzlib) },
{ MP_ROM_QSTR(MP_QSTR_decompress), MP_ROM_PTR(&uzlib_decompress_obj) },
{ MP_ROM_QSTR(MP_QSTR_DecompIO), MP_ROM_PTR(&decompio_type) },
};

STATIC MP_DEFINE_CONST_DICT(uzlib_globals, uzlib_globals_table);

const mp_obj_module_t uzlib_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&uzlib_globals,
};

MP_REGISTER_MODULE(MP_QSTR_uzlib, uzlib_module, CIRCUITPY_UZLIB);
32 changes: 32 additions & 0 deletions shared-bindings/uzlib/__init__.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Mark Komus
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_UZLIB___INIT___H
#define MICROPY_INCLUDED_SHARED_BINDINGS_UZLIB___INIT___H

mp_obj_t common_hal_uzlib_decompress(mp_obj_t data, bool is_zlib);

#endif // MICROPY_INCLUDED_SHARED_BINDINGS_UZLIB___INIT___H
101 changes: 101 additions & 0 deletions shared-module/uzlib/DecompIO.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Mark Komus
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include <stdint.h>
#include <assert.h>
#include <string.h>

#include "py/obj.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mperrno.h"
#include "py/builtin.h"
#include "py/objtuple.h"
#include "py/binary.h"
#include "py/parsenum.h"

#include "shared-bindings/uzlib/__init__.h"
#include "shared-bindings/uzlib/DecompIO.h"
#include "shared-module/uzlib/DecompIO.h"

STATIC int read_src_stream(TINF_DATA *data) {
mp_obj_decompio_t *self = (mp_obj_decompio_t *)data->self;

const mp_stream_p_t *stream = mp_get_stream_raise(self->src_stream, MP_STREAM_OP_READ);
int err;
byte c;
mp_uint_t out_sz = stream->read(self->src_stream, &c, 1, &err);

if (out_sz == MP_STREAM_ERROR) {
mp_raise_OSError(err);
}
if (out_sz == 0) {
mp_raise_type(&mp_type_EOFError);
}
return c;
}

void common_hal_uzlib_decompio_construct(mp_obj_decompio_t *self, mp_obj_t src_stream, mp_int_t dict_opt) {
self->decomp.self = self;
self->decomp.readSource = read_src_stream;
self->src_stream = src_stream;
self->eof = false;

int dict_sz;

if (dict_opt >= 16) {
int st = uzlib_gzip_parse_header(&self->decomp);
if (st != TINF_OK) {
goto header_error;
}
dict_sz = 1 << (dict_opt - 16);
} else if (dict_opt >= 0) {
dict_opt = uzlib_zlib_parse_header(&self->decomp);
if (dict_opt < 0) {
header_error:
mp_raise_ValueError(MP_ERROR_TEXT("compression header"));
}
dict_sz = 1 << dict_opt;
} else {
dict_sz = 1 << -dict_opt;
}

uzlib_uncompress_init(&self->decomp, m_new(byte, dict_sz), dict_sz);
}

mp_uint_t common_hal_uzlib_decompio_read(mp_obj_decompio_t *self, void *buf, mp_uint_t size, int *errcode) {
self->decomp.dest = buf;
self->decomp.dest_limit = (unsigned char *)buf + size;
int st = uzlib_uncompress_chksum(&self->decomp);
if (st == TINF_DONE) {
self->eof = true;
}
if (st < 0) {
*errcode = MP_EINVAL;
return MP_STREAM_ERROR;
}
return self->decomp.dest - (byte *)buf;
}
Loading