Skip to content

Instantly share code, notes, and snippets.

@dansouza
Created September 20, 2012 17:14
Show Gist options
  • Save dansouza/3757136 to your computer and use it in GitHub Desktop.
Save dansouza/3757136 to your computer and use it in GitHub Desktop.
LuaJIT FFI LZ4
#!/usr/bin/luajit
local M = {}
local ffi = require "ffi"
ffi.cdef[[
/*
LZ4_compress() :
isize : is the input size. Max supported value is ~1.9GB
return : the number of bytes written in buffer dest
or 0 if the compression fails (if LZ4_COMPRESSMIN is set)
note : destination buffer must be already allocated.
destination buffer must be sized to handle worst cases situations (input data not compressible)
worst case size evaluation is provided by function LZ4_compressBound()
*/
int LZ4_compress (const char* source, char* dest, int isize);
/*
LZ4_uncompress() :
osize : is the output size, therefore the original size
return : the number of bytes read in the source buffer
If the source stream is malformed, the function will stop decoding and return a negative result, indicating the byte position of the faulty instruction
This function never writes beyond dest + osize, and is therefore protected against malicious data packets
note : destination buffer must be already allocated
*/
int LZ4_uncompress (const char* source, char* dest, int osize);
/*
LZ4_compressBound() :
Provides the maximum size that LZ4 may output in a "worst case" scenario (input data not compressible)
primarily useful for memory allocation of output buffer.
isize : is the input size. Max supported value is ~1.9GB
return : maximum output size in a "worst case" scenario
note : this function is limited by "int" range (2^31-1)
*/
int LZ4_compressBound(int isize);
/*
LZ4_uncompress_unknownOutputSize() :
isize : is the input size, therefore the compressed size
maxOutputSize : is the size of the destination buffer (which must be already allocated)
return : the number of bytes decoded in the destination buffer (necessarily <= maxOutputSize)
If the source stream is malformed, the function will stop decoding and return a negative result, indicating the byte position of the faulty instruction
This function never writes beyond dest + maxOutputSize, and is therefore protected against malicious data packets
note : Destination buffer must be already allocated.
This version is slightly slower than LZ4_uncompress()
*/
int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
/*
LZ4_compressCtx() :
This function explicitly handles the CTX memory structure.
It avoids allocating/deallocating memory between each call, improving performance when malloc is heavily invoked.
This function is only useful when memory is allocated into the heap (HASH_LOG value beyond STACK_LIMIT)
Performance difference will be noticeable only when repetitively calling the compression function over many small segments.
Note : by default, memory is allocated into the stack, therefore "malloc" is not invoked.
*/
int LZ4_compressCtx(void** ctx, const char* source, char* dest, int isize);
/*
LZ4_compress64kCtx() :
Same as LZ4_compressCtx(), but specific to small inputs (<64KB).
isize *Must* be <64KB, otherwise the output will be corrupted.
On first call : provide a *ctx=NULL; It will be automatically allocated.
On next calls : reuse the same ctx pointer.
Use different pointers for different threads when doing multi-threading.
*/
int LZ4_compress64kCtx(void** ctx, const char* source, char* dest, int isize);
]]
local lz4 = ffi.load("./lz4.so")
function M.compress(data)
local n = lz4.LZ4_compressBound(#data)
local buf = ffi.new("uint8_t[?]", n)
local res = lz4.LZ4_compress(data, buf, #data)
if (res == 0) then
return nil
else
return ffi.string(buf, res)
end
end
function M.uncompress(source, orig_size)
local dest = ffi.new("uint8_t[?]", orig_size)
local res = lz4.LZ4_uncompress_unknownOutputSize(source, dest, #source, orig_size)
if (res > 0) then
return ffi.string(dest, res)
else
return nil
end
end
return M
@agladysh
Copy link

Please convert this to a proper GitHub repo and add license so the code can be reused by others. Thanks!

@CheyiLin
Copy link

Hi I created a GitHub repo https://github.com/CheyiLin/ljlz4 for this.
Any feedback is welcome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment