Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 56 additions & 32 deletions lzo.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@

import struct
import io
import __builtin__
import builtins
from _lzo import *

from enum import IntFlag

__all__ = ["LzoFile", "open"]

MAGIC = b"\x89\x4C\x5A\x4F\x00\x0D\x0A\x1A\x0A"
Expand All @@ -18,25 +20,41 @@
LZO_LIB_VERSION = 0x0940


BLOCK_SIZE = (128*1024L)
MAX_BLOCK_SIZE = (64*1024l*1024L)


F_ADLER32_D = 0x00000001L
F_ADLER32_C = 0x00000002L
F_STDIN = 0x00000004L
F_STDOUT = 0x00000008L
F_NAME_DEFAULT = 0x00000010L
F_DOSISH = 0x00000020L
F_H_EXTRA_FIELD = 0x00000040L
F_H_GMTDIFF = 0x00000080L
F_CRC32_D = 0x00000100L
F_CRC32_C = 0x00000200L
F_MULTIPART = 0x00000400L
F_H_FILTER = 0x00000800L
F_H_CRC32 = 0x00001000L
F_H_PATH = 0x00002000L
F_MASK = 0x00003FFFL
BLOCK_SIZE = (128*1024)
MAX_BLOCK_SIZE = (64*1024*1024)

class Flags(IntFlag):
adler32_d = 0x00000001
adler32_c = 0x00000002
stdin = 0x00000004
stdout = 0x00000008
name_default = 0x00000010
dosish = 0x00000020
header_extra_field = 0x00000040
header_gmt_diff = 0x00000080
crc32_d = 0x00000100
crc32_c = 0x00000200
multipart = 0x00000400
header_filter = 0x00000800
header_crc32 = 0x00001000
header_path = 0x00002000
mask = 0x00003FFF

F_ADLER32_D = Flags.adler32_d
F_ADLER32_C = Flags.adler32_c
F_STDIN = Flags.stdin
F_STDOUT = Flags.stdout
F_NAME_DEFAULT = Flags.name_default
F_DOSISH = Flags.dosish
F_H_EXTRA_FIELD = Flags.header_extra_field
F_H_GMTDIFF = Flags.header_gmt_diff
F_CRC32_D = Flags.crc32_d
F_CRC32_C = Flags.crc32_c
F_MULTIPART = Flags.multipart
F_H_FILTER = Flags.header_filter
F_H_CRC32 = Flags.header_crc32
F_H_PATH = Flags.header_path
F_MASK = Flags.mask

def open(filename, mode):
return LzoFile(filename = filename, mode = mode)
Expand All @@ -53,7 +71,7 @@ def __init__(self, filename=None, mode=None,
The compresslevel and mtime attribute is not supported so far

The new class instance is based on fileobj, which can be a regular
file, a StringIO object, or any other object which simulates a file.
file, a BytesIO object, or any other object which simulates a file.
It defaults to None, in which case filename is opened to provide
a file object.

Expand All @@ -74,7 +92,7 @@ def __init__(self, filename=None, mode=None,
mode = 'rb'

if fileobj is None:
fileobj = __builtin__.open(filename, mode)
fileobj = builtins.open(filename, mode)
self.need_close = True
else:
self.need_close = False
Expand All @@ -93,7 +111,7 @@ def __init__(self, filename=None, mode=None,
self.mode = WRITE

else:
raise IOError, "Mode " + mode + " not supported"
raise IOError("Mode " + mode + " not supported")

self.fileobj = fileobj
self.offset = 0
Expand Down Expand Up @@ -123,11 +141,17 @@ def __init__(self, filename=None, mode=None,
self.mtime_low = 0
self.mtime_high = 0

self.name = filename
self.name = filename.encode("utf-8")

self._write_magic()
self._write_header()

def __enter__(self):
return self

def __exit__(self, *args, **kwargs):
self.close()

def _clear_buf(self):
self._buf = []
self._buf_len = 0
Expand Down Expand Up @@ -172,7 +196,7 @@ def _read_magic(self):
if magic == MAGIC:
return True
else:
raise IOError, 'Wrong lzo signature'
raise IOError('Wrong lzo signature')

def _read_header(self):
self.adler32 = ADLER32_INIT_VALUE
Expand All @@ -184,9 +208,9 @@ def _read_header(self):
if self.version > 0x0940:
self.ver_need_ext = self._read16_c()
if self.ver_need_ext > LZOP_VERSION:
raise IOError, 'Need liblzo version higher than %s' %(hex(self.ver_need_ext))
raise IOError('Need liblzo version higher than %s' %(hex(self.ver_need_ext)))
elif self.ver_need_ext < 0x0900:
raise IOError, '3'
raise IOError('3')

self.method = self._read8_c()
assert(self.method in [1,2,3])
Expand All @@ -197,7 +221,7 @@ def _read_header(self):
self.flags = self._read32_c()

if self.flags & F_H_CRC32:
raise error, 'CRC32 not implemented in minilzo'
raise error('CRC32 not implemented in minilzo')

if self.flags & F_H_FILTER:
self.ffilter = self._read32()
Expand Down Expand Up @@ -230,7 +254,7 @@ def _read_block(self):
return None

if dst_len > MAX_BLOCK_SIZE:
raise error, 'uncompressed larger than max block size'
raise error('uncompressed larger than max block size')

src_len = self._read32()

Expand Down Expand Up @@ -542,14 +566,14 @@ def main():
else:
de_name = filename + '.uncompressed'

with __builtin__.open(de_name, 'wb') as de:
with builtins.open(de_name, 'wb') as de:
de.write(f.read())

else:
with __builtin__.open(args.path, 'rb') as f:
with builtins.open(args.path, 'rb') as f:
with LzoFile(filename = args.path + ".lzo", mode = 'wb') as com:
com.write(f.read())


if __name__ == '__main__':
main()
main()
70 changes: 29 additions & 41 deletions lzomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,6 @@ compress_block(PyObject *dummy, PyObject *args)

out_len = in_len + in_len / 64 + 16 + 3;

result = PyBytes_FromStringAndSize(NULL, out_len);

if (result == NULL){
return PyErr_NoMemory();
}

if (method == M_LZO1X_1)
wrk_len = LZO1X_1_MEM_COMPRESS;
#ifdef USE_LIBLZO
Expand All @@ -78,7 +72,7 @@ compress_block(PyObject *dummy, PyObject *args)
assert(wrk_len <= WRK_LEN);

wrkmem = (lzo_voidp) PyMem_Malloc(wrk_len);
out = (lzo_bytep) PyString_AsString(result);
out = (lzo_bytep) PyMem_Malloc(out_len);

if (method == M_LZO1X_1){
err = lzo1x_1_compress(in, (lzo_uint) in_len, out, (lzo_uint*) &new_len, wrkmem);
Expand All @@ -96,12 +90,18 @@ compress_block(PyObject *dummy, PyObject *args)
#endif
else{
PyMem_Free(wrkmem);
Py_DECREF(result);
PyMem_Free(out);
PyErr_SetString(LzoError, "Compression method not supported");
return NULL;
}

result = PyBytes_FromStringAndSize(out, new_len);
if (result == NULL){
return PyErr_NoMemory();
}

PyMem_Free(wrkmem);
PyMem_Free(out);
if (err != LZO_E_OK || new_len > out_len)
{
/* this should NEVER happen */
Expand All @@ -110,13 +110,6 @@ compress_block(PyObject *dummy, PyObject *args)
return NULL;
}

if (new_len != out_len)
_PyString_Resize(&result, new_len);
/*
If the reallocation fails, the result is set to NULL, and memory exception is set
So should raise right exception to python environment without additional check
*/

return result;

}
Expand Down Expand Up @@ -229,39 +222,34 @@ static /* const */ char module_documentation[]=

;

static PyModuleDef moduleSpec = {
PyModuleDef_HEAD_INIT,
/*.m_name=*/"_lzo",
/*.m_doc=*/module_documentation,
/*.m_size=*/-1,
/*.m_methods=*/methods,
/*.m_reload=*/NULL,
/*.m_traverse=*/NULL,
/*.m_clear=*/NULL,
/*.m_free=*/NULL,
};

#ifdef _MSC_VER
_declspec(dllexport)
#endif
void init_lzo(void)
{
PyObject *m, *d, *v;
PyMODINIT_FUNC PyInit__lzo() {
if (lzo_init() != LZO_E_OK)
{
return;
return NULL;
}

m = Py_InitModule4("_lzo", methods, module_documentation,
NULL, PYTHON_API_VERSION);
d = PyModule_GetDict(m);

LzoError = PyErr_NewException("_lzo.error", NULL, NULL);
PyDict_SetItemString(d, "error", LzoError);

v = PyString_FromString("<iridiummx@gmail.com>");
PyDict_SetItemString(d, "__author__", v);
Py_DECREF(v);

v = PyInt_FromLong(LZO_VERSION);
PyDict_SetItemString(d, "LZO_VERSION", v);
Py_DECREF(v);
v = PyString_FromString(LZO_VERSION_STRING);
PyDict_SetItemString(d, "LZO_VERSION_STRING", v);
Py_DECREF(v);
v = PyString_FromString(LZO_VERSION_DATE);
PyDict_SetItemString(d, "LZO_VERSION_DATE", v);
Py_DECREF(v);
}
PyObject *m = PyModule_Create(&moduleSpec);
PyObject_SetAttrString(m, "__author__", PyUnicode_FromString("<iridiummx@gmail.com>"));
PyObject_SetAttrString(m, "LZO_VERSION", PyLong_FromLong(LZO_VERSION));
PyObject_SetAttrString(m, "LZO_VERSION_STRING", PyUnicode_FromString(LZO_VERSION_STRING));
PyObject_SetAttrString(m, "LZO_VERSION_DATE", PyUnicode_FromString(LZO_VERSION_DATE));
PyObject_SetAttrString(m, "error", (PyObject*) PyErr_NewException("_lzo.error", NULL, NULL));
return m;
}


/*
Expand Down