Merge pull request #904 from pfalcon/moduzlib

Module "uzlib" - based on similarly named library
This commit is contained in:
Damien George
2014-10-12 23:25:24 +01:00
12 changed files with 923 additions and 2 deletions
+115
View File
@@ -0,0 +1,115 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Paul Sokolovsky
*
* 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 <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <math.h>
#include "mpconfig.h"
#include "misc.h"
#include "qstr.h"
#include "nlr.h"
#include "obj.h"
#include "runtime.h"
#if MICROPY_PY_UZLIB
#include "uzlib/tinf.h"
#if 0 // print debugging info
#define DEBUG_printf DEBUG_printf
#else // don't print debugging info
#define DEBUG_printf(...) (void)0
#endif
STATIC int mod_uzlib_grow_buf(TINF_DATA *d, unsigned alloc_req)
{
if (alloc_req < 256) {
alloc_req = 256;
}
DEBUG_printf("uzlib: Resizing buffer to " UINT_FMT " bytes\n", d->destSize + alloc_req);
d->destStart = m_renew(byte, d->destStart, d->destSize, d->destSize + alloc_req);
d->destSize += alloc_req;
return 0;
}
STATIC mp_obj_t mod_uzlib_decompress(uint n_args, mp_obj_t *args) {
mp_obj_t data = args[0];
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
TINF_DATA *decomp = m_new_obj(TINF_DATA);
DEBUG_printf("sizeof(TINF_DATA)=" UINT_FMT "\n", sizeof(*decomp));
decomp->destStart = m_new(byte, bufinfo.len);
decomp->destSize = bufinfo.len;
decomp->destGrow = mod_uzlib_grow_buf;
decomp->source = bufinfo.buf;
int st = tinf_zlib_uncompress_dyn(decomp, bufinfo.len);
if (st != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st)));
}
mp_obj_t res = mp_obj_new_bytearray_by_ref(decomp->dest - decomp->destStart, decomp->destStart);
m_del_obj(TINF_DATA, decomp);
return res;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_uzlib_decompress_obj, 1, 3, mod_uzlib_decompress);
STATIC const mp_map_elem_t mp_module_uzlib_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uzlib) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_decompress), (mp_obj_t)&mod_uzlib_decompress_obj },
};
STATIC const mp_obj_dict_t mp_module_uzlib_globals = {
.base = {&mp_type_dict},
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
.used = MP_ARRAY_SIZE(mp_module_uzlib_globals_table),
.alloc = MP_ARRAY_SIZE(mp_module_uzlib_globals_table),
.table = (mp_map_elem_t*)mp_module_uzlib_globals_table,
},
};
const mp_obj_module_t mp_module_uzlib = {
.base = { &mp_type_module },
.name = MP_QSTR_uzlib,
.globals = (mp_obj_dict_t*)&mp_module_uzlib_globals,
};
// Source files #include'd here to make sure they're compiled in
// only if module is enabled by config setting.
#include "uzlib/tinflate.c"
#include "uzlib/tinfzlib.c"
#include "uzlib/adler32.c"
#endif //MICROPY_PY_UZLIB
+78
View File
@@ -0,0 +1,78 @@
/*
* Adler-32 checksum
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* This software is provided 'as-is', without any express
* or implied warranty. In no event will the authors be
* held liable for any damages arising from the use of
* this software.
*
* Permission is granted to anyone to use this software
* for any purpose, including commercial applications,
* and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The origin of this software must not be
* misrepresented; you must not claim that you
* wrote the original software. If you use this
* software in a product, an acknowledgment in
* the product documentation would be appreciated
* but is not required.
*
* 2. Altered source versions must be plainly marked
* as such, and must not be misrepresented as
* being the original software.
*
* 3. This notice may not be removed or altered from
* any source distribution.
*/
/*
* Adler-32 algorithm taken from the zlib source, which is
* Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
*/
#include "tinf.h"
#define A32_BASE 65521
#define A32_NMAX 5552
unsigned int tinf_adler32(const void *data, unsigned int length)
{
const unsigned char *buf = (const unsigned char *)data;
unsigned int s1 = 1;
unsigned int s2 = 0;
while (length > 0)
{
int k = length < A32_NMAX ? length : A32_NMAX;
int i;
for (i = k / 16; i; --i, buf += 16)
{
s1 += buf[0]; s2 += s1; s1 += buf[1]; s2 += s1;
s1 += buf[2]; s2 += s1; s1 += buf[3]; s2 += s1;
s1 += buf[4]; s2 += s1; s1 += buf[5]; s2 += s1;
s1 += buf[6]; s2 += s1; s1 += buf[7]; s2 += s1;
s1 += buf[8]; s2 += s1; s1 += buf[9]; s2 += s1;
s1 += buf[10]; s2 += s1; s1 += buf[11]; s2 += s1;
s1 += buf[12]; s2 += s1; s1 += buf[13]; s2 += s1;
s1 += buf[14]; s2 += s1; s1 += buf[15]; s2 += s1;
}
for (i = k % 16; i; --i) { s1 += *buf++; s2 += s1; }
s1 %= A32_BASE;
s2 %= A32_BASE;
length -= k;
}
return (s2 << 16) | s1;
}
+102
View File
@@ -0,0 +1,102 @@
/*
* uzlib - tiny deflate/inflate library (deflate, gzip, zlib)
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
* http://www.ibsensoftware.com/
*
* Copyright (c) 2014 by Paul Sokolovsky
*/
#ifndef TINF_H_INCLUDED
#define TINF_H_INCLUDED
#include <stdint.h>
/* calling convention */
#ifndef TINFCC
#ifdef __WATCOMC__
#define TINFCC __cdecl
#else
#define TINFCC
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define TINF_OK 0
#define TINF_DATA_ERROR (-3)
#define TINF_DEST_OVERFLOW (-4)
/* data structures */
typedef struct {
unsigned short table[16]; /* table of code length counts */
unsigned short trans[288]; /* code -> symbol translation table */
} TINF_TREE;
struct TINF_DATA;
typedef struct TINF_DATA {
const unsigned char *source;
unsigned int tag;
unsigned int bitcount;
/* Buffer start */
unsigned char *destStart;
/* Buffer total size */
unsigned int destSize;
/* Current pointer in buffer */
unsigned char *dest;
/* Remaining bytes in buffer */
unsigned int destRemaining;
/* Argument is the allocation size which didn't fit into buffer. Note that
exact mimumum size to grow buffer by is lastAlloc - destRemaining. But
growing by this exact size is ineficient, as the next allocation will
fail again. */
int (*destGrow)(struct TINF_DATA *data, unsigned int lastAlloc);
TINF_TREE ltree; /* dynamic length/symbol tree */
TINF_TREE dtree; /* dynamic distance tree */
} TINF_DATA;
/* low-level API */
/* Step 1: Allocate TINF_DATA structure */
/* Step 2: Set destStart, destSize, and destGrow fields */
/* Step 3: Set source field */
/* Step 4: Call tinf_uncompress_dyn() */
/* Step 5: In response to destGrow callback, update destStart and destSize fields */
/* Step 6: When tinf_uncompress_dyn() returns, buf.dest points to a byte past last uncompressed byte */
int TINFCC tinf_uncompress_dyn(TINF_DATA *d);
int TINFCC tinf_zlib_uncompress_dyn(TINF_DATA *d, unsigned int sourceLen);
/* high-level API */
void TINFCC tinf_init();
int TINFCC tinf_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
int TINFCC tinf_gzip_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
int TINFCC tinf_zlib_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
unsigned int TINFCC tinf_adler32(const void *data, unsigned int length);
unsigned int TINFCC tinf_crc32(const void *data, unsigned int length);
/* compression API */
void TINFCC tinf_compress(void *data, const uint8_t *src, unsigned slen);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* TINF_H_INCLUDED */
File diff suppressed because it is too large Load Diff
+101
View File
@@ -0,0 +1,101 @@
/*
* tinfzlib - tiny zlib decompressor
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* This software is provided 'as-is', without any express
* or implied warranty. In no event will the authors be
* held liable for any damages arising from the use of
* this software.
*
* Permission is granted to anyone to use this software
* for any purpose, including commercial applications,
* and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The origin of this software must not be
* misrepresented; you must not claim that you
* wrote the original software. If you use this
* software in a product, an acknowledgment in
* the product documentation would be appreciated
* but is not required.
*
* 2. Altered source versions must be plainly marked
* as such, and must not be misrepresented as
* being the original software.
*
* 3. This notice may not be removed or altered from
* any source distribution.
*/
#include "tinf.h"
int tinf_zlib_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen)
{
TINF_DATA d;
int res;
/* initialise data */
d.source = (const unsigned char *)source;
d.destStart = (unsigned char *)dest;
d.destRemaining = *destLen;
res = tinf_zlib_uncompress_dyn(&d, sourceLen);
*destLen = d.dest - d.destStart;
return res;
}
int tinf_zlib_uncompress_dyn(TINF_DATA *d, unsigned int sourceLen)
{
unsigned int a32;
int res;
unsigned char cmf, flg;
/* -- get header bytes -- */
cmf = d->source[0];
flg = d->source[1];
/* -- check format -- */
/* check checksum */
if ((256*cmf + flg) % 31) return TINF_DATA_ERROR;
/* check method is deflate */
if ((cmf & 0x0f) != 8) return TINF_DATA_ERROR;
/* check window size is valid */
if ((cmf >> 4) > 7) return TINF_DATA_ERROR;
/* check there is no preset dictionary */
if (flg & 0x20) return TINF_DATA_ERROR;
/* -- get adler32 checksum -- */
a32 = d->source[sourceLen - 4];
a32 = 256*a32 + d->source[sourceLen - 3];
a32 = 256*a32 + d->source[sourceLen - 2];
a32 = 256*a32 + d->source[sourceLen - 1];
d->source += 2;
/* -- inflate -- */
res = tinf_uncompress_dyn(d);
if (res != TINF_OK) return res;
/* -- check adler32 checksum -- */
if (a32 != tinf_adler32(d->destStart, d->dest - d->destStart)) return TINF_DATA_ERROR;
return TINF_OK;
}
+1
View File
@@ -89,5 +89,6 @@ extern struct _dummy_t mp_sys_stderr_obj;
// extmod modules
extern const mp_obj_module_t mp_module_uctypes;
extern const mp_obj_module_t mp_module_zlibd;
extern const mp_obj_module_t mp_module_uzlib;
extern const mp_obj_module_t mp_module_ujson;
extern const mp_obj_module_t mp_module_ure;
+3
View File
@@ -206,6 +206,9 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = {
#if MICROPY_PY_ZLIBD
{ MP_OBJ_NEW_QSTR(MP_QSTR_zlibd), (mp_obj_t)&mp_module_zlibd },
#endif
#if MICROPY_PY_UZLIB
{ MP_OBJ_NEW_QSTR(MP_QSTR_uzlib), (mp_obj_t)&mp_module_uzlib },
#endif
#if MICROPY_PY_UJSON
{ MP_OBJ_NEW_QSTR(MP_QSTR_ujson), (mp_obj_t)&mp_module_ujson },
#endif
+4
View File
@@ -395,6 +395,10 @@ typedef double mp_float_t;
#define MICROPY_PY_ZLIBD (0)
#endif
#ifndef MICROPY_PY_UZLIB
#define MICROPY_PY_UZLIB (0)
#endif
#ifndef MICROPY_PY_UJSON
#define MICROPY_PY_UJSON (0)
#endif
+1
View File
@@ -114,6 +114,7 @@ PY_O_BASENAME = \
../extmod/modzlibd.o \
../extmod/modujson.o \
../extmod/modure.o \
../extmod/moduzlib.o \
# prepend the build destination prefix to the py object files
PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME))
+5
View File
@@ -468,6 +468,11 @@ Q(zlibd)
Q(decompress)
#endif
#if MICROPY_PY_UZLIB
Q(uzlib)
Q(decompress)
#endif
#if MICROPY_PY_UJSON
Q(ujson)
Q(dumps)
+1 -1
View File
@@ -1,7 +1,7 @@
try:
import zlib
except ImportError:
import zlibd as zlib
import uzlib as zlib
PATTERNS = [
# Packed results produced by CPy's zlib.compress()
+1 -1
View File
@@ -55,7 +55,7 @@
#define MICROPY_PY_GC_COLLECT_RETVAL (1)
#define MICROPY_PY_UCTYPES (1)
#define MICROPY_PY_ZLIBD (1)
#define MICROPY_PY_UZLIB (1)
#define MICROPY_PY_UJSON (1)
#define MICROPY_PY_URE (1)