Skip to content

Commit

Permalink
First Release
Browse files Browse the repository at this point in the history
  • Loading branch information
naqvis committed Mar 23, 2020
0 parents commit cd25441
Show file tree
Hide file tree
Showing 12 changed files with 607 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*.cr]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/docs/
/lib/
/bin/
/.shards/
*.dwarf

# Libraries don't need dependency lock
# Dependencies will be locked in applications that use them
/shard.lock
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
language: crystal

# Uncomment the following if you'd like Travis to run specs and check code formatting
# script:
# - crystal spec
# - crystal tool format --check
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2020 Ali Naqvi

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.
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Crystal LZ4 Compression

Crystal bindings to the [LZ4](https://lz4.github.io/lz4/) compression library. Bindings provided in this shard cover the [frame format](https://github.com/lz4/lz4/blob/master/doc/lz4_Frame_format.md) as the frame format is recommended one to use and guarantees interoperability with other implementations and language bindings.


LZ4 is lossless compression algorithm, providing compression speed > 500 MB/s per core (>0.15 Bytes/cycle). It features an extremely fast decoder, with speed in multiple GB/s per core (~1 Byte/cycle).

## Installation

1. Add the dependency to your `shard.yml`:

```yaml
dependencies:
lz4:
github: naqvis/lz4.cr
```
2. Run `shards install`

## Usage

```crystal
require "lz4"
```

`LZ4` shard provides both `LZ4::Reader` and `LZ4::Writer` as well as `LZ4#decode` and `LZ4#encode` methods for quick usage.

## Example: decompress an lz4 file
#
```crystal
require "lz4"
string = File.open("file.xz") do |file|
LZ4::Reader.open(file) do |lz4|
lz4.gets_to_end
end
end
pp string
```

## Example: compress to lz4 compression format
#
```crystal
require "lz4"
File.write("file.txt", "abcd")
File.open("./file.txt", "r") do |input_file|
File.open("./file.xz", "w") do |output_file|
LZ4::Writer.open(output_file) do |lz4|
IO.copy(input_file, lz4)
end
end
end
```

## Development

TODO: Write development instructions here

## Contributing

1. Fork it (<https://github.com/naqvis/lz4.cr/fork>)
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request

## Contributors

- [Ali Naqvi](https://github.com/naqvis) - creator and maintainer
11 changes: 11 additions & 0 deletions shard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: lz4
version: 0.1.0

authors:
- Ali Naqvi <syed.alinaqvi@gmail.com>
description: |
Crystal bindings to the LZ4 compression library.
crystal: 0.33.0

license: MIT
5 changes: 5 additions & 0 deletions spec/lz4_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require "./spec_helper"

describe Lz4 do

end
2 changes: 2 additions & 0 deletions spec/spec_helper.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require "spec"
require "../src/lz4"
36 changes: 36 additions & 0 deletions src/lz4.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# LZ4 Crystal Wrapper
require "semantic_version"

module LZ4
VERSION = "0.1.0"

LZ4_VERSION = SemanticVersion.parse String.new(LibLZ4.version_string)
LZ4_VERSION_MINIMUM = SemanticVersion.parse("1.9.2")
raise "unsupported lz4 version #{LZ4_VERSION}, needs #{LZ4_VERSION_MINIMUM} or higher" unless LZ4_VERSION >= LZ4_VERSION_MINIMUM

class LZ4Error < Exception
end

def self.decode(compressed : Slice)
buf = IO::Memory.new(compressed)
uncompressed = Reader.open(buf) do |br|
br.gets_to_end
end
uncompressed.to_slice
end

def self.encode(content : String)
encode(content.to_slice)
end

def self.encode(content : Slice)
buf = IO::Memory.new
Writer.open(buf) do |br|
br.write content
end
buf.rewind
buf.to_slice
end
end

require "./**"
121 changes: 121 additions & 0 deletions src/lz4/lib.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
module LZ4
@[Link(ldflags: "`command -v pkg-config > /dev/null && pkg-config --libs liblz4 2> /dev/null|| printf %s '--llz4'`")]
lib LibLZ4
alias ErrorCodeT = LibC::SizeT
alias Uint32T = LibC::UInt
alias Uint16T = LibC::UShort
alias Uint8T = UInt8

VERSION_MAJOR = 1
VERSION_MINOR = 9
VERSION_RELEASE = 2
MEMORY_USAGE = 14
MAX_INPUT_SIZE = 2113929216

CLEVEL_MIN = 3
CLEVEL_DEFAULT = 9
CLEVEL_OPT_MIN = 10
CLEVEL_MAX = 12

DICTIONARY_LOGSIZE = 16
HASH_LOG = 15

VERSION = 100
HEADER_SIZE_MIN = 7
HEADER_SIZE_MAX = 19
BLOCK_HEADER_SIZE = 4
BLOCK_CHECKSUM_SIZE = 4
CONTENT_CHECKSUM_SIZE = 4
MIN_SIZE_TO_KNOW_HEADER_LENGTH = 5

fun version_number = LZ4_versionNumber : LibC::Int
fun version_string = LZ4_versionString : LibC::Char*

# makes it possible to supply advanced compression instructions to streaming interface.
# Structure must be first init to 0, using memset() or LZ4F_INIT_PREFERENCES,
# setting all parameters to default.
# All reserved fields must be set to zero.
struct PreferencesT
frame_info : FrameInfoT
compression_level : LibC::Int
auto_flush : LibC::UInt
favor_dec_speed : LibC::UInt
reserved : LibC::UInt[3]
end

struct FrameInfoT
block_size_id : BlockSizeIdT
block_mode : BlockModeT
content_checksum_flag : ContentChecksumT
frame_type : FrameTypeT
content_size : LibC::ULongLong
dict_id : LibC::UInt
block_checksum_flag : BlockChecksumT
end

enum BlockSizeIdT
Default = 0
Max64Kb = 4
Max256Kb = 5
Max1Mb = 6
Max4Mb = 7
end
enum BlockModeT
BlockLinked = 0
BlockIndependent = 1
end
enum ContentChecksumT
NoContentChecksum = 0
ContentChecksumEnabled = 1
end
enum FrameTypeT
Frame = 0
SkippableFrame = 1
end
enum BlockChecksumT
NoBlockChecksum = 0
BlockChecksumEnabled = 1
end

# Error management
fun is_error = LZ4F_isError(code : ErrorCodeT) : LibC::UInt
fun get_error_name = LZ4F_getErrorName(code : ErrorCodeT) : LibC::Char*

# Simple compression function
fun compress_frame_bound = LZ4F_compressFrameBound(src_size : LibC::SizeT, preferences_ptr : PreferencesT*) : LibC::SizeT
fun compress_frame = LZ4F_compressFrame(dst_buffer : Void*, dst_capacity : LibC::SizeT, src_buffer : Void*, src_size : LibC::SizeT, preferences_ptr : PreferencesT*) : LibC::SizeT

# Compression Resource management
type Cctx = Void*
fun create_compression_context = LZ4F_createCompressionContext(cctx_ptr : Cctx*, version : LibC::UInt) : ErrorCodeT
fun free_compression_context = LZ4F_freeCompressionContext(cctx : Cctx) : ErrorCodeT

# Compression
struct CompressOptionsT
stable_src : LibC::UInt
reserved : LibC::UInt[3]
end

fun compress_begin = LZ4F_compressBegin(cctx : Cctx, dst_buffer : Void*, dst_capacity : LibC::SizeT, prefs_ptr : PreferencesT*) : LibC::SizeT
fun compress_bound = LZ4F_compressBound(src_size : LibC::SizeT, prefs_ptr : PreferencesT*) : LibC::SizeT
fun compress_update = LZ4F_compressUpdate(cctx : Cctx, dst_buffer : Void*, dst_capacity : LibC::SizeT, src_buffer : Void*, src_size : LibC::SizeT, c_opt_ptr : CompressOptionsT*) : LibC::SizeT
fun flush = LZ4F_flush(cctx : Cctx, dst_buffer : Void*, dst_capacity : LibC::SizeT, c_opt_ptr : CompressOptionsT*) : LibC::SizeT
fun compress_end = LZ4F_compressEnd(cctx : Cctx, dst_buffer : Void*, dst_capacity : LibC::SizeT, c_opt_ptr : CompressOptionsT*) : LibC::SizeT

# Decompression Resource Management
type Dctx = Void*
fun create_decompression_context = LZ4F_createDecompressionContext(dctx_ptr : Dctx*, version : LibC::UInt) : ErrorCodeT
fun free_decompression_context = LZ4F_freeDecompressionContext(dctx : Dctx) : ErrorCodeT

# Streaming Decompression Function
struct DecompressOptionsT
stable_dst : LibC::UInt
reserved : LibC::UInt[3]
end

fun header_size = LZ4F_headerSize(src : Void*, src_size : LibC::SizeT) : LibC::SizeT
fun get_frame_info = LZ4F_getFrameInfo(dctx : Dctx, frame_info_ptr : FrameInfoT*, src_buffer : Void*, src_size_ptr : LibC::SizeT*) : LibC::SizeT
fun decompress = LZ4F_decompress(dctx : Dctx, dst_buffer : Void*, dst_size_ptr : LibC::SizeT*, src_buffer : Void*, src_size_ptr : LibC::SizeT*, d_opt_ptr : DecompressOptionsT*) : LibC::SizeT
fun reset_decompression_context = LZ4F_resetDecompressionContext(dctx : Dctx)
end
end
Loading

0 comments on commit cd25441

Please sign in to comment.