├── .gitignore
├── .gitmodules
├── .npmignore
├── History.md
├── LICENSE
├── README.md
├── TODO.md
├── benchmark
└── bench.js
├── bin
└── lz4c
├── binding.gyp
├── bower.json
├── build.sh
├── build
├── lz4.js
└── lz4.min.js
├── data
├── lorem_1mb.txt
├── sphere.dae
├── sphere.lz4.dat
├── test
├── test.lz4
├── testHC.lz4
├── test_1.txt
├── test_medium
├── test_medium.lz4
└── test_smallchunk.lz4
├── doc
└── format.txt
├── examples
├── compress.html
├── cu.html
├── file_compress.js
├── file_compressBlock.js
├── file_compressHC.js
├── file_compressHCSync.js
├── file_compressJS.js
├── file_compressSync.js
├── file_uncompress.js
├── file_uncompressBlock.js
├── file_uncompressJS.js
├── file_uncompressSync.js
└── uncompress.html
├── karma.conf.js
├── lib
├── binding.js
├── binding
│ ├── lz4_binding.cc
│ └── xxhash_binding.cc
├── decoder.js
├── decoder_stream.js
├── encoder.js
├── encoder_stream.js
├── lz4.js
├── lz4l.js
├── static.js
├── utils-js.js
└── utils.js
├── package.json
└── test
├── block-test.js
├── browser
├── block.js
├── checksum.js
├── decoder.js
├── encoder.js
└── helpers
│ ├── download_data_file.js
│ └── spec_helper.js
├── checksum-test.js
├── decode-test.js
├── encode-test.js
└── jsencode_decode-test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | node_modules/
3 | tmp/
4 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "deps/lz4"]
2 | path = deps/lz4
3 | url = https://github.com/Cyan4973/lz4.git
4 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .gitignore
2 | node_modules/
3 | data/
4 |
--------------------------------------------------------------------------------
/History.md:
--------------------------------------------------------------------------------
1 | 0.5.3 / 2016-09-01
2 | ==================
3 |
4 | * Issue #44: Fix compressing a zero-sized stream. Thanks @ChALkeR.
5 |
6 | 0.5.2 / 2016-03-21
7 | ==================
8 |
9 | * Issue #36: Deprecated declarations. Thanks @ee99ee.
10 | * Updated LZ4 C code base with r131.
11 |
12 | 0.5.1 / 2015-12-10
13 | ==================
14 |
15 | * Issue #37: reverted commit breaking encodeBlock. Thanks @jamievicary.
16 |
17 | 0.5.0 / 2015-09-10
18 | ==================
19 |
20 | * Merged pull request #32 (thanks go to mog422)
21 | * Updated encoding tests to not depend on pre-encoded data
22 |
23 | 0.4.1 / 2015-08-14
24 | ==================
25 |
26 | * Issue #31: LZ4 Javascript compress function corrupts data
27 |
28 | 0.4.0 / 2015-04-08
29 | ==================
30 |
31 | * Support for node 0.12 and iojs 1.6. Thanks to EricMCornelius (github.com/EricMCornelius) for his merge request.
32 |
33 | 0.3.15 / 2015-03-07
34 | ===================
35 |
36 | * Fixed build
37 |
38 | 0.3.14 / 2014-11-03
39 | ===================
40 |
41 | * Issue #22: pos variable is not in read_DataBlockChecksum
42 |
43 | 0.3.13 / 2014-09-11
44 | ===================
45 |
46 | * Issue #19: fixed regression in Node wrt invalid checksums
47 | (nodejs and browserify Buffer.readInt32LE() are incompatible)
48 |
49 | 0.3.12 / 2014-09-03
50 | ===================
51 |
52 | * Issue #7: removed checks in writeInt32LE()
53 |
54 | 0.3.11 / 2014-07-09
55 | ===================
56 |
57 | * Updated LZ4 source to r119
58 |
59 | 0.3.10 / 2014-07-09
60 | ===================
61 |
62 | * Removed garbage in build/lz4.min.js by updating minify to latest version
63 |
64 | 0.3.9 / 2014-07-06
65 | ==================
66 |
67 | * Fixed checksum errors in the decoder (browser implementation) (issue #14)
68 | * Added start and end indexes to decodeBlock() and encodeBlock() (issue #15)
69 |
70 | 0.3.8 / 2014-05-21
71 | ==================
72 |
73 | * Fixed issue where the browser implementation of Buffer checks sign in writeUInt32LE()
74 |
75 | 0.3.7 / 2014-05-20
76 | ==================
77 |
78 | * Fixed assert() when writing uncompressible data
79 |
80 | 0.3.6 / 2014-04-11
81 | ==================
82 |
83 | * Added useJS option to encoder and decoder streams
84 |
85 | 0.3.5 / 2014-04-11
86 | ==================
87 |
88 | * Fixed stream encoder typo
89 |
90 | 0.3.4 / 2014-04-07
91 | ==================
92 |
93 | * Updated lz4 source to r116
94 | * Fixed stream encoder on large inputs
95 |
96 | 0.3.3 / 2014-03-28
97 | ==================
98 |
99 | * Updated build/lz4.js and build/lz4.min.js
100 |
101 | 0.3.2 / 2014-03-27
102 | ==================
103 |
104 | * Fixed Javascript compressBlock() not writing last batch of literals under some circumstances
105 |
106 | 0.3.1 / 2014-03-18
107 | ==================
108 |
109 | * Improved Javascript encoder speed
110 |
111 | 0.3.0 / 2014-03-11
112 | ==================
113 |
114 | * First release of the pure Javascript encoder
115 |
116 | 0.2.4 / 2014-03-05
117 | ==================
118 |
119 | * Updated lz4 source to r113
120 | * Split xxHash and LZ4 bindings
121 | * Added browser support via ./build/lz4.js and ./build/lz4.min.js
122 | * Exposed block level compression/decompression functions
123 |
124 | 0.2.3 / 2013-12-15
125 | ==================
126 |
127 | * Fixed handling of uncompressed data
128 | * Sync and async encoders share the same code
129 |
130 | 0.2.2 / 2013-10-04
131 | ==================
132 |
133 | * Sync and async decoders share the same code
134 | * Async decoder emits an error on missing data
135 |
136 | 0.2.1 / 2013-10-03
137 | ==================
138 |
139 | * Fixed encoder reversed logic
140 |
141 | 0.2.0 / 2013-10-01
142 | ==================
143 |
144 | * Updated lz4 source to r104
145 | * Support for LZ4Stream format v1.4, legacy format is deprecated, use v0.1 for its support
146 |
147 | 0.1.2 / 2013-09-09
148 | ==================
149 |
150 | * Updated lz4 source to r102
151 |
152 | 0.1.1 / 2013-06-09
153 | ==================
154 |
155 | * Updated lz4 source to r96
156 | * Fixed an issue with small chunkSize parameters
157 |
158 | 0.1.0 / 2013-03-13
159 | ==================
160 |
161 | * Updated streams to use streams2
162 |
163 | 0.0.5 / 2013-03-12
164 | ==================
165 |
166 | * Updated lz4 source to r90
167 | * Fixed node binding compilation errors for node v0.10
168 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012 Pierre Curto
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LZ4
2 |
3 | [LZ4](http://fastcompression.blogspot.fr/) is a very fast compression and decompression algorithm. This nodejs module provides a Javascript implementation of the decoder as well as native bindings to the LZ4 functions. Nodejs Streams are also supported for compression and decompression.
4 |
5 | NB.
6 | Version 0.2 does not support the legacy format, only the one as of "LZ4 Streaming Format 1.4". Use version 0.1 if required.
7 |
8 | ## Build
9 |
10 | With NodeJS:
11 |
12 | ```shell
13 | git clone https://github.com/pierrec/node-lz4.git
14 | cd node-lz4
15 | git submodule update --init --recursive
16 | npm install
17 | ```
18 |
19 | ## Install
20 |
21 | With NodeJS:
22 |
23 | ```shell
24 | npm install lz4
25 | ```
26 |
27 | Within the browser, using `build/lz4.js`:
28 |
29 | ```html
30 |
31 |
58 | ```
59 |
60 |
61 | From github cloning, after having made sure that node and node-gyp are properly installed:
62 |
63 | ```shell
64 | npm i
65 | node-gyp rebuild
66 | ```
67 |
68 | See below for more LZ4 functions.
69 |
70 |
71 | ## Usage
72 |
73 | ### Encoding
74 |
75 | There are 2 ways to encode:
76 |
77 | * __asynchronous__ using nodejs Streams - slowest but can handle very large data sets (no memory limitations).
78 | * __synchronous__ by feeding the whole set of data - faster but is limited by the amount of memory
79 |
80 |
81 | #### Asynchronous encoding
82 |
83 | First, create an LZ4 encoding NodeJS stream with `LZ4#createEncoderStream(options)`.
84 |
85 | * `options` (_Object_): LZ4 stream options (optional)
86 | * `options.blockMaxSize` (_Number_): chunk size to use (default=4Mb)
87 | * `options.highCompression` (_Boolean_): use high compression (default=false)
88 | * `options.blockIndependence` (_Boolean_): (default=true)
89 | * `options.blockChecksum` (_Boolean_): add compressed blocks checksum (default=false)
90 | * `options.streamSize` (_Boolean_): add full LZ4 stream size (default=false)
91 | * `options.streamChecksum` (_Boolean_): add full LZ4 stream checksum (default=true)
92 | * `options.dict` (_Boolean_): use dictionary (default=false)
93 | * `options.dictId` (_Integer_): dictionary id (default=0)
94 |
95 |
96 | The stream can then encode any data piped to it. It will emit a `data` event on each encoded chunk, which can be saved into an output stream.
97 |
98 | The following example shows how to encode a file `test` into `test.lz4`.
99 |
100 |
101 | ```javascript
102 | var fs = require('fs')
103 | var lz4 = require('lz4')
104 |
105 | var encoder = lz4.createEncoderStream()
106 |
107 | var input = fs.createReadStream('test')
108 | var output = fs.createWriteStream('test.lz4')
109 |
110 | input.pipe(encoder).pipe(output)
111 | ```
112 |
113 | #### Synchronous encoding
114 |
115 | Read the data into memory and feed it to `LZ4#encode(input[, options])` to decode an LZ4 stream.
116 |
117 | * `input` (_Buffer_): data to encode
118 | * `options` (_Object_): LZ4 stream options (optional)
119 | * `options.blockMaxSize` (_Number_): chunk size to use (default=4Mb)
120 | * `options.highCompression` (_Boolean_): use high compression (default=false)
121 | * `options.blockIndependence` (_Boolean_): (default=true)
122 | * `options.blockChecksum` (_Boolean_): add compressed blocks checksum (default=false)
123 | * `options.streamSize` (_Boolean_): add full LZ4 stream size (default=false)
124 | * `options.streamChecksum` (_Boolean_): add full LZ4 stream checksum (default=true)
125 | * `options.dict` (_Boolean_): use dictionary (default=false)
126 | * `options.dictId` (_Integer_): dictionary id (default=0)
127 |
128 |
129 | ```javascript
130 | var fs = require('fs')
131 | var lz4 = require('lz4')
132 |
133 | var input = fs.readFileSync('test')
134 | var output = lz4.encode(input)
135 |
136 | fs.writeFileSync('test.lz4', output)
137 | ```
138 |
139 |
140 | ### Decoding
141 |
142 | There are 2 ways to decode:
143 |
144 | * __asynchronous__ using nodejs Streams - slowest but can handle very large data sets (no memory limitations)
145 | * __synchronous__ by feeding the whole LZ4 data - faster but is limited by the amount of memory
146 |
147 |
148 | #### Asynchronous decoding
149 |
150 | First, create an LZ4 decoding NodeJS stream with `LZ4#createDecoderStream()`.
151 |
152 |
153 | The stream can then decode any data piped to it. It will emit a `data` event on each decoded sequence, which can be saved into an output stream.
154 |
155 | The following example shows how to decode an LZ4 compressed file `test.lz4` into `test`.
156 |
157 |
158 | ```javascript
159 | var fs = require('fs')
160 | var lz4 = require('lz4')
161 |
162 | var decoder = lz4.createDecoderStream()
163 |
164 | var input = fs.createReadStream('test.lz4')
165 | var output = fs.createWriteStream('test')
166 |
167 | input.pipe(decoder).pipe(output)
168 | ```
169 |
170 | #### Synchronous decoding
171 |
172 | Read the data into memory and feed it to `LZ4#decode(input)` to produce an LZ4 stream.
173 |
174 | * `input` (_Buffer_): data to decode
175 |
176 |
177 | ```javascript
178 | var fs = require('fs')
179 | var lz4 = require('lz4')
180 |
181 | var input = fs.readFileSync('test.lz4')
182 | var output = lz4.decode(input)
183 |
184 | fs.writeFileSync('test', output)
185 | ```
186 |
187 | ## Block level encoding/decoding
188 |
189 | In some cases, it is useful to be able to manipulate an LZ4 block instead of an LZ4 stream. The functions to decode and encode are therefore exposed as:
190 |
191 | * `LZ4#decodeBlock(input, output[, startIdx, endIdx])` (_Number_) >=0: uncompressed size, <0: error at offset
192 | * `input` (_Buffer_): data block to decode
193 | * `output` (_Buffer_): decoded data block
194 | * `startIdx` (_Number_): input buffer start index (optional, default=0)
195 | * `endIdx` (_Number_): input buffer end index (optional, default=startIdx + input.length)
196 | * `LZ4#encodeBound(inputSize)` (_Number_): maximum size for a compressed block
197 | * `inputSize` (_Number_) size of the input, 0 if too large
198 | This is required to size the buffer for a block encoded data
199 | * `LZ4#encodeBlock(input, output[, startIdx, endIdx])` (_Number_) >0: compressed size, =0: not compressible
200 | * `input` (_Buffer_): data block to encode
201 | * `output` (_Buffer_): encoded data block
202 | * `startIdx` (_Number_): output buffer start index (optional, default=0)
203 | * `endIdx` (_Number_): output buffer end index (optional, default=startIdx + output.length)
204 | * `LZ4#encodeBlockHC(input, output[, compressionLevel])` (_Number_) >0: compressed size, =0: not compressible
205 | * `input` (_Buffer_): data block to encode with high compression
206 | * `output` (_Buffer_): encoded data block
207 | * `compressionLevel` (_Number_): compression level between 3 and 12 (optional, default=9)
208 |
209 |
210 | Blocks do not have any magic number and are provided as is. It is useful to store somewhere the size of the original input for decoding.
211 | LZ4#encodeBlockHC() is not available as pure Javascript.
212 |
213 |
214 | ## How it works
215 |
216 | * [LZ4 stream format](http://fastcompression.blogspot.fr/2011/05/lz4-explained.html)
217 |
218 | ## Restrictions / Issues
219 |
220 | * `blockIndependence` property only supported for `true`
221 |
222 |
223 | ## License
224 |
225 | MIT
226 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | * LZ4 stream dictionary
2 | * NodeJS streams updates
3 | * dependent blocks compression
--------------------------------------------------------------------------------
/benchmark/bench.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var path = require('path')
3 | var Benchmark = require('benchmark')
4 | var lz4 = require('..')
5 | var lz4js = require('../lib/binding')
6 |
7 | var inputFileName = path.normalize( process.argv[2] || __dirname + '/../data/lorem_1mb.txt' )
8 | console.log('Input file:', inputFileName)
9 |
10 | var input = fs.readFileSync(inputFileName)
11 | var outputMaxSize = lz4.encodeBound(input.length)
12 | var output = Buffer.alloc(outputMaxSize)
13 |
14 | var decoded = Buffer.alloc(input.length)
15 | var encoded = Buffer.alloc(outputMaxSize)
16 | var n = lz4.encodeBlock(input, encoded)
17 | encoded = encoded.slice(0, n)
18 |
19 | console.log('Input size:', input.length)
20 | console.log('Output size:', encoded.length)
21 |
22 | var suite = new Benchmark.Suite
23 | suite
24 | .add('lz4.encodeBlock native', function() {
25 | lz4.encodeBlock(input, output)
26 | })
27 | .add('lz4.decodeBlock native', function() {
28 | lz4.decodeBlock(encoded, decoded)
29 | })
30 | .add('lz4.encodeBlock JS', function() {
31 | lz4js.compress(input, output)
32 | })
33 | .add('lz4.decodeBlock JS', function() {
34 | lz4js.uncompress(encoded, decoded)
35 | })
36 | // add listeners
37 | .on('cycle', function(event) {
38 | console.log( String(event.target) )
39 | })
40 | .run()
--------------------------------------------------------------------------------
/bin/lz4c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pierrec/node-lz4/943e768691a9fb29e2d9a88f9942463765a45468/bin/lz4c
--------------------------------------------------------------------------------
/binding.gyp:
--------------------------------------------------------------------------------
1 | {
2 | 'targets': [
3 | {
4 | 'target_name': 'xxhash',
5 | 'cflags!': [ '-fno-exceptions' ],
6 | 'cflags_cc!': [ '-fno-exceptions' ],
7 | 'xcode_settings': { 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
8 | 'CLANG_CXX_LIBRARY': 'libc++',
9 | 'MACOSX_DEPLOYMENT_TARGET': '10.7',
10 | },
11 | 'msvs_settings': {
12 | 'VCCLCompilerTool': { 'ExceptionHandling': 1 },
13 | },
14 | 'sources': [
15 | 'lib/binding/xxhash_binding.cc',
16 | 'deps/lz4/lib/xxhash.h',
17 | 'deps/lz4/lib/xxhash.c',
18 | ],
19 | 'include_dirs': [
20 | '"
7 | ],
8 | "description": "LZ4 streaming compression and decompression",
9 | "main": "build/lz4.js",
10 | "moduleType": [
11 | "node"
12 | ],
13 | "keywords": [
14 | "lz4",
15 | "compression",
16 | "decompression",
17 | "stream"
18 | ],
19 | "license": "MIT",
20 | "ignore": [
21 | "**/.*",
22 | "node_modules",
23 | "bower_components",
24 | "test",
25 | "tests"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | browserify -r ./lib/utils-js.js:./utils -r buffer -r xxhashjs -r ./lib/lz4l.js:lz4 -o build/lz4.js lib/lz4l.js && \
4 | minify build/lz4.js > build/lz4.min.js
5 |
6 |
--------------------------------------------------------------------------------
/data/sphere.dae:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | alorino
6 | Maya 7.0 | ColladaMaya v2.01 Jun 9 2006 at 16:08:19 | FCollada v1.11
7 | Collada Maya Export Options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
8 | curveConstrainSampling=0;exportCameraAsLookat=0;
9 | exportLights=1;exportCameras=1;exportJointsAndSkin=1;
10 | exportAnimations=1;exportTriangles=0;exportInvisibleNodes=0;
11 | exportNormals=1;exportTexCoords=1;exportVertexColors=1;exportTangents=0;
12 | exportTexTangents=0;exportConstraints=0;exportPhysics=0;exportXRefs=1;
13 | dereferenceXRefs=0;cameraXFov=0;cameraYFov=1
14 |
15 | Copyright 2006 Sony Computer Entertainment Inc.
16 | Licensed under the SCEA Shared Source License, Version 1.0 (the
17 | "License"); you may not use this file except in compliance with the
18 | License. You may obtain a copy of the License at:
19 | http://research.scea.com/scea_shared_source_license.html
20 | Unless required by applicable law or agreed to in writing, software
21 | distributed under the License is distributed on an "AS IS" BASIS,
22 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 | See the License for the specific language governing permissions and
24 | limitations under the License.
25 |
26 |
27 | 2006-06-23T18:26:06Z
28 | 2006-06-23T18:26:06Z
29 |
30 | Y_UP
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | 0 0 0 1
44 |
45 |
46 | 0 0 0 1
47 |
48 |
49 | 0.5 0.5 0.5 1
50 |
51 |
52 | 1 1 1 1
53 |
54 |
55 | 1
56 |
57 |
58 | 0 0 0 1
59 |
60 |
61 | 1
62 |
63 |
64 | 0
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | 0.148778 -0.987688 -0.048341 0.126558 -0.987688 -0.09195 0.09195 -0.987688 -0.126558 0.048341 -0.987688 -0.148778 0 -0.987688 -0.156435 -0.048341 -0.987688 -0.148778 -0.09195 -0.987688 -0.126558 -0.126558 -0.987688 -0.09195 -0.148778 -0.987688 -0.048341 -0.156435 -0.987688 0 -0.148778 -0.987688 0.048341 -0.126558 -0.987688 0.09195 -0.09195 -0.987688 0.126558 -0.048341 -0.987688 0.148778 0 -0.987688 0.156434 0.048341 -0.987688 0.148778 0.09195 -0.987688 0.126558 0.126558 -0.987688 0.09195 0.148778 -0.987688 0.048341 0.156434 -0.987688 0 0.293893 -0.951057 -0.095492 0.25 -0.951057 -0.181636 0.181636 -0.951057 -0.25 0.095492 -0.951057 -0.293893 0 -0.951057 -0.309017 -0.095492 -0.951057 -0.293893 -0.181636 -0.951057 -0.25 -0.25 -0.951057 -0.181636 -0.293893 -0.951057 -0.095492 -0.309017 -0.951057 0 -0.293893 -0.951057 0.095492 -0.25 -0.951057 0.181636 -0.181636 -0.951057 0.25 -0.095492 -0.951057 0.293893 0 -0.951057 0.309017 0.095492 -0.951057 0.293893 0.181636 -0.951057 0.25 0.25 -0.951057 0.181636 0.293893 -0.951057 0.095492 0.309017 -0.951057 0 0.431771 -0.891007 -0.140291 0.367286 -0.891007 -0.266849 0.266849 -0.891007 -0.367286 0.140291 -0.891007 -0.431771 0 -0.891007 -0.453991 -0.140291 -0.891007 -0.431771 -0.266849 -0.891007 -0.367286 -0.367286 -0.891007 -0.266849 -0.431771 -0.891007 -0.140291 -0.453991 -0.891007 0 -0.431771 -0.891007 0.140291 -0.367286 -0.891007 0.266849 -0.266849 -0.891007 0.367286 -0.140291 -0.891007 0.431771 0 -0.891007 0.453991 0.140291 -0.891007 0.431771 0.266849 -0.891007 0.367286 0.367286 -0.891007 0.266849 0.431771 -0.891007 0.140291 0.453991 -0.891007 0 0.559017 -0.809017 -0.181636 0.475528 -0.809017 -0.345492 0.345492 -0.809017 -0.475528 0.181636 -0.809017 -0.559017 0 -0.809017 -0.587785 -0.181636 -0.809017 -0.559017 -0.345492 -0.809017 -0.475528 -0.475528 -0.809017 -0.345492 -0.559017 -0.809017 -0.181636 -0.587785 -0.809017 0 -0.559017 -0.809017 0.181636 -0.475528 -0.809017 0.345492 -0.345492 -0.809017 0.475528 -0.181636 -0.809017 0.559017 0 -0.809017 0.587785 0.181636 -0.809017 0.559017 0.345492 -0.809017 0.475528 0.475528 -0.809017 0.345492 0.559017 -0.809017 0.181636 0.587785 -0.809017 0 0.672499 -0.707107 -0.218508 0.572062 -0.707107 -0.415627 0.415627 -0.707107 -0.572062 0.218508 -0.707107 -0.672499 0 -0.707107 -0.707107 -0.218508 -0.707107 -0.672499 -0.415627 -0.707107 -0.572062 -0.572062 -0.707107 -0.415627 -0.672499 -0.707107 -0.218508 -0.707107 -0.707107 0 -0.672499 -0.707107 0.218508 -0.572062 -0.707107 0.415627 -0.415627 -0.707107 0.572061 -0.218508 -0.707107 0.672499 0 -0.707107 0.707107 0.218508 -0.707107 0.672499 0.415627 -0.707107 0.572061 0.572061 -0.707107 0.415627 0.672499 -0.707107 0.218508 0.707107 -0.707107 0 0.769421 -0.587785 -0.25 0.654509 -0.587785 -0.475529 0.475528 -0.587785 -0.654509 0.25 -0.587785 -0.769421 0 -0.587785 -0.809017 -0.25 -0.587785 -0.769421 -0.475528 -0.587785 -0.654509 -0.654509 -0.587785 -0.475528 -0.769421 -0.587785 -0.25 -0.809017 -0.587785 0 -0.769421 -0.587785 0.25 -0.654509 -0.587785 0.475528 -0.475528 -0.587785 0.654509 -0.25 -0.587785 0.769421 0 -0.587785 0.809017 0.25 -0.587785 0.769421 0.475528 -0.587785 0.654509 0.654509 -0.587785 0.475528 0.769421 -0.587785 0.25 0.809017 -0.587785 0 0.847398 -0.453991 -0.275336 0.72084 -0.453991 -0.523721 0.523721 -0.453991 -0.72084 0.275336 -0.453991 -0.847398 0 -0.453991 -0.891007 -0.275336 -0.453991 -0.847398 -0.523721 -0.453991 -0.72084 -0.72084 -0.453991 -0.523721 -0.847398 -0.453991 -0.275336 -0.891007 -0.453991 0 -0.847398 -0.453991 0.275336 -0.72084 -0.453991 0.523721 -0.523721 -0.453991 0.72084 -0.275336 -0.453991 0.847398 0 -0.453991 0.891007 0.275336 -0.453991 0.847398 0.523721 -0.453991 0.72084 0.72084 -0.453991 0.523721 0.847398 -0.453991 0.275336 0.891007 -0.453991 0 0.904509 -0.309017 -0.293893 0.769421 -0.309017 -0.559017 0.559017 -0.309017 -0.769421 0.293893 -0.309017 -0.904509 0 -0.309017 -0.951057 -0.293893 -0.309017 -0.904509 -0.559017 -0.309017 -0.769421 -0.769421 -0.309017 -0.559017 -0.904509 -0.309017 -0.293893 -0.951057 -0.309017 0 -0.904509 -0.309017 0.293893 -0.769421 -0.309017 0.559017 -0.559017 -0.309017 0.769421 -0.293893 -0.309017 0.904509 0 -0.309017 0.951057 0.293893 -0.309017 0.904509 0.559017 -0.309017 0.769421 0.769421 -0.309017 0.559017 0.904509 -0.309017 0.293893 0.951057 -0.309017 0 0.939348 -0.156434 -0.305213 0.799057 -0.156434 -0.580549 0.580549 -0.156434 -0.799057 0.305213 -0.156434 -0.939348 0 -0.156434 -0.987689 -0.305213 -0.156434 -0.939348 -0.580549 -0.156434 -0.799057 -0.799057 -0.156434 -0.580549 -0.939348 -0.156434 -0.305213 -0.987689 -0.156434 0 -0.939348 -0.156434 0.305213 -0.799057 -0.156434 0.580549 -0.580549 -0.156434 0.799057 -0.305213 -0.156434 0.939348 0 -0.156434 0.987688 0.305213 -0.156434 0.939348 0.580549 -0.156434 0.799057 0.799057 -0.156434 0.580549 0.939348 -0.156434 0.305212 0.987688 -0.156434 0 0.951057 0 -0.309017 0.809017 0 -0.587786 0.587785 0 -0.809017 0.309017 0 -0.951057 0 0 -1 -0.309017 0 -0.951057 -0.587785 0 -0.809017 -0.809017 0 -0.587785 -0.951057 0 -0.309017 -1 0 0 -0.951057 0 0.309017 -0.809017 0 0.587785 -0.587785 0 0.809017 -0.309017 0 0.951057 0 0 1 0.309017 0 0.951057 0.587785 0 0.809017 0.809017 0 0.587785 0.951057 0 0.309017 1 0 0 0.939348 0.156434 -0.305213 0.799057 0.156434 -0.580549 0.580549 0.156434 -0.799057 0.305213 0.156434 -0.939348 0 0.156434 -0.987689 -0.305213 0.156434 -0.939348 -0.580549 0.156434 -0.799057 -0.799057 0.156434 -0.580549 -0.939348 0.156434 -0.305213 -0.987689 0.156434 0 -0.939348 0.156434 0.305213 -0.799057 0.156434 0.580549 -0.580549 0.156434 0.799057 -0.305213 0.156434 0.939348 0 0.156434 0.987688 0.305213 0.156434 0.939348 0.580549 0.156434 0.799057 0.799057 0.156434 0.580549 0.939348 0.156434 0.305212 0.987688 0.156434 0 0.904509 0.309017 -0.293893 0.769421 0.309017 -0.559017 0.559017 0.309017 -0.769421 0.293893 0.309017 -0.904509 0 0.309017 -0.951057 -0.293893 0.309017 -0.904509 -0.559017 0.309017 -0.769421 -0.769421 0.309017 -0.559017 -0.904509 0.309017 -0.293893 -0.951057 0.309017 0 -0.904509 0.309017 0.293893 -0.769421 0.309017 0.559017 -0.559017 0.309017 0.769421 -0.293893 0.309017 0.904509 0 0.309017 0.951057 0.293893 0.309017 0.904509 0.559017 0.309017 0.769421 0.769421 0.309017 0.559017 0.904509 0.309017 0.293893 0.951057 0.309017 0 0.847398 0.453991 -0.275336 0.72084 0.453991 -0.523721 0.523721 0.453991 -0.72084 0.275336 0.453991 -0.847398 0 0.453991 -0.891007 -0.275336 0.453991 -0.847398 -0.523721 0.453991 -0.72084 -0.72084 0.453991 -0.523721 -0.847398 0.453991 -0.275336 -0.891007 0.453991 0 -0.847398 0.453991 0.275336 -0.72084 0.453991 0.523721 -0.523721 0.453991 0.72084 -0.275336 0.453991 0.847398 0 0.453991 0.891007 0.275336 0.453991 0.847398 0.523721 0.453991 0.72084 0.72084 0.453991 0.523721 0.847398 0.453991 0.275336 0.891007 0.453991 0 0.769421 0.587785 -0.25 0.654509 0.587785 -0.475529 0.475528 0.587785 -0.654509 0.25 0.587785 -0.769421 0 0.587785 -0.809017 -0.25 0.587785 -0.769421 -0.475528 0.587785 -0.654509 -0.654509 0.587785 -0.475528 -0.769421 0.587785 -0.25 -0.809017 0.587785 0 -0.769421 0.587785 0.25 -0.654509 0.587785 0.475528 -0.475528 0.587785 0.654509 -0.25 0.587785 0.769421 0 0.587785 0.809017 0.25 0.587785 0.769421 0.475528 0.587785 0.654509 0.654509 0.587785 0.475528 0.769421 0.587785 0.25 0.809017 0.587785 0 0.672499 0.707107 -0.218508 0.572062 0.707107 -0.415627 0.415627 0.707107 -0.572062 0.218508 0.707107 -0.672499 0 0.707107 -0.707107 -0.218508 0.707107 -0.672499 -0.415627 0.707107 -0.572062 -0.572062 0.707107 -0.415627 -0.672499 0.707107 -0.218508 -0.707107 0.707107 0 -0.672499 0.707107 0.218508 -0.572062 0.707107 0.415627 -0.415627 0.707107 0.572061 -0.218508 0.707107 0.672499 0 0.707107 0.707107 0.218508 0.707107 0.672499 0.415627 0.707107 0.572061 0.572061 0.707107 0.415627 0.672499 0.707107 0.218508 0.707107 0.707107 0 0.559017 0.809017 -0.181636 0.475528 0.809017 -0.345492 0.345492 0.809017 -0.475528 0.181636 0.809017 -0.559017 0 0.809017 -0.587785 -0.181636 0.809017 -0.559017 -0.345492 0.809017 -0.475528 -0.475528 0.809017 -0.345492 -0.559017 0.809017 -0.181636 -0.587785 0.809017 0 -0.559017 0.809017 0.181636 -0.475528 0.809017 0.345492 -0.345492 0.809017 0.475528 -0.181636 0.809017 0.559017 0 0.809017 0.587785 0.181636 0.809017 0.559017 0.345492 0.809017 0.475528 0.475528 0.809017 0.345492 0.559017 0.809017 0.181636 0.587785 0.809017 0 0.431771 0.891007 -0.140291 0.367286 0.891007 -0.266849 0.266849 0.891007 -0.367286 0.140291 0.891007 -0.431771 0 0.891007 -0.453991 -0.140291 0.891007 -0.431771 -0.266849 0.891007 -0.367286 -0.367286 0.891007 -0.266849 -0.431771 0.891007 -0.140291 -0.453991 0.891007 0 -0.431771 0.891007 0.140291 -0.367286 0.891007 0.266849 -0.266849 0.891007 0.367286 -0.140291 0.891007 0.431771 0 0.891007 0.453991 0.140291 0.891007 0.431771 0.266849 0.891007 0.367286 0.367286 0.891007 0.266849 0.431771 0.891007 0.140291 0.453991 0.891007 0 0.293893 0.951057 -0.095492 0.25 0.951057 -0.181636 0.181636 0.951057 -0.25 0.095492 0.951057 -0.293893 0 0.951057 -0.309017 -0.095492 0.951057 -0.293893 -0.181636 0.951057 -0.25 -0.25 0.951057 -0.181636 -0.293893 0.951057 -0.095492 -0.309017 0.951057 0 -0.293893 0.951057 0.095492 -0.25 0.951057 0.181636 -0.181636 0.951057 0.25 -0.095492 0.951057 0.293893 0 0.951057 0.309017 0.095492 0.951057 0.293893 0.181636 0.951057 0.25 0.25 0.951057 0.181636 0.293893 0.951057 0.095492 0.309017 0.951057 0 0.148778 0.987688 -0.048341 0.126558 0.987688 -0.09195 0.09195 0.987688 -0.126558 0.048341 0.987688 -0.148778 0 0.987688 -0.156435 -0.048341 0.987688 -0.148778 -0.09195 0.987688 -0.126558 -0.126558 0.987688 -0.09195 -0.148778 0.987688 -0.048341 -0.156435 0.987688 0 -0.148778 0.987688 0.048341 -0.126558 0.987688 0.09195 -0.09195 0.987688 0.126558 -0.048341 0.987688 0.148778 0 0.987688 0.156434 0.048341 0.987688 0.148778 0.09195 0.987688 0.126558 0.126558 0.987688 0.09195 0.148778 0.987688 0.048341 0.156434 0.987688 0 0 -1 0 0 1 0
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | 0.148756 -0.987692 -0.048334 0.126539 -0.987692 -0.091936 0.091936 -0.987692 -0.126539 0.048334 -0.987692 -0.148755 0 -0.987692 -0.156411 -0.048334 -0.987692 -0.148755 -0.091936 -0.987692 -0.126538 -0.126539 -0.987692 -0.091935 -0.148756 -0.987692 -0.048334 -0.156411 -0.987692 -1e-006 -0.148755 -0.987692 0.048334 -0.126539 -0.987692 0.091936 -0.091936 -0.987692 0.126539 -0.048334 -0.987692 0.148755 0 -0.987692 0.156411 0.048334 -0.987692 0.148755 0.091936 -0.987692 0.126538 0.126539 -0.987692 0.091936 0.148756 -0.987692 0.048334 0.156411 -0.987692 1e-006 0.293852 -0.951071 -0.095478 0.249965 -0.95107 -0.18161 0.18161 -0.95107 -0.249965 0.095478 -0.95107 -0.293852 0 -0.95107 -0.308974 -0.095478 -0.951071 -0.293852 -0.18161 -0.951071 -0.249965 -0.249965 -0.951071 -0.18161 -0.293852 -0.951071 -0.095478 -0.308974 -0.951071 0 -0.293852 -0.95107 0.095479 -0.249965 -0.95107 0.181611 -0.18161 -0.95107 0.249965 -0.095478 -0.951071 0.293852 0 -0.95107 0.308974 0.095478 -0.951071 0.293852 0.18161 -0.95107 0.249965 0.249965 -0.95107 0.181611 0.293852 -0.95107 0.095479 0.308974 -0.95107 0 0.431718 -0.891035 -0.140273 0.367241 -0.891035 -0.266816 0.266816 -0.891035 -0.367241 0.140274 -0.891035 -0.431718 0 -0.891035 -0.453935 -0.140274 -0.891035 -0.431718 -0.266816 -0.891035 -0.367241 -0.367241 -0.891035 -0.266816 -0.431718 -0.891035 -0.140274 -0.453935 -0.891035 0 -0.431718 -0.891035 0.140274 -0.367241 -0.891035 0.266817 -0.266816 -0.891035 0.367241 -0.140274 -0.891035 0.431718 0 -0.891035 0.453935 0.140274 -0.891035 0.431718 0.266816 -0.891035 0.367241 0.367241 -0.891035 0.266816 0.431718 -0.891035 0.140274 0.453935 -0.891035 0 0.558961 -0.80906 -0.181617 0.475481 -0.80906 -0.345457 0.345457 -0.80906 -0.47548 0.181617 -0.80906 -0.558961 0 -0.80906 -0.587726 -0.181617 -0.80906 -0.558961 -0.345457 -0.80906 -0.475481 -0.475481 -0.80906 -0.345457 -0.558961 -0.80906 -0.181617 -0.587726 -0.80906 0 -0.558961 -0.80906 0.181617 -0.47548 -0.80906 0.345457 -0.345457 -0.80906 0.475481 -0.181617 -0.80906 0.558961 0 -0.80906 0.587726 0.181617 -0.80906 0.558961 0.345457 -0.80906 0.475481 0.475481 -0.80906 0.345457 0.558961 -0.80906 0.181617 0.587726 -0.80906 0 0.672447 -0.707161 -0.218491 0.572018 -0.707161 -0.415595 0.415595 -0.707161 -0.572018 0.218491 -0.707161 -0.672447 0 -0.707161 -0.707053 -0.218491 -0.707161 -0.672447 -0.415595 -0.707161 -0.572018 -0.572018 -0.707161 -0.415595 -0.672447 -0.707161 -0.218491 -0.707053 -0.707161 0 -0.672447 -0.707161 0.218491 -0.572018 -0.707161 0.415595 -0.415595 -0.707161 0.572018 -0.218491 -0.707161 0.672447 0 -0.707161 0.707053 0.218491 -0.707161 0.672447 0.415595 -0.707161 0.572018 0.572018 -0.707161 0.415595 0.672447 -0.707161 0.218491 0.707053 -0.707161 1e-006 0.76938 -0.587844 -0.249986 0.654474 -0.587844 -0.475503 0.475503 -0.587844 -0.654474 0.249987 -0.587844 -0.76938 0 -0.587844 -0.808974 -0.249987 -0.587844 -0.76938 -0.475503 -0.587844 -0.654474 -0.654474 -0.587844 -0.475503 -0.76938 -0.587844 -0.249987 -0.808974 -0.587844 0 -0.76938 -0.587844 0.249987 -0.654474 -0.587844 0.475503 -0.475503 -0.587844 0.654474 -0.249987 -0.587844 0.76938 0 -0.587844 0.808974 0.249987 -0.587844 0.76938 0.475503 -0.587844 0.654474 0.654474 -0.587844 0.475503 0.76938 -0.587844 0.249987 0.808974 -0.587844 1e-006 0.847371 -0.454045 -0.275327 0.720817 -0.454045 -0.523704 0.523704 -0.454045 -0.720817 0.275327 -0.454045 -0.847371 0 -0.454045 -0.890979 -0.275328 -0.454045 -0.847371 -0.523704 -0.454045 -0.720817 -0.720817 -0.454045 -0.523704 -0.847371 -0.454045 -0.275327 -0.890979 -0.454045 0 -0.847371 -0.454045 0.275328 -0.720817 -0.454045 0.523704 -0.523704 -0.454045 0.720817 -0.275327 -0.454045 0.847371 0 -0.454045 0.890979 0.275328 -0.454045 0.847371 0.523704 -0.454045 0.720817 0.720817 -0.454045 0.523704 0.847371 -0.454045 0.275327 0.890979 -0.454045 1e-006 0.904496 -0.309059 -0.293888 0.76941 -0.309059 -0.559009 0.559009 -0.309059 -0.76941 0.293888 -0.309059 -0.904496 0 -0.309059 -0.951043 -0.293889 -0.309059 -0.904495 -0.559009 -0.309059 -0.76941 -0.76941 -0.309059 -0.559009 -0.904495 -0.309059 -0.293888 -0.951043 -0.309059 0 -0.904495 -0.309059 0.293888 -0.76941 -0.309059 0.559009 -0.559009 -0.309059 0.76941 -0.293888 -0.309059 0.904495 0 -0.309059 0.951043 0.293888 -0.309059 0.904495 0.559009 -0.309059 0.76941 0.76941 -0.309059 0.559009 0.904495 -0.309059 0.293888 0.951043 -0.309059 1e-006 0.939344 -0.156457 -0.305211 0.799054 -0.156457 -0.580547 0.580546 -0.156457 -0.799054 0.305211 -0.156457 -0.939344 0 -0.156457 -0.987685 -0.305212 -0.156457 -0.939344 -0.580547 -0.156457 -0.799054 -0.799054 -0.156457 -0.580546 -0.939344 -0.156457 -0.305211 -0.987685 -0.156457 0 -0.939344 -0.156457 0.305211 -0.799054 -0.156457 0.580547 -0.580546 -0.156457 0.799054 -0.305211 -0.156457 0.939344 0 -0.156457 0.987685 0.305211 -0.156457 0.939344 0.580547 -0.156457 0.799054 0.799054 -0.156457 0.580546 0.939344 -0.156457 0.305211 0.987685 -0.156457 1e-006 0.951057 0 -0.309016 0.809017 0 -0.587785 0.587785 0 -0.809017 0.309017 0 -0.951057 0 0 -1 -0.309017 0 -0.951056 -0.587785 0 -0.809017 -0.809017 0 -0.587785 -0.951057 0 -0.309017 -1 0 0 -0.951056 0 0.309017 -0.809017 0 0.587785 -0.587785 0 0.809017 -0.309017 0 0.951057 0 0 1 0.309017 0 0.951056 0.587785 0 0.809017 0.809017 0 0.587785 0.951057 0 0.309017 1 0 1e-006 0.939344 0.156457 -0.305211 0.799054 0.156457 -0.580547 0.580546 0.156457 -0.799054 0.305211 0.156457 -0.939344 0 0.156457 -0.987685 -0.305212 0.156457 -0.939344 -0.580547 0.156457 -0.799054 -0.799054 0.156457 -0.580546 -0.939344 0.156457 -0.305211 -0.987685 0.156457 0 -0.939344 0.156457 0.305211 -0.799054 0.156457 0.580547 -0.580546 0.156457 0.799054 -0.305211 0.156457 0.939344 0 0.156457 0.987685 0.305211 0.156457 0.939344 0.580547 0.156457 0.799054 0.799054 0.156457 0.580546 0.939344 0.156457 0.305211 0.987685 0.156457 1e-006 0.904496 0.309059 -0.293888 0.76941 0.309059 -0.559009 0.559009 0.309059 -0.76941 0.293888 0.309059 -0.904496 0 0.309059 -0.951043 -0.293889 0.309059 -0.904495 -0.559009 0.309059 -0.76941 -0.76941 0.309059 -0.559009 -0.904495 0.309059 -0.293888 -0.951043 0.309059 0 -0.904495 0.309059 0.293888 -0.76941 0.309059 0.559009 -0.559009 0.309059 0.76941 -0.293888 0.309059 0.904495 0 0.309059 0.951043 0.293888 0.309059 0.904495 0.559009 0.309059 0.76941 0.76941 0.309059 0.559009 0.904495 0.309059 0.293888 0.951043 0.309059 1e-006 0.847371 0.454045 -0.275327 0.720817 0.454045 -0.523704 0.523704 0.454045 -0.720817 0.275327 0.454045 -0.847371 0 0.454045 -0.890979 -0.275328 0.454045 -0.847371 -0.523704 0.454045 -0.720817 -0.720817 0.454045 -0.523704 -0.847371 0.454045 -0.275327 -0.890979 0.454045 0 -0.847371 0.454045 0.275328 -0.720817 0.454045 0.523704 -0.523704 0.454045 0.720817 -0.275327 0.454045 0.847371 0 0.454045 0.890979 0.275328 0.454045 0.847371 0.523704 0.454045 0.720817 0.720817 0.454045 0.523704 0.847371 0.454045 0.275327 0.890979 0.454045 1e-006 0.76938 0.587844 -0.249986 0.654474 0.587844 -0.475503 0.475503 0.587844 -0.654474 0.249987 0.587844 -0.76938 0 0.587844 -0.808974 -0.249987 0.587844 -0.76938 -0.475503 0.587844 -0.654474 -0.654474 0.587844 -0.475503 -0.76938 0.587844 -0.249987 -0.808974 0.587844 0 -0.76938 0.587844 0.249987 -0.654474 0.587844 0.475503 -0.475503 0.587844 0.654474 -0.249987 0.587844 0.76938 0 0.587844 0.808974 0.249987 0.587844 0.76938 0.475503 0.587844 0.654474 0.654474 0.587844 0.475503 0.76938 0.587844 0.249987 0.808974 0.587844 1e-006 0.672447 0.707161 -0.218491 0.572018 0.707161 -0.415595 0.415595 0.707161 -0.572018 0.218491 0.707161 -0.672447 0 0.707161 -0.707053 -0.218491 0.707161 -0.672447 -0.415595 0.707161 -0.572018 -0.572018 0.707161 -0.415595 -0.672447 0.707161 -0.218491 -0.707053 0.707161 0 -0.672447 0.707161 0.218491 -0.572018 0.707161 0.415595 -0.415595 0.707161 0.572018 -0.218491 0.707161 0.672447 0 0.707161 0.707053 0.218491 0.707161 0.672447 0.415595 0.707161 0.572018 0.572018 0.707161 0.415595 0.672447 0.707161 0.218491 0.707053 0.707161 0 0.558961 0.80906 -0.181617 0.475481 0.80906 -0.345457 0.345457 0.80906 -0.475481 0.181617 0.80906 -0.558961 0 0.80906 -0.587726 -0.181617 0.80906 -0.558961 -0.345457 0.80906 -0.475481 -0.475481 0.80906 -0.345457 -0.558961 0.80906 -0.181617 -0.587726 0.80906 0 -0.558961 0.80906 0.181617 -0.475481 0.80906 0.345457 -0.345457 0.80906 0.475481 -0.181617 0.80906 0.558961 0 0.80906 0.587726 0.181617 0.80906 0.558961 0.345457 0.80906 0.475481 0.475481 0.80906 0.345457 0.558961 0.80906 0.181617 0.587726 0.80906 1e-006 0.431718 0.891035 -0.140273 0.367241 0.891035 -0.266816 0.266816 0.891035 -0.367241 0.140274 0.891035 -0.431718 0 0.891035 -0.453935 -0.140274 0.891035 -0.431718 -0.266816 0.891035 -0.367241 -0.367241 0.891035 -0.266816 -0.431718 0.891035 -0.140274 -0.453935 0.891035 0 -0.431718 0.891035 0.140274 -0.367241 0.891035 0.266817 -0.266816 0.891035 0.367241 -0.140274 0.891035 0.431718 0 0.891035 0.453935 0.140274 0.891035 0.431718 0.266816 0.891035 0.367241 0.367241 0.891035 0.266816 0.431718 0.891035 0.140274 0.453935 0.891035 0 0.293852 0.951071 -0.095478 0.249965 0.951071 -0.18161 0.18161 0.951071 -0.249965 0.095478 0.951071 -0.293852 0 0.951071 -0.308974 -0.095478 0.951071 -0.293852 -0.18161 0.951071 -0.249965 -0.249965 0.95107 -0.18161 -0.293852 0.951071 -0.095478 -0.308974 0.951071 0 -0.293852 0.951071 0.095478 -0.249965 0.951071 0.18161 -0.18161 0.95107 0.249965 -0.095478 0.951071 0.293852 0 0.951071 0.308974 0.095478 0.95107 0.293852 0.18161 0.95107 0.249965 0.249965 0.95107 0.18161 0.293852 0.951071 0.095478 0.308974 0.95107 0 0.148756 0.987692 -0.048334 0.126539 0.987692 -0.091935 0.091936 0.987692 -0.126538 0.048334 0.987692 -0.148755 0 0.987692 -0.156411 -0.048334 0.987692 -0.148755 -0.091936 0.987692 -0.126539 -0.126539 0.987692 -0.091936 -0.148756 0.987692 -0.048333 -0.156411 0.987692 1e-006 -0.148756 0.987692 0.048334 -0.126539 0.987692 0.091935 -0.091936 0.987692 0.126538 -0.048334 0.987692 0.148755 0 0.987692 0.156411 0.048334 0.987692 0.148755 0.091936 0.987692 0.126539 0.126539 0.987692 0.091936 0.148756 0.987692 0.048333 0.156411 0.987692 -1e-006 0 -1 0 0 1 0
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | 0 0.05 0.05 0.05 0.1 0.05 0.15 0.05 0.2 0.05 0.25 0.05 0.3 0.05 0.35 0.05 0.4 0.05 0.45 0.05 0.5 0.05 0.55 0.05 0.6 0.05 0.65 0.05 0.7 0.05 0.75 0.05 0.8 0.05 0.85 0.05 0.9 0.05 0.95 0.05 1 0.05 0 0.1 0.05 0.1 0.1 0.1 0.15 0.1 0.2 0.1 0.25 0.1 0.3 0.1 0.35 0.1 0.4 0.1 0.45 0.1 0.5 0.1 0.55 0.1 0.6 0.1 0.65 0.1 0.7 0.1 0.75 0.1 0.8 0.1 0.85 0.1 0.9 0.1 0.95 0.1 1 0.1 0 0.15 0.05 0.15 0.1 0.15 0.15 0.15 0.2 0.15 0.25 0.15 0.3 0.15 0.35 0.15 0.4 0.15 0.45 0.15 0.5 0.15 0.55 0.15 0.6 0.15 0.65 0.15 0.7 0.15 0.75 0.15 0.8 0.15 0.85 0.15 0.9 0.15 0.95 0.15 1 0.15 0 0.2 0.05 0.2 0.1 0.2 0.15 0.2 0.2 0.2 0.25 0.2 0.3 0.2 0.35 0.2 0.4 0.2 0.45 0.2 0.5 0.2 0.55 0.2 0.6 0.2 0.65 0.2 0.7 0.2 0.75 0.2 0.8 0.2 0.85 0.2 0.9 0.2 0.95 0.2 1 0.2 0 0.25 0.05 0.25 0.1 0.25 0.15 0.25 0.2 0.25 0.25 0.25 0.3 0.25 0.35 0.25 0.4 0.25 0.45 0.25 0.5 0.25 0.55 0.25 0.6 0.25 0.65 0.25 0.7 0.25 0.75 0.25 0.8 0.25 0.85 0.25 0.9 0.25 0.95 0.25 1 0.25 0 0.3 0.05 0.3 0.1 0.3 0.15 0.3 0.2 0.3 0.25 0.3 0.3 0.3 0.35 0.3 0.4 0.3 0.45 0.3 0.5 0.3 0.55 0.3 0.6 0.3 0.65 0.3 0.7 0.3 0.75 0.3 0.8 0.3 0.85 0.3 0.9 0.3 0.95 0.3 1 0.3 0 0.35 0.05 0.35 0.1 0.35 0.15 0.35 0.2 0.35 0.25 0.35 0.3 0.35 0.35 0.35 0.4 0.35 0.45 0.35 0.5 0.35 0.55 0.35 0.6 0.35 0.65 0.35 0.7 0.35 0.75 0.35 0.8 0.35 0.85 0.35 0.9 0.35 0.95 0.35 1 0.35 0 0.4 0.05 0.4 0.1 0.4 0.15 0.4 0.2 0.4 0.25 0.4 0.3 0.4 0.35 0.4 0.4 0.4 0.45 0.4 0.5 0.4 0.55 0.4 0.6 0.4 0.65 0.4 0.7 0.4 0.75 0.4 0.8 0.4 0.85 0.4 0.9 0.4 0.95 0.4 1 0.4 0 0.45 0.05 0.45 0.1 0.45 0.15 0.45 0.2 0.45 0.25 0.45 0.3 0.45 0.35 0.45 0.4 0.45 0.45 0.45 0.5 0.45 0.55 0.45 0.6 0.45 0.65 0.45 0.7 0.45 0.75 0.45 0.8 0.45 0.85 0.45 0.9 0.45 0.95 0.45 1 0.45 0 0.5 0.05 0.5 0.1 0.5 0.15 0.5 0.2 0.5 0.25 0.5 0.3 0.5 0.35 0.5 0.4 0.5 0.45 0.5 0.5 0.5 0.55 0.5 0.6 0.5 0.65 0.5 0.7 0.5 0.75 0.5 0.8 0.5 0.85 0.5 0.9 0.5 0.95 0.5 1 0.5 0 0.55 0.05 0.55 0.1 0.55 0.15 0.55 0.2 0.55 0.25 0.55 0.3 0.55 0.35 0.55 0.4 0.55 0.45 0.55 0.5 0.55 0.55 0.55 0.6 0.55 0.65 0.55 0.7 0.55 0.75 0.55 0.8 0.55 0.85 0.55 0.9 0.55 0.95 0.55 1 0.55 0 0.6 0.05 0.6 0.1 0.6 0.15 0.6 0.2 0.6 0.25 0.6 0.3 0.6 0.35 0.6 0.4 0.6 0.45 0.6 0.5 0.6 0.55 0.6 0.6 0.6 0.65 0.6 0.7 0.6 0.75 0.6 0.8 0.6 0.85 0.6 0.9 0.6 0.95 0.6 1 0.6 0 0.65 0.05 0.65 0.1 0.65 0.15 0.65 0.2 0.65 0.25 0.65 0.3 0.65 0.35 0.65 0.4 0.65 0.45 0.65 0.5 0.65 0.55 0.65 0.6 0.65 0.65 0.65 0.7 0.65 0.75 0.65 0.8 0.65 0.85 0.65 0.9 0.65 0.95 0.65 1 0.65 0 0.7 0.05 0.7 0.1 0.7 0.15 0.7 0.2 0.7 0.25 0.7 0.3 0.7 0.35 0.7 0.4 0.7 0.45 0.7 0.5 0.7 0.55 0.7 0.6 0.7 0.65 0.7 0.7 0.7 0.75 0.7 0.8 0.7 0.85 0.7 0.9 0.7 0.95 0.7 1 0.7 0 0.75 0.05 0.75 0.1 0.75 0.15 0.75 0.2 0.75 0.25 0.75 0.3 0.75 0.35 0.75 0.4 0.75 0.45 0.75 0.5 0.75 0.55 0.75 0.6 0.75 0.65 0.75 0.7 0.75 0.75 0.75 0.8 0.75 0.85 0.75 0.9 0.75 0.95 0.75 1 0.75 0 0.8 0.05 0.8 0.1 0.8 0.15 0.8 0.2 0.8 0.25 0.8 0.3 0.8 0.35 0.8 0.4 0.8 0.45 0.8 0.5 0.8 0.55 0.8 0.6 0.8 0.65 0.8 0.7 0.8 0.75 0.8 0.8 0.8 0.85 0.8 0.9 0.8 0.95 0.8 1 0.8 0 0.85 0.05 0.85 0.1 0.85 0.15 0.85 0.2 0.85 0.25 0.85 0.3 0.85 0.35 0.85 0.4 0.85 0.45 0.85 0.5 0.85 0.55 0.85 0.6 0.85 0.65 0.85 0.7 0.85 0.75 0.85 0.8 0.85 0.85 0.85 0.9 0.85 0.95 0.85 1 0.85 0 0.9 0.05 0.9 0.1 0.9 0.15 0.9 0.2 0.9 0.25 0.9 0.3 0.9 0.35 0.9 0.4 0.9 0.45 0.9 0.5 0.9 0.55 0.9 0.6 0.9 0.65 0.9 0.7 0.9 0.75 0.9 0.8 0.9 0.85 0.9 0.9 0.9 0.95 0.9 1 0.9 0 0.95 0.05 0.95 0.1 0.95 0.15 0.95 0.2 0.95 0.25 0.95 0.3 0.95 0.35 0.95 0.4 0.95 0.45 0.95 0.5 0.95 0.55 0.95 0.6 0.95 0.65 0.95 0.7 0.95 0.75 0.95 0.8 0.95 0.85 0.95 0.9 0.95 0.95 0.95 1 0.95 0.5 0 0.5 1
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
111 | 0 0 1 1 21 22 20 21 1 1 2 2 22 23 21 22 2 2 3 3 23 24 22 23 3 3 4 4 24 25 23 24 4 4 5 5 25 26 24 25 5 5 6 6 26 27 25 26 6 6 7 7 27 28 26 27 7 7 8 8 28 29 27 28 8 8 9 9 29 30 28 29 9 9 10 10 30 31 29 30 10 10 11 11 31 32 30 31 11 11 12 12 32 33 31 32 12 12 13 13 33 34 32 33 13 13 14 14 34 35 33 34 14 14 15 15 35 36 34 35 15 15 16 16 36 37 35 36 16 16 17 17 37 38 36 37 17 17 18 18 38 39 37 38 18 18 19 19 39 40 38 39 19 19 0 20 20 41 39 40 20 21 21 22 41 43 40 42 21 22 22 23 42 44 41 43 22 23 23 24 43 45 42 44 23 24 24 25 44 46 43 45 24 25 25 26 45 47 44 46 25 26 26 27 46 48 45 47 26 27 27 28 47 49 46 48 27 28 28 29 48 50 47 49 28 29 29 30 49 51 48 50 29 30 30 31 50 52 49 51 30 31 31 32 51 53 50 52 31 32 32 33 52 54 51 53 32 33 33 34 53 55 52 54 33 34 34 35 54 56 53 55 34 35 35 36 55 57 54 56 35 36 36 37 56 58 55 57 36 37 37 38 57 59 56 58 37 38 38 39 58 60 57 59 38 39 39 40 59 61 58 60 39 40 20 41 40 62 59 61 40 42 41 43 61 64 60 63 41 43 42 44 62 65 61 64 42 44 43 45 63 66 62 65 43 45 44 46 64 67 63 66 44 46 45 47 65 68 64 67 45 47 46 48 66 69 65 68 46 48 47 49 67 70 66 69 47 49 48 50 68 71 67 70 48 50 49 51 69 72 68 71 49 51 50 52 70 73 69 72 50 52 51 53 71 74 70 73 51 53 52 54 72 75 71 74 52 54 53 55 73 76 72 75 53 55 54 56 74 77 73 76 54 56 55 57 75 78 74 77 55 57 56 58 76 79 75 78 56 58 57 59 77 80 76 79 57 59 58 60 78 81 77 80 58 60 59 61 79 82 78 81 59 61 40 62 60 83 79 82 60 63 61 64 81 85 80 84 61 64 62 65 82 86 81 85 62 65 63 66 83 87 82 86 63 66 64 67 84 88 83 87 64 67 65 68 85 89 84 88 65 68 66 69 86 90 85 89 66 69 67 70 87 91 86 90 67 70 68 71 88 92 87 91 68 71 69 72 89 93 88 92 69 72 70 73 90 94 89 93 70 73 71 74 91 95 90 94 71 74 72 75 92 96 91 95 72 75 73 76 93 97 92 96 73 76 74 77 94 98 93 97 74 77 75 78 95 99 94 98 75 78 76 79 96 100 95 99 76 79 77 80 97 101 96 100 77 80 78 81 98 102 97 101 78 81 79 82 99 103 98 102 79 82 60 83 80 104 99 103 80 84 81 85 101 106 100 105 81 85 82 86 102 107 101 106 82 86 83 87 103 108 102 107 83 87 84 88 104 109 103 108 84 88 85 89 105 110 104 109 85 89 86 90 106 111 105 110 86 90 87 91 107 112 106 111 87 91 88 92 108 113 107 112 88 92 89 93 109 114 108 113 89 93 90 94 110 115 109 114 90 94 91 95 111 116 110 115 91 95 92 96 112 117 111 116 92 96 93 97 113 118 112 117 93 97 94 98 114 119 113 118 94 98 95 99 115 120 114 119 95 99 96 100 116 121 115 120 96 100 97 101 117 122 116 121 97 101 98 102 118 123 117 122 98 102 99 103 119 124 118 123 99 103 80 104 100 125 119 124 100 105 101 106 121 127 120 126 101 106 102 107 122 128 121 127 102 107 103 108 123 129 122 128 103 108 104 109 124 130 123 129 104 109 105 110 125 131 124 130 105 110 106 111 126 132 125 131 106 111 107 112 127 133 126 132 107 112 108 113 128 134 127 133 108 113 109 114 129 135 128 134 109 114 110 115 130 136 129 135 110 115 111 116 131 137 130 136 111 116 112 117 132 138 131 137 112 117 113 118 133 139 132 138 113 118 114 119 134 140 133 139 114 119 115 120 135 141 134 140 115 120 116 121 136 142 135 141 116 121 117 122 137 143 136 142 117 122 118 123 138 144 137 143 118 123 119 124 139 145 138 144 119 124 100 125 120 146 139 145 120 126 121 127 141 148 140 147 121 127 122 128 142 149 141 148 122 128 123 129 143 150 142 149 123 129 124 130 144 151 143 150 124 130 125 131 145 152 144 151 125 131 126 132 146 153 145 152 126 132 127 133 147 154 146 153 127 133 128 134 148 155 147 154 128 134 129 135 149 156 148 155 129 135 130 136 150 157 149 156 130 136 131 137 151 158 150 157 131 137 132 138 152 159 151 158 132 138 133 139 153 160 152 159 133 139 134 140 154 161 153 160 134 140 135 141 155 162 154 161 135 141 136 142 156 163 155 162 136 142 137 143 157 164 156 163 137 143 138 144 158 165 157 164 138 144 139 145 159 166 158 165 139 145 120 146 140 167 159 166 140 147 141 148 161 169 160 168 141 148 142 149 162 170 161 169 142 149 143 150 163 171 162 170 143 150 144 151 164 172 163 171 144 151 145 152 165 173 164 172 145 152 146 153 166 174 165 173 146 153 147 154 167 175 166 174 147 154 148 155 168 176 167 175 148 155 149 156 169 177 168 176 149 156 150 157 170 178 169 177 150 157 151 158 171 179 170 178 151 158 152 159 172 180 171 179 152 159 153 160 173 181 172 180 153 160 154 161 174 182 173 181 154 161 155 162 175 183 174 182 155 162 156 163 176 184 175 183 156 163 157 164 177 185 176 184 157 164 158 165 178 186 177 185 158 165 159 166 179 187 178 186 159 166 140 167 160 188 179 187 160 168 161 169 181 190 180 189 161 169 162 170 182 191 181 190 162 170 163 171 183 192 182 191 163 171 164 172 184 193 183 192 164 172 165 173 185 194 184 193 165 173 166 174 186 195 185 194 166 174 167 175 187 196 186 195 167 175 168 176 188 197 187 196 168 176 169 177 189 198 188 197 169 177 170 178 190 199 189 198 170 178 171 179 191 200 190 199 171 179 172 180 192 201 191 200 172 180 173 181 193 202 192 201 173 181 174 182 194 203 193 202 174 182 175 183 195 204 194 203 175 183 176 184 196 205 195 204 176 184 177 185 197 206 196 205 177 185 178 186 198 207 197 206 178 186 179 187 199 208 198 207 179 187 160 188 180 209 199 208 180 189 181 190 201 211 200 210 181 190 182 191 202 212 201 211 182 191 183 192 203 213 202 212 183 192 184 193 204 214 203 213 184 193 185 194 205 215 204 214 185 194 186 195 206 216 205 215 186 195 187 196 207 217 206 216 187 196 188 197 208 218 207 217 188 197 189 198 209 219 208 218 189 198 190 199 210 220 209 219 190 199 191 200 211 221 210 220 191 200 192 201 212 222 211 221 192 201 193 202 213 223 212 222 193 202 194 203 214 224 213 223 194 203 195 204 215 225 214 224 195 204 196 205 216 226 215 225 196 205 197 206 217 227 216 226 197 206 198 207 218 228 217 227 198 207 199 208 219 229 218 228 199 208 180 209 200 230 219 229 200 210 201 211 221 232 220 231 201 211 202 212 222 233 221 232 202 212 203 213 223 234 222 233 203 213 204 214 224 235 223 234 204 214 205 215 225 236 224 235 205 215 206 216 226 237 225 236 206 216 207 217 227 238 226 237 207 217 208 218 228 239 227 238 208 218 209 219 229 240 228 239 209 219 210 220 230 241 229 240 210 220 211 221 231 242 230 241 211 221 212 222 232 243 231 242 212 222 213 223 233 244 232 243 213 223 214 224 234 245 233 244 214 224 215 225 235 246 234 245 215 225 216 226 236 247 235 246 216 226 217 227 237 248 236 247 217 227 218 228 238 249 237 248 218 228 219 229 239 250 238 249 219 229 200 230 220 251 239 250 220 231 221 232 241 253 240 252 221 232 222 233 242 254 241 253 222 233 223 234 243 255 242 254 223 234 224 235 244 256 243 255 224 235 225 236 245 257 244 256 225 236 226 237 246 258 245 257 226 237 227 238 247 259 246 258 227 238 228 239 248 260 247 259 228 239 229 240 249 261 248 260 229 240 230 241 250 262 249 261 230 241 231 242 251 263 250 262 231 242 232 243 252 264 251 263 232 243 233 244 253 265 252 264 233 244 234 245 254 266 253 265 234 245 235 246 255 267 254 266 235 246 236 247 256 268 255 267 236 247 237 248 257 269 256 268 237 248 238 249 258 270 257 269 238 249 239 250 259 271 258 270 239 250 220 251 240 272 259 271 240 252 241 253 261 274 260 273 241 253 242 254 262 275 261 274 242 254 243 255 263 276 262 275 243 255 244 256 264 277 263 276 244 256 245 257 265 278 264 277 245 257 246 258 266 279 265 278 246 258 247 259 267 280 266 279 247 259 248 260 268 281 267 280 248 260 249 261 269 282 268 281 249 261 250 262 270 283 269 282 250 262 251 263 271 284 270 283 251 263 252 264 272 285 271 284 252 264 253 265 273 286 272 285 253 265 254 266 274 287 273 286 254 266 255 267 275 288 274 287 255 267 256 268 276 289 275 288 256 268 257 269 277 290 276 289 257 269 258 270 278 291 277 290 258 270 259 271 279 292 278 291 259 271 240 272 260 293 279 292 260 273 261 274 281 295 280 294 261 274 262 275 282 296 281 295 262 275 263 276 283 297 282 296 263 276 264 277 284 298 283 297 264 277 265 278 285 299 284 298 265 278 266 279 286 300 285 299 266 279 267 280 287 301 286 300 267 280 268 281 288 302 287 301 268 281 269 282 289 303 288 302 269 282 270 283 290 304 289 303 270 283 271 284 291 305 290 304 271 284 272 285 292 306 291 305 272 285 273 286 293 307 292 306 273 286 274 287 294 308 293 307 274 287 275 288 295 309 294 308 275 288 276 289 296 310 295 309 276 289 277 290 297 311 296 310 277 290 278 291 298 312 297 311 278 291 279 292 299 313 298 312 279 292 260 293 280 314 299 313 280 294 281 295 301 316 300 315 281 295 282 296 302 317 301 316 282 296 283 297 303 318 302 317 283 297 284 298 304 319 303 318 284 298 285 299 305 320 304 319 285 299 286 300 306 321 305 320 286 300 287 301 307 322 306 321 287 301 288 302 308 323 307 322 288 302 289 303 309 324 308 323 289 303 290 304 310 325 309 324 290 304 291 305 311 326 310 325 291 305 292 306 312 327 311 326 292 306 293 307 313 328 312 327 293 307 294 308 314 329 313 328 294 308 295 309 315 330 314 329 295 309 296 310 316 331 315 330 296 310 297 311 317 332 316 331 297 311 298 312 318 333 317 332 298 312 299 313 319 334 318 333 299 313 280 314 300 335 319 334 300 315 301 316 321 337 320 336 301 316 302 317 322 338 321 337 302 317 303 318 323 339 322 338 303 318 304 319 324 340 323 339 304 319 305 320 325 341 324 340 305 320 306 321 326 342 325 341 306 321 307 322 327 343 326 342 307 322 308 323 328 344 327 343 308 323 309 324 329 345 328 344 309 324 310 325 330 346 329 345 310 325 311 326 331 347 330 346 311 326 312 327 332 348 331 347 312 327 313 328 333 349 332 348 313 328 314 329 334 350 333 349 314 329 315 330 335 351 334 350 315 330 316 331 336 352 335 351 316 331 317 332 337 353 336 352 317 332 318 333 338 354 337 353 318 333 319 334 339 355 338 354 319 334 300 335 320 356 339 355 320 336 321 337 341 358 340 357 321 337 322 338 342 359 341 358 322 338 323 339 343 360 342 359 323 339 324 340 344 361 343 360 324 340 325 341 345 362 344 361 325 341 326 342 346 363 345 362 326 342 327 343 347 364 346 363 327 343 328 344 348 365 347 364 328 344 329 345 349 366 348 365 329 345 330 346 350 367 349 366 330 346 331 347 351 368 350 367 331 347 332 348 352 369 351 368 332 348 333 349 353 370 352 369 333 349 334 350 354 371 353 370 334 350 335 351 355 372 354 371 335 351 336 352 356 373 355 372 336 352 337 353 357 374 356 373 337 353 338 354 358 375 357 374 338 354 339 355 359 376 358 375 339 355 320 356 340 377 359 376 340 357 341 358 361 379 360 378 341 358 342 359 362 380 361 379 342 359 343 360 363 381 362 380 343 360 344 361 364 382 363 381 344 361 345 362 365 383 364 382 345 362 346 363 366 384 365 383 346 363 347 364 367 385 366 384 347 364 348 365 368 386 367 385 348 365 349 366 369 387 368 386 349 366 350 367 370 388 369 387 350 367 351 368 371 389 370 388 351 368 352 369 372 390 371 389 352 369 353 370 373 391 372 390 353 370 354 371 374 392 373 391 354 371 355 372 375 393 374 392 355 372 356 373 376 394 375 393 356 373 357 374 377 395 376 394 357 374 358 375 378 396 377 395 358 375 359 376 379 397 378 396 359 376 340 377 360 398 379 397 1 1 0 0 380 399 2 2 1 1 380 399 3 3 2 2 380 399 4 4 3 3 380 399 5 5 4 4 380 399 6 6 5 5 380 399 7 7 6 6 380 399 8 8 7 7 380 399 9 9 8 8 380 399 10 10 9 9 380 399 11 11 10 10 380 399 12 12 11 11 380 399 13 13 12 12 380 399 14 14 13 13 380 399 15 15 14 14 380 399 16 16 15 15 380 399 17 17 16 16 380 399 18 18 17 17 380 399 19 19 18 18 380 399 0 20 19 19 380 399 360 378 361 379 381 400 361 379 362 380 381 400 362 380 363 381 381 400 363 381 364 382 381 400 364 382 365 383 381 400 365 383 366 384 381 400 366 384 367 385 381 400 367 385 368 386 381 400 368 386 369 387 381 400 369 387 370 388 381 400 370 388 371 389 381 400 371 389 372 390 381 400 372 390 373 391 381 400 373 391 374 392 381 400 374 392 375 393 381 400 375 393 376 394 381 400 376 394 377 395 381 400 377 395 378 396 381 400 378 396 379 397 381 400 379 397 360 398 381 400
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | 0 0 1 0
120 | 0 1 0 0
121 | 1 0 0 0
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/data/sphere.lz4.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pierrec/node-lz4/943e768691a9fb29e2d9a88f9942463765a45468/data/sphere.lz4.dat
--------------------------------------------------------------------------------
/data/test:
--------------------------------------------------------------------------------
1 | {
2 | "author": "Pierre Curto"
3 | , "name": "lz4-js"
4 | , "description": "LZ4 streaming compression and decompression"
5 | , "keywords": ["lz4","compression","decompression","stream"]
6 | , "version": "0.0.1"
7 | , "homepage": "http://github.com/pierrec/node-lz4-js"
8 | , "repository": {
9 | "type": "git"
10 | , "url": "git://github.com/pierrec/node-lz4-js.git"
11 | }
12 | , "main": "./lib/lz4.js"
13 | , "bugs": { "url" : "http://github.com/pierrec/node-lz4-js/issues" }
14 | , "licenses":
15 | [ {
16 | "type": "MIT"
17 | , "url": "http://github.com/pierrec/node-lz4-js/raw/master/LICENSE"
18 | }
19 | ]
20 | , "engines": {
21 | "node": ">= 0.8"
22 | }
23 | , "dependencies": {
24 | "inherits": ">= 1.0"
25 | }
26 | , "devDependencies": {
27 | "mocha": ">= 0.10"
28 | }
29 | , "scripts": {
30 | "test": "mocha test/*-test.js"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/data/test.lz4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pierrec/node-lz4/943e768691a9fb29e2d9a88f9942463765a45468/data/test.lz4
--------------------------------------------------------------------------------
/data/testHC.lz4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pierrec/node-lz4/943e768691a9fb29e2d9a88f9942463765a45468/data/testHC.lz4
--------------------------------------------------------------------------------
/data/test_medium:
--------------------------------------------------------------------------------
1 | # LZ4
2 |
3 | [LZ4](http://fastcompression.blogspot.fr/) is a very fast compression and decompression algorithm. This nodejs module provides a Javascript implementation of the decoder as well as native bindings to the LZ4 functions. Nodejs Streams are also supported for compression and decompression.
4 |
5 |
6 | ## Install
7 |
8 | npm install lz4
9 |
10 |
11 | ## Usage
12 |
13 | ### Encoding
14 |
15 | There are 2 ways to encode:
16 |
17 | * __asynchronous__ using nodejs Streams - slowest but can handle very large data sets (no memory limitations).
18 | * __synchronous__ by feeding the whole set of data - faster but is limited by the amount of memory
19 |
20 |
21 | #### Asynchronous encoding
22 |
23 | First, create an LZ4 encoding NodeJS stream with `LZ4#createEncoderStream(options)`.
24 |
25 | * `options.chunkSize` (_Number_): chunk size to use (default=8Mb) (optional)
26 | * `options.hc` (_Boolean_): use high compression (default=false) (optional)
27 |
28 |
29 | The stream can then encode any data piped to it. It will emit a `data` event on each encoded chunk, which can be saved into an output stream.
30 |
31 | The following example shows how to encode a file `test` into `test.lz4`.
32 |
33 |
34 | ```javascript
35 | var fs = require('fs')
36 | var lz4 = require('lz4')
37 |
38 | var encoder = lz4.createEncoderStream()
39 |
40 | var input = fs.createReadStream('test')
41 | var output = fs.createWriteStream('test.lz4')
42 |
43 | input.pipe(encoder).pipe(output)
44 |
45 | ```
46 |
47 | #### Synchronous encoding
48 |
49 | Read the data into memory and feed it to `LZ4#encode(input[, options])` to decode an LZ4 stream.
50 |
51 | * `input` (_Buffer_): data to encode
52 | * `options` (_Object_): LZ4 stream options (optional)
53 | * `options.blockMaxSize` (_Number_): chunk size to use (default=4Mb)
54 | * `options.highCompression` (_Boolean_): use high compression (default=false)
55 | * `options.blockIndependence` (_Boolean_): (default=true)
56 | * `options.blockChecksum` (_Boolean_): add compressed blocks checksum (default=false)
57 | * `options.streamSize` (_Boolean_): add full LZ4 stream size (default=false)
58 | * `options.streamChecksum` (_Boolean_): add full LZ4 stream checksum (default=true)
59 | * `options.dict` (_Boolean_): use dictionary (default=false)
60 | * `options.dictId` (_Integer_): dictionary id (default=0)
61 |
62 |
63 | ```javascript
64 | var fs = require('fs')
65 | var lz4 = require('lz4')
66 |
67 | var input = fs.readFileSync('test')
68 | var output = lz4.encode(input)
69 |
70 | fs.writeFileSync('test.lz4', output)
71 |
72 | ```
73 |
74 |
75 | ### Decoding
76 |
77 | There are 2 ways to decode:
78 |
79 | * __asynchronous__ using nodejs Streams - slowest but can handle very large data sets (no memory limitations)
80 | * __synchronous__ by feeding the whole LZ4 data - faster but is limited by the amount of memory
81 |
82 |
83 | #### Asynchronous decoding
84 |
85 | First, create an LZ4 decoding NodeJS stream with `LZ4#createDecoderStream(options)`.
86 |
87 | * `options.chunkSize` (_Number_): chunk size to use (default=8Mb) (optional)
88 | * `options.outputSize` (_Number_): number of bytes for the output buffer (default=`chunkSize`) (optional)
89 |
90 |
91 | The stream can then decode any data piped to it. It will emit a `data` event on each decoded sequence, which can be saved into an output stream.
92 |
93 | The following example shows how to decode an LZ4 compressed file `test.lz4` into `test`.
94 |
95 |
96 | ```javascript
97 | var fs = require('fs')
98 | var lz4 = require('lz4')
99 |
100 | var decoder = lz4.createDecoderStream()
101 |
102 | var input = fs.createReadStream('test.lz4')
103 | var output = fs.createWriteStream('test')
104 |
105 | input.pipe(decoder).pipe(output)
106 |
107 | ```
108 |
109 | #### Synchronous decoding
110 |
111 | Read the data into memory and feed it to `LZ4#decode(input)` to produce an LZ4 stream.
112 |
113 | * `input` (_Buffer_): data to decode
114 |
115 |
116 | ```javascript
117 | var fs = require('fs')
118 | var lz4 = require('lz4')
119 |
120 | var input = fs.readFileSync('test.lz4')
121 | var output = lz4.decode(input)
122 |
123 | fs.writeFileSync('test', output)
124 |
125 | ```
126 |
127 |
128 | ## How it works
129 |
130 | * [LZ4 stream format](http://fastcompression.blogspot.fr/2011/05/lz4-explained.html)
131 |
132 | ## Restrictions / Issues
133 |
134 | * LZ4 streams have only been tested using `bin/lz4demo32`, not `bin/lz4demo64`.
135 |
136 | ## License
137 |
138 | MIT# LZ4
139 |
140 | [LZ4](http://fastcompression.blogspot.fr/) is a very fast compression and decompression algorithm. This nodejs module provides a Javascript implementation of the decoder as well as native bindings to the LZ4 functions. Nodejs Streams are also supported for compression and decompression.
141 |
142 |
143 | ## Install
144 |
145 | npm install lz4
146 |
147 |
148 | ## Usage
149 |
150 | ### Encoding
151 |
152 | There are 2 ways to encode:
153 |
154 | * __asynchronous__ using nodejs Streams - slowest but can handle very large data sets (no memory limitations).
155 | * __synchronous__ by feeding the whole set of data - faster but is limited by the amount of memory
156 |
157 |
158 | #### Asynchronous encoding
159 |
160 | First, create an LZ4 encoding NodeJS stream with `LZ4#createEncoderStream(options)`.
161 |
162 | * `options.chunkSize` (_Number_): chunk size to use (default=8Mb) (optional)
163 | * `options.hc` (_Boolean_): use high compression (default=false) (optional)
164 |
165 |
166 | The stream can then encode any data piped to it. It will emit a `data` event on each encoded chunk, which can be saved into an output stream.
167 |
168 | The following example shows how to encode a file `test` into `test.lz4`.
169 |
170 |
171 | ```javascript
172 | var fs = require('fs')
173 | var lz4 = require('lz4')
174 |
175 | var encoder = lz4.createEncoderStream()
176 |
177 | var input = fs.createReadStream('test')
178 | var output = fs.createWriteStream('test.lz4')
179 |
180 | input.pipe(encoder).pipe(output)
181 |
182 | ```
183 |
184 | #### Synchronous encoding
185 |
186 | Read the data into memory and feed it to `LZ4#encode(input[, options])` to decode an LZ4 stream.
187 |
188 | * `input` (_Buffer_): data to encode
189 | * `options` (_Object_): LZ4 stream options (optional)
190 | * `options.blockMaxSize` (_Number_): chunk size to use (default=4Mb)
191 | * `options.highCompression` (_Boolean_): use high compression (default=false)
192 | * `options.blockIndependence` (_Boolean_): (default=true)
193 | * `options.blockChecksum` (_Boolean_): add compressed blocks checksum (default=false)
194 | * `options.streamSize` (_Boolean_): add full LZ4 stream size (default=false)
195 | * `options.streamChecksum` (_Boolean_): add full LZ4 stream checksum (default=true)
196 | * `options.dict` (_Boolean_): use dictionary (default=false)
197 | * `options.dictId` (_Integer_): dictionary id (default=0)
198 |
199 |
200 | ```javascript
201 | var fs = require('fs')
202 | var lz4 = require('lz4')
203 |
204 | var input = fs.readFileSync('test')
205 | var output = lz4.encode(input)
206 |
207 | fs.writeFileSync('test.lz4', output)
208 |
209 | ```
210 |
211 |
212 | ### Decoding
213 |
214 | There are 2 ways to decode:
215 |
216 | * __asynchronous__ using nodejs Streams - slowest but can handle very large data sets (no memory limitations)
217 | * __synchronous__ by feeding the whole LZ4 data - faster but is limited by the amount of memory
218 |
219 |
220 | #### Asynchronous decoding
221 |
222 | First, create an LZ4 decoding NodeJS stream with `LZ4#createDecoderStream(options)`.
223 |
224 | * `options.chunkSize` (_Number_): chunk size to use (default=8Mb) (optional)
225 | * `options.outputSize` (_Number_): number of bytes for the output buffer (default=`chunkSize`) (optional)
226 |
227 |
228 | The stream can then decode any data piped to it. It will emit a `data` event on each decoded sequence, which can be saved into an output stream.
229 |
230 | The following example shows how to decode an LZ4 compressed file `test.lz4` into `test`.
231 |
232 |
233 | ```javascript
234 | var fs = require('fs')
235 | var lz4 = require('lz4')
236 |
237 | var decoder = lz4.createDecoderStream()
238 |
239 | var input = fs.createReadStream('test.lz4')
240 | var output = fs.createWriteStream('test')
241 |
242 | input.pipe(decoder).pipe(output)
243 |
244 | ```
245 |
246 | #### Synchronous decoding
247 |
248 | Read the data into memory and feed it to `LZ4#decode(input)` to produce an LZ4 stream.
249 |
250 | * `input` (_Buffer_): data to decode
251 |
252 |
253 | ```javascript
254 | var fs = require('fs')
255 | var lz4 = require('lz4')
256 |
257 | var input = fs.readFileSync('test.lz4')
258 | var output = lz4.decode(input)
259 |
260 | fs.writeFileSync('test', output)
261 |
262 | ```
263 |
264 |
265 | ## How it works
266 |
267 | * [LZ4 stream format](http://fastcompression.blogspot.fr/2011/05/lz4-explained.html)
268 |
269 | ## Restrictions / Issues
270 |
271 | * LZ4 streams have only been tested using `bin/lz4demo32`, not `bin/lz4demo64`.
272 |
273 | ## License
274 |
275 | MIT# LZ4
276 |
277 | [LZ4](http://fastcompression.blogspot.fr/) is a very fast compression and decompression algorithm. This nodejs module provides a Javascript implementation of the decoder as well as native bindings to the LZ4 functions. Nodejs Streams are also supported for compression and decompression.
278 |
279 |
280 | ## Install
281 |
282 | npm install lz4
283 |
284 |
285 | ## Usage
286 |
287 | ### Encoding
288 |
289 | There are 2 ways to encode:
290 |
291 | * __asynchronous__ using nodejs Streams - slowest but can handle very large data sets (no memory limitations).
292 | * __synchronous__ by feeding the whole set of data - faster but is limited by the amount of memory
293 |
294 |
295 | #### Asynchronous encoding
296 |
297 | First, create an LZ4 encoding NodeJS stream with `LZ4#createEncoderStream(options)`.
298 |
299 | * `options.chunkSize` (_Number_): chunk size to use (default=8Mb) (optional)
300 | * `options.hc` (_Boolean_): use high compression (default=false) (optional)
301 |
302 |
303 | The stream can then encode any data piped to it. It will emit a `data` event on each encoded chunk, which can be saved into an output stream.
304 |
305 | The following example shows how to encode a file `test` into `test.lz4`.
306 |
307 |
308 | ```javascript
309 | var fs = require('fs')
310 | var lz4 = require('lz4')
311 |
312 | var encoder = lz4.createEncoderStream()
313 |
314 | var input = fs.createReadStream('test')
315 | var output = fs.createWriteStream('test.lz4')
316 |
317 | input.pipe(encoder).pipe(output)
318 |
319 | ```
320 |
321 | #### Synchronous encoding
322 |
323 | Read the data into memory and feed it to `LZ4#encode(input[, options])` to decode an LZ4 stream.
324 |
325 | * `input` (_Buffer_): data to encode
326 | * `options` (_Object_): LZ4 stream options (optional)
327 | * `options.blockMaxSize` (_Number_): chunk size to use (default=4Mb)
328 | * `options.highCompression` (_Boolean_): use high compression (default=false)
329 | * `options.blockIndependence` (_Boolean_): (default=true)
330 | * `options.blockChecksum` (_Boolean_): add compressed blocks checksum (default=false)
331 | * `options.streamSize` (_Boolean_): add full LZ4 stream size (default=false)
332 | * `options.streamChecksum` (_Boolean_): add full LZ4 stream checksum (default=true)
333 | * `options.dict` (_Boolean_): use dictionary (default=false)
334 | * `options.dictId` (_Integer_): dictionary id (default=0)
335 |
336 |
337 | ```javascript
338 | var fs = require('fs')
339 | var lz4 = require('lz4')
340 |
341 | var input = fs.readFileSync('test')
342 | var output = lz4.encode(input)
343 |
344 | fs.writeFileSync('test.lz4', output)
345 |
346 | ```
347 |
348 |
349 | ### Decoding
350 |
351 | There are 2 ways to decode:
352 |
353 | * __asynchronous__ using nodejs Streams - slowest but can handle very large data sets (no memory limitations)
354 | * __synchronous__ by feeding the whole LZ4 data - faster but is limited by the amount of memory
355 |
356 |
357 | #### Asynchronous decoding
358 |
359 | First, create an LZ4 decoding NodeJS stream with `LZ4#createDecoderStream(options)`.
360 |
361 | * `options.chunkSize` (_Number_): chunk size to use (default=8Mb) (optional)
362 | * `options.outputSize` (_Number_): number of bytes for the output buffer (default=`chunkSize`) (optional)
363 |
364 |
365 | The stream can then decode any data piped to it. It will emit a `data` event on each decoded sequence, which can be saved into an output stream.
366 |
367 | The following example shows how to decode an LZ4 compressed file `test.lz4` into `test`.
368 |
369 |
370 | ```javascript
371 | var fs = require('fs')
372 | var lz4 = require('lz4')
373 |
374 | var decoder = lz4.createDecoderStream()
375 |
376 | var input = fs.createReadStream('test.lz4')
377 | var output = fs.createWriteStream('test')
378 |
379 | input.pipe(decoder).pipe(output)
380 |
381 | ```
382 |
383 | #### Synchronous decoding
384 |
385 | Read the data into memory and feed it to `LZ4#decode(input)` to produce an LZ4 stream.
386 |
387 | * `input` (_Buffer_): data to decode
388 |
389 |
390 | ```javascript
391 | var fs = require('fs')
392 | var lz4 = require('lz4')
393 |
394 | var input = fs.readFileSync('test.lz4')
395 | var output = lz4.decode(input)
396 |
397 | fs.writeFileSync('test', output)
398 |
399 | ```
400 |
401 |
402 | ## How it works
403 |
404 | * [LZ4 stream format](http://fastcompression.blogspot.fr/2011/05/lz4-explained.html)
405 |
406 | ## Restrictions / Issues
407 |
408 | * LZ4 streams have only been tested using `bin/lz4demo32`, not `bin/lz4demo64`.
409 |
410 | ## License
411 |
412 | MIT# LZ4
413 |
414 | [LZ4](http://fastcompression.blogspot.fr/) is a very fast compression and decompression algorithm. This nodejs module provides a Javascript implementation of the decoder as well as native bindings to the LZ4 functions. Nodejs Streams are also supported for compression and decompression.
415 |
416 |
417 | ## Install
418 |
419 | npm install lz4
420 |
421 |
422 | ## Usage
423 |
424 | ### Encoding
425 |
426 | There are 2 ways to encode:
427 |
428 | * __asynchronous__ using nodejs Streams - slowest but can handle very large data sets (no memory limitations).
429 | * __synchronous__ by feeding the whole set of data - faster but is limited by the amount of memory
430 |
431 |
432 | #### Asynchronous encoding
433 |
434 | First, create an LZ4 encoding NodeJS stream with `LZ4#createEncoderStream(options)`.
435 |
436 | * `options.chunkSize` (_Number_): chunk size to use (default=8Mb) (optional)
437 | * `options.hc` (_Boolean_): use high compression (default=false) (optional)
438 |
439 |
440 | The stream can then encode any data piped to it. It will emit a `data` event on each encoded chunk, which can be saved into an output stream.
441 |
442 | The following example shows how to encode a file `test` into `test.lz4`.
443 |
444 |
445 | ```javascript
446 | var fs = require('fs')
447 | var lz4 = require('lz4')
448 |
449 | var encoder = lz4.createEncoderStream()
450 |
451 | var input = fs.createReadStream('test')
452 | var output = fs.createWriteStream('test.lz4')
453 |
454 | input.pipe(encoder).pipe(output)
455 |
456 | ```
457 |
458 | #### Synchronous encoding
459 |
460 | Read the data into memory and feed it to `LZ4#encode(input[, options])` to decode an LZ4 stream.
461 |
462 | * `input` (_Buffer_): data to encode
463 | * `options` (_Object_): LZ4 stream options (optional)
464 | * `options.blockMaxSize` (_Number_): chunk size to use (default=4Mb)
465 | * `options.highCompression` (_Boolean_): use high compression (default=false)
466 | * `options.blockIndependence` (_Boolean_): (default=true)
467 | * `options.blockChecksum` (_Boolean_): add compressed blocks checksum (default=false)
468 | * `options.streamSize` (_Boolean_): add full LZ4 stream size (default=false)
469 | * `options.streamChecksum` (_Boolean_): add full LZ4 stream checksum (default=true)
470 | * `options.dict` (_Boolean_): use dictionary (default=false)
471 | * `options.dictId` (_Integer_): dictionary id (default=0)
472 |
473 |
474 | ```javascript
475 | var fs = require('fs')
476 | var lz4 = require('lz4')
477 |
478 | var input = fs.readFileSync('test')
479 | var output = lz4.encode(input)
480 |
481 | fs.writeFileSync('test.lz4', output)
482 |
483 | ```
484 |
485 |
486 | ### Decoding
487 |
488 | There are 2 ways to decode:
489 |
490 | * __asynchronous__ using nodejs Streams - slowest but can handle very large data sets (no memory limitations)
491 | * __synchronous__ by feeding the whole LZ4 data - faster but is limited by the amount of memory
492 |
493 |
494 | #### Asynchronous decoding
495 |
496 | First, create an LZ4 decoding NodeJS stream with `LZ4#createDecoderStream(options)`.
497 |
498 | * `options.chunkSize` (_Number_): chunk size to use (default=8Mb) (optional)
499 | * `options.outputSize` (_Number_): number of bytes for the output buffer (default=`chunkSize`) (optional)
500 |
501 |
502 | The stream can then decode any data piped to it. It will emit a `data` event on each decoded sequence, which can be saved into an output stream.
503 |
504 | The following example shows how to decode an LZ4 compressed file `test.lz4` into `test`.
505 |
506 |
507 | ```javascript
508 | var fs = require('fs')
509 | var lz4 = require('lz4')
510 |
511 | var decoder = lz4.createDecoderStream()
512 |
513 | var input = fs.createReadStream('test.lz4')
514 | var output = fs.createWriteStream('test')
515 |
516 | input.pipe(decoder).pipe(output)
517 |
518 | ```
519 |
520 | #### Synchronous decoding
521 |
522 | Read the data into memory and feed it to `LZ4#decode(input)` to produce an LZ4 stream.
523 |
524 | * `input` (_Buffer_): data to decode
525 |
526 |
527 | ```javascript
528 | var fs = require('fs')
529 | var lz4 = require('lz4')
530 |
531 | var input = fs.readFileSync('test.lz4')
532 | var output = lz4.decode(input)
533 |
534 | fs.writeFileSync('test', output)
535 |
536 | ```
537 |
538 |
539 | ## How it works
540 |
541 | * [LZ4 stream format](http://fastcompression.blogspot.fr/2011/05/lz4-explained.html)
542 |
543 | ## Restrictions / Issues
544 |
545 | * LZ4 streams have only been tested using `bin/lz4demo32`, not `bin/lz4demo64`.
546 |
547 | ## License
548 |
549 | MIT
--------------------------------------------------------------------------------
/data/test_medium.lz4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pierrec/node-lz4/943e768691a9fb29e2d9a88f9942463765a45468/data/test_medium.lz4
--------------------------------------------------------------------------------
/data/test_smallchunk.lz4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pierrec/node-lz4/943e768691a9fb29e2d9a88f9942463765a45468/data/test_smallchunk.lz4
--------------------------------------------------------------------------------
/doc/format.txt:
--------------------------------------------------------------------------------
1 | lz4 format
2 |
3 | sequence = token(1) + literalslen(i) + literals(token >> 4 + i) + [match copy: offset(2) + length(token >> 4 << 4)]
4 |
5 | match copy:
6 | position = current postition - offset (0 is invalid)
7 | length = 4 + length
8 |
9 | last 5 bytes = literals
10 | last match starts 12 bytes before end of stream
11 | last sequence is incomplete and stops after the literals
--------------------------------------------------------------------------------
/examples/compress.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | LZ4 compress
4 |
5 |
6 |
7 |
40 |
41 |
42 |
Input data
43 |
44 |
45 |
46 |
47 |
Encode
48 |
49 |
50 |
Compressed data
51 |
52 |
53 |
54 |
55 |
56 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/examples/cu.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/examples/file_compress.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Compress a stream
3 | */
4 | // Modules
5 | var path = require('path')
6 | var fs = require('fs')
7 | var lz4 = require('..')
8 |
9 | // Input/Output files
10 | var inputFile = process.argv[2] || 'test'
11 | var outputFile = process.argv[3] || inputFile + lz4.extension
12 |
13 | var encoder = lz4.createEncoderStream()
14 |
15 | var input = fs.createReadStream( inputFile )
16 | var output = fs.createWriteStream( outputFile )
17 |
18 |
19 | // Timing
20 | encoder.on('end', function () {
21 | var fileSize = fs.statSync(inputFile).size
22 | var delta = Date.now() - startTime
23 | console.log(
24 | 'lz4 compressed %d bytes in %dms (%dMb/s)'
25 | , fileSize
26 | , delta
27 | , Math.round( 100 * fileSize / ( delta * (1 << 20) ) * 1000 ) / 100
28 | )
29 | })
30 |
31 | console.log('Compressing %s to %s...', inputFile, outputFile)
32 | var startTime = Date.now()
33 | input.pipe(encoder).pipe(output)
--------------------------------------------------------------------------------
/examples/file_compressBlock.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Compress data into a block (no archive format)
3 | */
4 | // Modules
5 | var path = require('path')
6 | var fs = require('fs')
7 | var lz4 = require('..')
8 |
9 | // Input/Output files
10 | var inputFile = process.argv[2] || 'test'
11 | var outputFile = process.argv[3] || inputFile + lz4.extension
12 |
13 | var input = fs.readFileSync( inputFile )
14 | // Allocate max block size, __to be sliced__ accordingly after compression
15 | var output = Buffer.alloc( lz4.encodeBound(input.length) )
16 |
17 | console.log('Compressing %s to %s...', inputFile, outputFile)
18 | var startTime = Date.now()
19 |
20 | // encodeBlock is synchronous
21 | // native
22 | var compressedBlockSize = lz4.encodeBlock(input, output)
23 | // javascript
24 | //var compressedBlockSize = require('../lib/binding').compress(input, output)
25 |
26 | // Timing
27 | var delta = Date.now() - startTime
28 |
29 | if (compressedBlockSize > 0) {
30 | var fileSize = fs.statSync(inputFile).size
31 | console.log(
32 | 'lz4 block compressed %d bytes into %d bytes in %dms (%dMb/s)'
33 | , fileSize
34 | , compressedBlockSize
35 | , delta
36 | , delta > 0 ? Math.round( 100 * fileSize / ( delta * (1 << 20) ) * 1000 ) / 100 : 0
37 | )
38 | output = output.slice(0, compressedBlockSize)
39 | } else {
40 | console.log('data could not be compressed')
41 | output = input
42 | }
43 |
44 | fs.writeFileSync( outputFile, output )
45 |
--------------------------------------------------------------------------------
/examples/file_compressHC.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Compress a stream
3 | */
4 | // Modules
5 | var path = require('path')
6 | var fs = require('fs')
7 | var lz4 = require('..')
8 |
9 | // Input/Output files
10 | var inputFile = process.argv[2] || 'test'
11 | var outputFile = process.argv[3] || inputFile + lz4.extension
12 |
13 | var encoder = lz4.createEncoderStream({ highCompression: true })
14 |
15 | var input = fs.createReadStream( inputFile )
16 | var output = fs.createWriteStream( outputFile )
17 |
18 | // Timing
19 | encoder.on('end', function () {
20 | var delta = Date.now() - startTime
21 | var fileSize = fs.statSync(inputFile).size
22 | var outfileSize = fs.statSync(outputFile).size
23 | console.log(
24 | 'lz4 compressed %d bytes into %d bytes in %dms (%dMb/s)'
25 | , fileSize
26 | , outfileSize
27 | , delta
28 | , Math.round( 100 * fileSize / ( delta * (1 << 20) ) * 1000 ) / 100
29 | )
30 | })
31 |
32 | console.log('Compressing %s to %s...', inputFile, outputFile)
33 | var startTime = Date.now()
34 | input.pipe(encoder).pipe(output)
--------------------------------------------------------------------------------
/examples/file_compressHCSync.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Compress a Buffer
3 | */
4 | // Modules
5 | var path = require('path')
6 | var fs = require('fs')
7 | var lz4 = require('..')
8 |
9 | // Input/Output files
10 | var inputFile = process.argv[2] || 'test'
11 | var outputFile = process.argv[3] || inputFile + lz4.extension
12 |
13 | // Load the data
14 | var input = fs.readFileSync( inputFile )
15 |
16 | // Timing
17 | console.log('Compressing %s to %s...', inputFile, outputFile)
18 | var startTime = Date.now()
19 | var compressed = lz4.encode(input, { highCompression: true })
20 | var fileSize = fs.statSync(inputFile).size
21 | var outfileSize = fs.statSync(outputFile).size
22 | var delta = Date.now() - startTime
23 | console.log(
24 | 'lz4 compressed %d bytes into %d bytes in %dms (%dMb/s)'
25 | , fileSize
26 | , outfileSize
27 | , delta
28 | , Math.round( 100 * fileSize / ( delta * (1 << 20) ) * 1000 ) / 100
29 | )
30 |
31 | // Save the uncompressed data
32 | fs.writeFileSync( outputFile, compressed )
--------------------------------------------------------------------------------
/examples/file_compressJS.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Compress a stream using Javascript only
3 | */
4 | // Modules
5 | var path = require('path')
6 | var fs = require('fs')
7 | var lz4 = require('..')
8 |
9 | // Input/Output files
10 | var inputFile = process.argv[2] || 'test'
11 | var outputFile = process.argv[3] || inputFile + lz4.extension
12 |
13 | var encoder = lz4.createEncoderStream({ useJS: true })
14 |
15 | var input = fs.createReadStream( inputFile )
16 | var output = fs.createWriteStream( outputFile )
17 |
18 |
19 | // Timing
20 | encoder.on('end', function () {
21 | var fileSize = fs.statSync(inputFile).size
22 | var delta = Date.now() - startTime
23 | console.log(
24 | 'lz4 compressed %d bytes in %dms (%dMb/s)'
25 | , fileSize
26 | , delta
27 | , Math.round( 100 * fileSize / ( delta * (1 << 20) ) * 1000 ) / 100
28 | )
29 | })
30 |
31 | console.log('Compressing using Javascript %s to %s...', inputFile, outputFile)
32 | var startTime = Date.now()
33 | input.pipe(encoder).pipe(output)
--------------------------------------------------------------------------------
/examples/file_compressSync.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Compress a Buffer
3 | */
4 | // Modules
5 | var path = require('path')
6 | var fs = require('fs')
7 | var lz4 = require('..')
8 |
9 | // Input/Output files
10 | var inputFile = process.argv[2] || 'test'
11 | var outputFile = process.argv[3] || inputFile + lz4.extension
12 |
13 | // Load the data
14 | var input = fs.readFileSync( inputFile )
15 |
16 | // Timing
17 |
18 | console.log('Compressing %s to %s...', inputFile, outputFile)
19 | var startTime = Date.now()
20 | var compressed = lz4.encode(input)
21 | var delta = Date.now() - startTime
22 | var fileSize = fs.statSync(inputFile).size
23 | console.log(
24 | 'lz4 compressed %d bytes in %dms (%dMb/s)'
25 | , fileSize
26 | , delta
27 | , Math.round( 100 * fileSize / ( delta * (1 << 20) ) * 1000 ) / 100
28 | )
29 |
30 | // Save the uncompressed data
31 | fs.writeFileSync( outputFile, compressed )
--------------------------------------------------------------------------------
/examples/file_uncompress.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Uncompress an LZ4 stream
3 | */
4 | // Modules
5 | var path = require('path')
6 | var fs = require('fs')
7 | var lz4 = require('..')
8 |
9 | // Input/Output files
10 | var inputFile = process.argv[2] || 'test.lz4'
11 | var outputFile = process.argv[3] || path.basename(inputFile, lz4.extension)
12 |
13 | var decoder = lz4.createDecoderStream()
14 |
15 | // Higher buffer size increases performance
16 | var input = fs.createReadStream( inputFile, { highWaterMark: 4 << 20 } )
17 | var output = fs.createWriteStream( outputFile )
18 |
19 | // Timing
20 | var startTime = Date.now()
21 | var fileSize = fs.statSync(inputFile).size
22 | decoder.on('end', function () {
23 | var delta = Date.now() - startTime
24 | console.log(
25 | 'lz4 decompressed %d bytes in %dms (%dMb/s)'
26 | , fileSize
27 | , delta
28 | , Math.round( 100 * fileSize / ( delta * (1 << 20) ) * 1000 ) / 100
29 | )
30 | })
31 |
32 | console.log('Uncompressing %s to %s...', inputFile, outputFile)
33 | input.pipe(decoder).pipe(output)
--------------------------------------------------------------------------------
/examples/file_uncompressBlock.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Uncompress data block (no archive format)
3 | */
4 | // Modules
5 | var path = require('path')
6 | var fs = require('fs')
7 | var lz4 = require('..')
8 |
9 | // Input/Output files
10 | var inputFile = process.argv[2] || 'test'
11 | var outputFile = process.argv[3] || path.basename(inputFile, lz4.extension)
12 |
13 | var input = fs.readFileSync( inputFile )
14 | // Allocate output size... randomly :s
15 | var output = Buffer.alloc( input.length * 3 )
16 |
17 | console.log('Uncompressing %s to %s...', inputFile, outputFile)
18 | var startTime = Date.now()
19 |
20 | // decodeBlock is synchronous
21 | // native
22 | // var uncompressedBlockSize = lz4.decodeBlock(input, output)
23 | // javascript
24 | var uncompressedBlockSize = require('../lib/binding').uncompress(input, output)
25 |
26 | // Timing
27 | var delta = Date.now() - startTime
28 |
29 | if (uncompressedBlockSize > 0) {
30 | var fileSize = fs.statSync(inputFile).size
31 | console.log(
32 | 'lz4 block uncompressed %d bytes into %d bytes in %dms (%dMb/s)'
33 | , fileSize
34 | , uncompressedBlockSize
35 | , delta
36 | , delta > 0 ? Math.round( 100 * fileSize / ( delta * (1 << 20) ) * 1000 ) / 100 : 0
37 | )
38 | fs.writeFileSync( outputFile, output.slice(0, uncompressedBlockSize) )
39 | } else {
40 | console.log('data could not be uncompressed')
41 | }
42 |
--------------------------------------------------------------------------------
/examples/file_uncompressJS.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Uncompress an LZ4 stream using Javascript
3 | */
4 | // Modules
5 | var path = require('path')
6 | var fs = require('fs')
7 | var lz4 = require('..')
8 |
9 | // Input/Output files
10 | var inputFile = process.argv[2] || 'test.lz4'
11 | var outputFile = process.argv[3] || path.basename(inputFile, lz4.extension)
12 |
13 | var decoder = lz4.createDecoderStream({ useJS: true })
14 |
15 | // Higher buffer size increases performance
16 | var input = fs.createReadStream( inputFile, { highWaterMark: 4 << 20 } )
17 | var output = fs.createWriteStream( outputFile )
18 |
19 | // Timing
20 | var startTime = Date.now()
21 | var fileSize = fs.statSync(inputFile).size
22 | decoder.on('end', function () {
23 | var delta = Date.now() - startTime
24 | console.log(
25 | 'lz4 decompressed %d bytes in %dms (%dMb/s)'
26 | , fileSize
27 | , delta
28 | , Math.round( 100 * fileSize / ( delta * (1 << 20) ) * 1000 ) / 100
29 | )
30 | })
31 |
32 | console.log('Uncompressing using Javascript %s to %s...', inputFile, outputFile)
33 | input.pipe(decoder).pipe(output)
--------------------------------------------------------------------------------
/examples/file_uncompressSync.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Uncompress a Buffer containing LZ4 compressed data
3 | */
4 | // Modules
5 | var path = require('path')
6 | var fs = require('fs')
7 | var lz4 = require('..')
8 |
9 | // Input/Output files
10 | var inputFile = process.argv[2] || 'test.lz4'
11 | var outputFile = process.argv[3] || path.basename(inputFile, lz4.extension)
12 |
13 | // Load the compressed data
14 | var input = fs.readFileSync( inputFile )
15 |
16 | // Timing
17 | var startTime = Date.now()
18 | console.log('Uncompressing %s to %s...', inputFile, outputFile)
19 | var decoded = lz4.decode( input )
20 | var delta = Date.now() - startTime
21 |
22 | var fileSize = fs.statSync(inputFile).size
23 | console.log(
24 | 'lz4 decompressed %d bytes in %dms (%dMb/s)'
25 | , fileSize
26 | , delta
27 | , Math.round( 100 * fileSize / ( delta * (1 << 20) ) * 1000 ) / 100
28 | )
29 |
30 | // Save the uncompressed data
31 | fs.writeFileSync( outputFile, decoded )
--------------------------------------------------------------------------------
/examples/uncompress.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | LZ4 uncompress
4 |
5 |
6 |
7 |
21 |
22 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | module.exports = function(config) {
2 | config.set({
3 |
4 | // base path, that will be used to resolve files and exclude
5 | basePath: '',
6 |
7 | // frameworks to use
8 | frameworks: ['jasmine'],
9 |
10 | // list of files / patterns to load in the browser
11 | files: [
12 | 'build/lz4.js',
13 | 'test/browser/**/*.js',
14 | { pattern: 'data/**/*', included: false, serve: true}
15 | ],
16 |
17 | // test results reporter to use
18 | // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
19 | reporters: ['progress'],
20 |
21 | // web server port
22 | port: 9876,
23 |
24 | // enable / disable colors in the output (reporters and logs)
25 | colors: true,
26 |
27 | // level of logging
28 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
29 | logLevel: config.LOG_DEBUG,
30 |
31 | // enable / disable watching file and executing tests whenever any file changes
32 | autoWatch: true,
33 |
34 | // Start these browsers, currently available:
35 | // - Chrome
36 | // - ChromeCanary
37 | // - Firefox
38 | // - Opera (has to be installed with `npm install karma-opera-launcher`)
39 | // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
40 | // - PhantomJS
41 | // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
42 | browsers: ['Chrome','Firefox'],
43 |
44 | // If browser does not capture in given timeout [ms], kill it
45 | captureTimeout: 60000,
46 |
47 | // Continuous Integration mode
48 | // if true, it capture browsers, run tests and exit
49 | singleRun: false
50 | });
51 | };
52 |
--------------------------------------------------------------------------------
/lib/binding.js:
--------------------------------------------------------------------------------
1 | /**
2 | Javascript version of the key LZ4 C functions
3 | */
4 | var uint32 = require('cuint').UINT32
5 |
6 | if (!Math.imul) Math.imul = function imul(a, b) {
7 | var ah = a >>> 16;
8 | var al = a & 0xffff;
9 | var bh = b >>> 16;
10 | var bl = b & 0xffff;
11 | return (al*bl + ((ah*bl + al*bh) << 16))|0;
12 | };
13 |
14 | /**
15 | * Decode a block. Assumptions: input contains all sequences of a
16 | * chunk, output is large enough to receive the decoded data.
17 | * If the output buffer is too small, an error will be thrown.
18 | * If the returned value is negative, an error occured at the returned offset.
19 | *
20 | * @param input {Buffer} input data
21 | * @param output {Buffer} output data
22 | * @return {Number} number of decoded bytes
23 | * @private
24 | */
25 | exports.uncompress = function (input, output, sIdx, eIdx) {
26 | sIdx = sIdx || 0
27 | eIdx = eIdx || (input.length - sIdx)
28 | // Process each sequence in the incoming data
29 | for (var i = sIdx, n = eIdx, j = 0; i < n;) {
30 | var token = input[i++]
31 |
32 | // Literals
33 | var literals_length = (token >> 4)
34 | if (literals_length > 0) {
35 | // length of literals
36 | var l = literals_length + 240
37 | while (l === 255) {
38 | l = input[i++]
39 | literals_length += l
40 | }
41 |
42 | // Copy the literals
43 | var end = i + literals_length
44 | while (i < end) output[j++] = input[i++]
45 |
46 | // End of buffer?
47 | if (i === n) return j
48 | }
49 |
50 | // Match copy
51 | // 2 bytes offset (little endian)
52 | var offset = input[i++] | (input[i++] << 8)
53 |
54 | // 0 is an invalid offset value
55 | if (offset === 0 || offset > j) return -(i-2)
56 |
57 | // length of match copy
58 | var match_length = (token & 0xf)
59 | var l = match_length + 240
60 | while (l === 255) {
61 | l = input[i++]
62 | match_length += l
63 | }
64 |
65 | // Copy the match
66 | var pos = j - offset // position of the match copy in the current output
67 | var end = j + match_length + 4 // minmatch = 4
68 | while (j < end) output[j++] = output[pos++]
69 | }
70 |
71 | return j
72 | }
73 |
74 | var
75 | maxInputSize = 0x7E000000
76 | , minMatch = 4
77 | // uint32() optimization
78 | , hashLog = 16
79 | , hashShift = (minMatch * 8) - hashLog
80 | , hashSize = 1 << hashLog
81 |
82 | , copyLength = 8
83 | , lastLiterals = 5
84 | , mfLimit = copyLength + minMatch
85 | , skipStrength = 6
86 |
87 | , mlBits = 4
88 | , mlMask = (1 << mlBits) - 1
89 | , runBits = 8 - mlBits
90 | , runMask = (1 << runBits) - 1
91 |
92 | , hasher = 2654435761
93 |
94 | // CompressBound returns the maximum length of a lz4 block, given it's uncompressed length
95 | exports.compressBound = function (isize) {
96 | return isize > maxInputSize
97 | ? 0
98 | : (isize + (isize/255) + 16) | 0
99 | }
100 |
101 | exports.compress = function (src, dst, sIdx, eIdx) {
102 | // V8 optimization: non sparse array with integers
103 | var hashTable = new Array(hashSize)
104 | for (var i = 0; i < hashSize; i++) {
105 | hashTable[i] = 0
106 | }
107 | return compressBlock(src, dst, 0, hashTable, sIdx || 0, eIdx || dst.length)
108 | }
109 |
110 | exports.compressHC = exports.compress
111 |
112 | exports.compressDependent = compressBlock
113 |
114 | function compressBlock (src, dst, pos, hashTable, sIdx, eIdx) {
115 | var dpos = sIdx
116 | var dlen = eIdx - sIdx
117 | var anchor = 0
118 |
119 | if (src.length >= maxInputSize) throw new Error("input too large")
120 |
121 | // Minimum of input bytes for compression (LZ4 specs)
122 | if (src.length > mfLimit) {
123 | var n = exports.compressBound(src.length)
124 | if ( dlen < n ) throw Error("output too small: " + dlen + " < " + n)
125 |
126 | var
127 | step = 1
128 | , findMatchAttempts = (1 << skipStrength) + 3
129 | // Keep last few bytes incompressible (LZ4 specs):
130 | // last 5 bytes must be literals
131 | , srcLength = src.length - mfLimit
132 |
133 | while (pos + minMatch < srcLength) {
134 | // Find a match
135 | // min match of 4 bytes aka sequence
136 | var sequenceLowBits = src[pos+1]<<8 | src[pos]
137 | var sequenceHighBits = src[pos+3]<<8 | src[pos+2]
138 | // compute hash for the current sequence
139 | var hash = Math.imul(sequenceLowBits | (sequenceHighBits << 16), hasher) >>> hashShift
140 | // get the position of the sequence matching the hash
141 | // NB. since 2 different sequences may have the same hash
142 | // it is double-checked below
143 | // do -1 to distinguish between initialized and uninitialized values
144 | var ref = hashTable[hash] - 1
145 | // save position of current sequence in hash table
146 | hashTable[hash] = pos + 1
147 |
148 | // first reference or within 64k limit or current sequence !== hashed one: no match
149 | if ( ref < 0 ||
150 | ((pos - ref) >>> 16) > 0 ||
151 | (
152 | ((src[ref+3]<<8 | src[ref+2]) != sequenceHighBits) ||
153 | ((src[ref+1]<<8 | src[ref]) != sequenceLowBits )
154 | )
155 | ) {
156 | // increase step if nothing found within limit
157 | step = findMatchAttempts++ >> skipStrength
158 | pos += step
159 | continue
160 | }
161 |
162 | findMatchAttempts = (1 << skipStrength) + 3
163 |
164 | // got a match
165 | var literals_length = pos - anchor
166 | var offset = pos - ref
167 |
168 | // minMatch already verified
169 | pos += minMatch
170 | ref += minMatch
171 |
172 | // move to the end of the match (>=minMatch)
173 | var match_length = pos
174 | while (pos < srcLength && src[pos] == src[ref]) {
175 | pos++
176 | ref++
177 | }
178 |
179 | // match length
180 | match_length = pos - match_length
181 |
182 | // token
183 | var token = match_length < mlMask ? match_length : mlMask
184 |
185 | // encode literals length
186 | if (literals_length >= runMask) {
187 | // add match length to the token
188 | dst[dpos++] = (runMask << mlBits) + token
189 | for (var len = literals_length - runMask; len > 254; len -= 255) {
190 | dst[dpos++] = 255
191 | }
192 | dst[dpos++] = len
193 | } else {
194 | // add match length to the token
195 | dst[dpos++] = (literals_length << mlBits) + token
196 | }
197 |
198 | // write literals
199 | for (var i = 0; i < literals_length; i++) {
200 | dst[dpos++] = src[anchor+i]
201 | }
202 |
203 | // encode offset
204 | dst[dpos++] = offset
205 | dst[dpos++] = (offset >> 8)
206 |
207 | // encode match length
208 | if (match_length >= mlMask) {
209 | match_length -= mlMask
210 | while (match_length >= 255) {
211 | match_length -= 255
212 | dst[dpos++] = 255
213 | }
214 |
215 | dst[dpos++] = match_length
216 | }
217 |
218 | anchor = pos
219 | }
220 | }
221 |
222 | // cannot compress input
223 | if (anchor == 0) return 0
224 |
225 | // Write last literals
226 | // encode literals length
227 | literals_length = src.length - anchor
228 | if (literals_length >= runMask) {
229 | // add match length to the token
230 | dst[dpos++] = (runMask << mlBits)
231 | for (var ln = literals_length - runMask; ln > 254; ln -= 255) {
232 | dst[dpos++] = 255
233 | }
234 | dst[dpos++] = ln
235 | } else {
236 | // add match length to the token
237 | dst[dpos++] = (literals_length << mlBits)
238 | }
239 |
240 | // write literals
241 | pos = anchor
242 | while (pos < src.length) {
243 | dst[dpos++] = src[pos++]
244 | }
245 |
246 | return dpos
247 | }
248 |
--------------------------------------------------------------------------------
/lib/binding/lz4_binding.cc:
--------------------------------------------------------------------------------
1 | #define NAPI_VERSION 3
2 | #include
3 |
4 | #include "../../deps/lz4/lib/lz4.h"
5 | #include "../../deps/lz4/lib/lz4hc.h"
6 |
7 | //-----------------------------------------------------------------------------
8 | // LZ4 Compress
9 | //-----------------------------------------------------------------------------
10 | // Simple functions
11 |
12 | // {Buffer} input, {Buffer} output
13 | Napi::Value LZ4Compress(const Napi::CallbackInfo& info) {
14 | Napi::Env env = info.Env();
15 |
16 | uint32_t alen = info.Length();
17 | if (alen < 2 || alen > 4) {
18 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
19 | return env.Null();
20 | }
21 |
22 | if (!info[0].IsBuffer() || !info[1].IsBuffer()) {
23 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
24 | return env.Null();
25 | }
26 | Napi::Buffer input = info[0].As>();
27 | Napi::Buffer output = info[1].As>();
28 |
29 | Napi::Number result;
30 | uint32_t sIdx = 0;
31 | uint32_t eIdx = output.Length();
32 | switch (alen) {
33 | case 4:
34 | if (!info[3].IsNumber()) {
35 | Napi::TypeError::New(env, "Invalid endIdx").ThrowAsJavaScriptException();
36 | return env.Null();
37 | }
38 | eIdx = info[3].As().Uint32Value();
39 | // fall through
40 | [[fallthrough]];
41 | case 3:
42 | if (!info[2].IsNumber()) {
43 | Napi::TypeError::New(env, "Invalid startIdx").ThrowAsJavaScriptException();
44 | return env.Null();
45 | }
46 | sIdx = info[2].As().Uint32Value();
47 | // fall through
48 | [[fallthrough]];
49 | case 2:
50 | result = Napi::Number::New(env, LZ4_compress_default(input.Data(),
51 | output.Data() + sIdx,
52 | input.Length(),
53 | eIdx - sIdx)
54 | );
55 | }
56 |
57 | return result;
58 | }
59 |
60 | // {Buffer} input, {Buffer} output, {Integer} compressionLevel
61 | Napi::Value LZ4CompressHC(const Napi::CallbackInfo& info) {
62 | Napi::Env env = info.Env();
63 |
64 | uint32_t alen = info.Length();
65 | if (alen != 2 && alen != 3) {
66 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
67 | return env.Null();
68 | }
69 |
70 | if (!info[0].IsBuffer() || !info[1].IsBuffer()) {
71 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
72 | return env.Null();
73 | }
74 |
75 | Napi::Buffer input = info[0].As>();
76 | Napi::Buffer output = info[1].As>();
77 | uint32_t compressionLevel = info[2].IsNumber() ? info[2].As().Uint32Value() : 9;
78 |
79 | Napi::Number result = Napi::Number::New(env, LZ4_compress_HC(input.Data(),
80 | output.Data(),
81 | input.Length(),
82 | output.Length(),
83 | compressionLevel)
84 | );
85 | return result;
86 | }
87 |
88 | // Advanced functions
89 |
90 | // {Integer} Buffer size
91 | Napi::Value LZ4CompressBound(const Napi::CallbackInfo& info) {
92 | Napi::Env env = info.Env();
93 |
94 | if (info.Length() != 1) {
95 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
96 | return env.Null();
97 | }
98 |
99 | if (!info[0].IsNumber()) {
100 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
101 | return env.Null();
102 | }
103 |
104 | uint32_t size = info[0].As().Uint32Value();
105 |
106 | return Napi::Number::New(env, LZ4_compressBound(size));
107 | }
108 |
109 | // {Buffer} input, {Buffer} output, {Integer} maxOutputSize
110 | Napi::Value LZ4CompressLimited(const Napi::CallbackInfo& info) {
111 | Napi::Env env = info.Env();
112 |
113 | if (info.Length() != 3) {
114 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
115 | return env.Null();
116 | }
117 |
118 | if (!info[0].IsBuffer() || !info[1].IsBuffer()) {
119 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
120 | return env.Null();
121 | }
122 |
123 | if (!info[2].IsNumber()) {
124 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
125 | return env.Null();
126 | }
127 |
128 | Napi::Buffer input = info[0].As>();
129 | Napi::Buffer output = info[1].As>();
130 | uint32_t size = info[2].As().Uint32Value();
131 |
132 | Napi::Number result = Napi::Number::New(env, LZ4_compress_default(input.Data(),
133 | output.Data(),
134 | input.Length(),
135 | size)
136 | );
137 | return result;
138 | }
139 |
140 | // {Buffer} input, {Buffer} output, {Integer} maxOutputSize, {Integer} compressionLevel
141 | Napi::Value LZ4CompressHCLimited(const Napi::CallbackInfo& info) {
142 | Napi::Env env = info.Env();
143 |
144 | uint32_t alen = info.Length();
145 | if (alen != 3 && alen != 4) {
146 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
147 | return env.Null();
148 | }
149 |
150 | if (!info[0].IsBuffer() || !info[1].IsBuffer()) {
151 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
152 | return env.Null();
153 | }
154 |
155 | if (!info[2].IsNumber()) {
156 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
157 | return env.Null();
158 | }
159 |
160 | Napi::Buffer input = info[0].As>();
161 | Napi::Buffer output = info[1].As>();
162 | uint32_t size = info[2].As().Uint32Value();
163 | uint32_t compressionLevel = info[3].IsNumber() ? info[3].As().Uint32Value() : 9;
164 |
165 | Napi::Number result = Napi::Number::New(env, LZ4_compress_HC(input.Data(),
166 | output.Data(),
167 | input.Length(),
168 | size,
169 | compressionLevel)
170 | );
171 | return result;
172 | }
173 |
174 | /*
175 | //-----------------------------------------------------------------------------
176 | // LZ4 Stream
177 | //-----------------------------------------------------------------------------
178 | // {Buffer} input
179 | Napi::Value LZ4Stream_create(const Napi::CallbackInfo& info) {
180 | Napi::Env env = info.Env();
181 |
182 | if (info.Length() != 1) {
183 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
184 | return env.Null();
185 | }
186 |
187 | if (!info[0].IsBuffer()) {
188 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
189 | return env.Null();
190 | }
191 |
192 | Napi::Buffer input = info[0].As>();
193 |
194 | void* p = LZ4_create(input.Data());
195 |
196 | if (p == NULL) {
197 | return env.Null();
198 | }
199 |
200 | Napi::Buffer handle = Napi::Buffer::New(env, (char *)p, LZ4_sizeofStreamState());
201 |
202 | return handle;
203 | }
204 |
205 | // {Buffer} lz4 data struct, {Buffer} input, {Buffer} output
206 | Napi::Value LZ4Stream_compress_continue(const Napi::CallbackInfo& info) {
207 | Napi::Env env = info.Env();
208 |
209 | if (info.Length() != 3) {
210 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
211 | return env.Null();
212 | }
213 |
214 | if (!info[0].IsBuffer() || !info[1].IsBuffer() || !info[2].IsBuffer()) {
215 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
216 | return env.Null();
217 | }
218 |
219 | Napi::Buffer lz4ds = info[0].As>();
220 | Napi::Buffer input = info[1].As>();
221 | Napi::Buffer output = info[2].As>();
222 |
223 | Napi::Number result = Napi::Number::New(env, LZ4_compress_continue(
224 | (LZ4_stream_t*)lz4ds.Data(),
225 | input.Data(),
226 | output.Data(),
227 | input.Length())
228 | );
229 | return result;
230 | }
231 |
232 | // {Buffer} input, {Buffer} lz4 data struct
233 | Napi::Value LZ4Stream_slideInputBuffer(const Napi::CallbackInfo& info) {
234 | Napi::Env env = info.Env();
235 |
236 | if (info.Length() != 2) {
237 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
238 | return env.Null();
239 | }
240 |
241 | if (!info[0].IsBuffer() || !info[1].IsBuffer()) {
242 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
243 | return env.Null();
244 | }
245 |
246 | Napi::Buffer lz4ds = info[0].As>();
247 | Napi::Buffer input = info[1].As>();
248 |
249 | // Pointer to the position into the input buffer where the next data block should go
250 | char* input_next_block = LZ4_slideInputBuffer(lz4ds.Data());
251 | char* input_current = (char *)input.Data();
252 |
253 | // Return the position of the next block
254 | return Napi::Number::New(env, (int)(input_next_block - input_current));
255 | }
256 |
257 | // {Buffer} lz4 data struct
258 | Napi::Value LZ4Stream_free(const Napi::CallbackInfo& info) {
259 | Napi::Env env = info.Env();
260 |
261 | if (info.Length() != 1) {
262 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
263 | return env.Null();
264 | }
265 |
266 | if (!info[0].IsBuffer()) {
267 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
268 | return env.Null();
269 | }
270 |
271 | Napi::Buffer lz4ds = info[0].As>();
272 | int res = LZ4_freeStream( (LZ4_stream_t*) lz4ds .Data());
273 |
274 | return Napi::Number::New(env, res);
275 | }
276 | */
277 | //-----------------------------------------------------------------------------
278 | // LZ4 Uncompress
279 | //-----------------------------------------------------------------------------
280 | // {Buffer} input, {Buffer} output
281 | Napi::Value LZ4Uncompress(const Napi::CallbackInfo& info) {
282 | Napi::Env env = info.Env();
283 |
284 | uint32_t alen = info.Length();
285 | if (alen < 2 || alen > 4) {
286 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
287 | return env.Null();
288 | }
289 |
290 | if (!info[0].IsBuffer() || !info[1].IsBuffer()) {
291 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
292 | return env.Null();
293 | }
294 | Napi::Buffer input = info[0].As>();
295 | Napi::Buffer output = info[1].As>();
296 |
297 | Napi::Number result;
298 | uint32_t sIdx = 0;
299 | uint32_t eIdx = input.Length();
300 | switch (alen) {
301 | case 4:
302 | if (!info[3].IsNumber()) {
303 | Napi::TypeError::New(env, "Invalid endIdx").ThrowAsJavaScriptException();
304 | return env.Null();
305 | }
306 | if (!info[2].IsNumber()) {
307 | Napi::TypeError::New(env, "Invalid startIdx").ThrowAsJavaScriptException();
308 | return env.Null();
309 | }
310 | sIdx = info[2].As().Uint32Value();
311 | eIdx = info[3].As().Uint32Value();
312 | result = Napi::Number::New(env, LZ4_decompress_safe(input.Data() + sIdx,
313 | output.Data(),
314 | eIdx - sIdx,
315 | output.Length())
316 | );
317 | break;
318 | case 3:
319 | if (!info[2].IsNumber()) {
320 | Napi::TypeError::New(env, "Invalid startIdx").ThrowAsJavaScriptException();
321 | return env.Null();
322 | }
323 | sIdx = info[2].As().Uint32Value();
324 | [[fallthrough]];
325 | case 2:
326 | result = Napi::Number::New(env, LZ4_decompress_safe(input.Data() + sIdx,
327 | output.Data(),
328 | eIdx - sIdx,
329 | output.Length())
330 | );
331 | }
332 |
333 | return result;
334 | }
335 |
336 | // {Buffer} input, {Buffer} output
337 | Napi::Value LZ4Uncompress_fast(const Napi::CallbackInfo& info) {
338 | Napi::Env env = info.Env();
339 |
340 | if (info.Length() != 2) {
341 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
342 | return env.Null();
343 | }
344 |
345 | if (!info[0].IsBuffer() || !info[1].IsBuffer()) {
346 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
347 | return env.Null();
348 | }
349 |
350 | Napi::Buffer input = info[0].As>();
351 | Napi::Buffer output = info[1].As>();
352 |
353 | #pragma GCC diagnostic push
354 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
355 | Napi::Number result = Napi::Number::New(env, LZ4_decompress_fast(input.Data(),
356 | output.Data(),
357 | output.Length())
358 | );
359 | #pragma GCC diagnostic pop
360 | return result;
361 | }
362 |
363 |
364 | Napi::Object init_lz4(Napi::Env env, Napi::Object exports) {
365 | exports.Set(Napi::String::New(env, "compressBound"), Napi::Function::New(env, LZ4CompressBound));
366 | exports.Set(Napi::String::New(env, "compress"), Napi::Function::New(env, LZ4Compress));
367 | exports.Set(Napi::String::New(env, "compressLimited"), Napi::Function::New(env, LZ4CompressLimited));
368 |
369 | // exports.Set(Napi::String::New(env, "lz4s_create"), Napi::Function::New(env, LZ4Stream_create));
370 | // exports.Set(Napi::String::New(env, "lz4s_compress_continue"), Napi::Function::New(env, LZ4Stream_compress_continue));
371 | // exports.Set(Napi::String::New(env, "lz4s_slide_input"), Napi::Function::New(env, LZ4Stream_slideInputBuffer));
372 | // exports.Set(Napi::String::New(env, "lz4s_free"), Napi::Function::New(env, LZ4Stream_free));
373 |
374 | exports.Set(Napi::String::New(env, "compressHC"), Napi::Function::New(env, LZ4CompressHC));
375 | exports.Set(Napi::String::New(env, "compressHCLimited"), Napi::Function::New(env, LZ4CompressHCLimited));
376 |
377 | exports.Set(Napi::String::New(env, "uncompress"), Napi::Function::New(env, LZ4Uncompress));
378 | exports.Set(Napi::String::New(env, "uncompress_fast"), Napi::Function::New(env, LZ4Uncompress_fast));
379 |
380 | return exports;
381 | }
382 | NODE_API_MODULE(lz4_binding, init_lz4);
--------------------------------------------------------------------------------
/lib/binding/xxhash_binding.cc:
--------------------------------------------------------------------------------
1 | #define NAPI_VERSION 3
2 | #include
3 |
4 | #define XXH_PRIVATE_API
5 |
6 | #include "../../deps/lz4/lib/xxhash.h"
7 |
8 | //-----------------------------------------------------------------------------
9 | // xxHash
10 | //-----------------------------------------------------------------------------
11 | // {Buffer} input, {Integer} seed (optional)
12 | Napi::Value xxHash(const Napi::CallbackInfo &info) {
13 | Napi::Env env = info.Env();
14 |
15 | if (info.Length() == 0) {
16 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
17 | return env.Null();
18 | }
19 |
20 | if (!info[0].IsBuffer()) {
21 | Napi::TypeError::New(env, "Wrong argument: Buffer expected").ThrowAsJavaScriptException();
22 | return env.Null();
23 | }
24 |
25 | Napi::Buffer input = info[0].As>();
26 | uint32_t seed = 0;
27 | if (info[1].IsNumber()) {
28 | seed = info[1].As().Uint32Value();
29 | }
30 |
31 | Napi::Number result = Napi::Number::New(env, XXH32(input.Data(),
32 | input.Length(),
33 | seed)
34 | );
35 | return result;
36 | }
37 |
38 | // {Integer} seed
39 | Napi::Value xxHash_init(const Napi::CallbackInfo &info) {
40 | Napi::Env env = info.Env();
41 |
42 | if (info.Length() == 0) {
43 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
44 | return env.Null();
45 | }
46 |
47 | if (!info[0].IsNumber()) {
48 | Napi::TypeError::New(env, "Wrong argument: Integer expected").ThrowAsJavaScriptException();
49 | return env.Null();
50 | }
51 |
52 | uint32_t seed = info[0].As().Uint32Value();
53 |
54 | XXH32_state_t* state = XXH32_createState();
55 | XXH32_reset(state, seed);
56 | Napi::Buffer handle = Napi::Buffer::New(env, (char *) state, sizeof(XXH32_state_t));
57 |
58 | return handle;
59 | }
60 |
61 | // {Buffer} state {Buffer} input {Integer} seed
62 | Napi::Value xxHash_update(const Napi::CallbackInfo &info) {
63 | Napi::Env env = info.Env();
64 |
65 | if (info.Length() != 2) {
66 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
67 | return env.Null();
68 | }
69 |
70 | if (!info[0].IsBuffer() || !info[1].IsBuffer()) {
71 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
72 | return env.Null();
73 | }
74 |
75 | Napi::Buffer data0 = info[0].As>();
76 | Napi::Buffer data1 = info[1].As>();
77 |
78 | int err_code = XXH32_update(
79 | (XXH32_state_t *) data0.Data(),
80 | data1.Data(),
81 | data1.Length()
82 | );
83 |
84 | return Napi::Number::New(env, err_code);
85 | }
86 |
87 | // {Buffer} state
88 | Napi::Value xxHash_digest(const Napi::CallbackInfo &info) {
89 | Napi::Env env = info.Env();
90 |
91 | if (info.Length() != 1) {
92 | Napi::Error::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
93 | return env.Null();
94 | }
95 |
96 | if (!info[0].IsBuffer()) {
97 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
98 | return env.Null();
99 | }
100 |
101 | Napi::Number res = Napi::Number::New(env,
102 | XXH32_digest((XXH32_state_t *) info[0].As>().Data())
103 | );
104 |
105 | return res;
106 | }
107 |
108 | Napi::Object init_xxhash(Napi::Env env, Napi::Object exports) {
109 | exports.Set(Napi::String::New(env, "xxHash"), Napi::Function::New(env, xxHash));
110 | exports.Set(Napi::String::New(env, "init"), Napi::Function::New(env, xxHash_init));
111 | exports.Set(Napi::String::New(env, "update"), Napi::Function::New(env, xxHash_update));
112 | exports.Set(Napi::String::New(env, "digest"), Napi::Function::New(env, xxHash_digest));
113 |
114 | return exports;
115 | }
116 |
117 | NODE_API_MODULE(xxhash, init_xxhash);
--------------------------------------------------------------------------------
/lib/decoder.js:
--------------------------------------------------------------------------------
1 | var Decoder = require('./decoder_stream')
2 |
3 | /**
4 | Decode an LZ4 stream
5 | */
6 | function LZ4_uncompress (input, options) {
7 | var output = []
8 | var decoder = new Decoder(options)
9 |
10 | decoder.on('data', function (chunk) {
11 | output.push(chunk)
12 | })
13 |
14 | decoder.end(input)
15 |
16 | return Buffer.concat(output)
17 | }
18 |
19 | exports.LZ4_uncompress = LZ4_uncompress
--------------------------------------------------------------------------------
/lib/decoder_stream.js:
--------------------------------------------------------------------------------
1 | var Transform = require('stream').Transform
2 | var inherits = require('util').inherits
3 |
4 | var lz4_static = require('./static')
5 | var utils = lz4_static.utils
6 | var lz4_binding = utils.bindings
7 | var lz4_jsbinding = require('./binding')
8 |
9 | var STATES = lz4_static.STATES
10 | var SIZES = lz4_static.SIZES
11 |
12 | function Decoder (options) {
13 | if ( !(this instanceof Decoder) )
14 | return new Decoder(options)
15 |
16 | Transform.call(this, options)
17 | // Options
18 | this.options = options || {}
19 |
20 | this.binding = this.options.useJS ? lz4_jsbinding : lz4_binding
21 |
22 | // Encoded data being processed
23 | this.buffer = null
24 | // Current position within the data
25 | this.pos = 0
26 | this.descriptor = null
27 |
28 | // Current state of the parsing
29 | this.state = STATES.MAGIC
30 |
31 | this.notEnoughData = false
32 | this.descriptorStart = 0
33 | this.streamSize = null
34 | this.dictId = null
35 | this.currentStreamChecksum = null
36 | this.dataBlockSize = 0
37 | this.skippableSize = 0
38 | }
39 | inherits(Decoder, Transform)
40 |
41 | Decoder.prototype._transform = function (data, encoding, done) {
42 | // Handle skippable data
43 | if (this.skippableSize > 0) {
44 | this.skippableSize -= data.length
45 | if (this.skippableSize > 0) {
46 | // More to skip
47 | done()
48 | return
49 | }
50 |
51 | data = data.slice(-this.skippableSize)
52 | this.skippableSize = 0
53 | this.state = STATES.MAGIC
54 | }
55 | // Buffer the incoming data
56 | this.buffer = this.buffer
57 | ? Buffer.concat( [ this.buffer, data ], this.buffer.length + data.length )
58 | : data
59 |
60 | this._main(done)
61 | }
62 |
63 | Decoder.prototype.emit_Error = function (msg) {
64 | this.emit( 'error', new Error(msg + ' @' + this.pos) )
65 | }
66 |
67 | Decoder.prototype.check_Size = function (n) {
68 | var delta = this.buffer.length - this.pos
69 | if (delta <= 0 || delta < n) {
70 | if (this.notEnoughData) this.emit_Error( 'Unexpected end of LZ4 stream' )
71 | return true
72 | }
73 |
74 | this.pos += n
75 | return false
76 | }
77 |
78 | Decoder.prototype.read_MagicNumber = function () {
79 | var pos = this.pos
80 | if ( this.check_Size(SIZES.MAGIC) ) return true
81 |
82 | var magic = utils.readUInt32LE(this.buffer, pos)
83 |
84 | // Skippable chunk
85 | if ( (magic & 0xFFFFFFF0) === lz4_static.MAGICNUMBER_SKIPPABLE ) {
86 | this.state = STATES.SKIP_SIZE
87 | return
88 | }
89 |
90 | // LZ4 stream
91 | if ( magic !== lz4_static.MAGICNUMBER ) {
92 | this.pos = pos
93 | this.emit_Error( 'Invalid magic number: ' + magic.toString(16).toUpperCase() )
94 | return true
95 | }
96 |
97 | this.state = STATES.DESCRIPTOR
98 | }
99 |
100 | Decoder.prototype.read_SkippableSize = function () {
101 | var pos = this.pos
102 | if ( this.check_Size(SIZES.SKIP_SIZE) ) return true
103 | this.state = STATES.SKIP_DATA
104 | this.skippableSize = utils.readUInt32LE(this.buffer, pos)
105 | }
106 |
107 | Decoder.prototype.read_Descriptor = function () {
108 | // Flags
109 | var pos = this.pos
110 | if ( this.check_Size(SIZES.DESCRIPTOR) ) return true
111 |
112 | this.descriptorStart = pos
113 |
114 | // version
115 | var descriptor_flg = this.buffer[pos]
116 | var version = descriptor_flg >> 6
117 | if ( version !== lz4_static.VERSION ) {
118 | this.pos = pos
119 | this.emit_Error( 'Invalid version: ' + version + ' != ' + lz4_static.VERSION )
120 | return true
121 | }
122 |
123 | // flags
124 | // reserved bit should not be set
125 | if ( (descriptor_flg >> 1) & 0x1 ) {
126 | this.pos = pos
127 | this.emit_Error('Reserved bit set')
128 | return true
129 | }
130 |
131 | var blockMaxSizeIndex = (this.buffer[pos+1] >> 4) & 0x7
132 | var blockMaxSize = lz4_static.blockMaxSizes[ blockMaxSizeIndex ]
133 | if ( blockMaxSize === null ) {
134 | this.pos = pos
135 | this.emit_Error( 'Invalid block max size: ' + blockMaxSizeIndex )
136 | return true
137 | }
138 |
139 | this.descriptor = {
140 | blockIndependence: Boolean( (descriptor_flg >> 5) & 0x1 )
141 | , blockChecksum: Boolean( (descriptor_flg >> 4) & 0x1 )
142 | , blockMaxSize: blockMaxSize
143 | , streamSize: Boolean( (descriptor_flg >> 3) & 0x1 )
144 | , streamChecksum: Boolean( (descriptor_flg >> 2) & 0x1 )
145 | , dict: Boolean( descriptor_flg & 0x1 )
146 | , dictId: 0
147 | }
148 |
149 | this.state = STATES.SIZE
150 | }
151 |
152 | Decoder.prototype.read_Size = function () {
153 | if (this.descriptor.streamSize) {
154 | var pos = this.pos
155 | if ( this.check_Size(SIZES.SIZE) ) return true
156 | //TODO max size is unsigned 64 bits
157 | this.streamSize = this.buffer.slice(pos, pos + 8)
158 | }
159 |
160 | this.state = STATES.DICTID
161 | }
162 |
163 | Decoder.prototype.read_DictId = function () {
164 | if (this.descriptor.dictId) {
165 | var pos = this.pos
166 | if ( this.check_Size(SIZES.DICTID) ) return true
167 | this.dictId = utils.readUInt32LE(this.buffer, pos)
168 | }
169 |
170 | this.state = STATES.DESCRIPTOR_CHECKSUM
171 | }
172 |
173 | Decoder.prototype.read_DescriptorChecksum = function () {
174 | var pos = this.pos
175 | if ( this.check_Size(SIZES.DESCRIPTOR_CHECKSUM) ) return true
176 |
177 | var checksum = this.buffer[pos]
178 | var currentChecksum = utils.descriptorChecksum( this.buffer.slice(this.descriptorStart, pos) )
179 | if (currentChecksum !== checksum) {
180 | this.pos = pos
181 | this.emit_Error( 'Invalid stream descriptor checksum' )
182 | return true
183 | }
184 |
185 | this.state = STATES.DATABLOCK_SIZE
186 | }
187 |
188 | Decoder.prototype.read_DataBlockSize = function () {
189 | var pos = this.pos
190 | if ( this.check_Size(SIZES.DATABLOCK_SIZE) ) return true
191 | var datablock_size = utils.readUInt32LE(this.buffer, pos)
192 | // Uncompressed
193 | if ( datablock_size === lz4_static.EOS ) {
194 | this.state = STATES.EOS
195 | return
196 | }
197 |
198 | // if (datablock_size > this.descriptor.blockMaxSize) {
199 | // this.emit_Error( 'ASSERTION: invalid datablock_size: ' + datablock_size.toString(16).toUpperCase() + ' > ' + this.descriptor.blockMaxSize.toString(16).toUpperCase() )
200 | // }
201 | this.dataBlockSize = datablock_size
202 |
203 | this.state = STATES.DATABLOCK_DATA
204 | }
205 |
206 | Decoder.prototype.read_DataBlockData = function () {
207 | var pos = this.pos
208 | var datablock_size = this.dataBlockSize
209 | if ( datablock_size & 0x80000000 ) {
210 | // Uncompressed size
211 | datablock_size = datablock_size & 0x7FFFFFFF
212 | }
213 | if ( this.check_Size(datablock_size) ) return true
214 |
215 | this.dataBlock = this.buffer.slice(pos, pos + datablock_size)
216 |
217 | this.state = STATES.DATABLOCK_CHECKSUM
218 | }
219 |
220 | Decoder.prototype.read_DataBlockChecksum = function () {
221 | var pos = this.pos
222 | if (this.descriptor.blockChecksum) {
223 | if ( this.check_Size(SIZES.DATABLOCK_CHECKSUM) ) return true
224 | var checksum = utils.readUInt32LE(this.buffer, this.pos-4)
225 | var currentChecksum = utils.blockChecksum( this.dataBlock )
226 | if (currentChecksum !== checksum) {
227 | this.pos = pos
228 | this.emit_Error( 'Invalid block checksum' )
229 | return true
230 | }
231 | }
232 |
233 | this.state = STATES.DATABLOCK_UNCOMPRESS
234 | }
235 |
236 | Decoder.prototype.uncompress_DataBlock = function () {
237 | var uncompressed
238 | // uncompressed?
239 | if ( this.dataBlockSize & 0x80000000 ) {
240 | uncompressed = this.dataBlock
241 | } else {
242 | uncompressed = Buffer.alloc(this.descriptor.blockMaxSize)
243 | var decodedSize = this.binding.uncompress( this.dataBlock, uncompressed )
244 | if (decodedSize < 0) {
245 | this.emit_Error( 'Invalid data block: ' + (-decodedSize) )
246 | return true
247 | }
248 | if ( decodedSize < this.descriptor.blockMaxSize )
249 | uncompressed = uncompressed.slice(0, decodedSize)
250 | }
251 | this.dataBlock = null
252 | this.push( uncompressed )
253 |
254 | // Stream checksum
255 | if (this.descriptor.streamChecksum) {
256 | this.currentStreamChecksum = utils.streamChecksum(uncompressed, this.currentStreamChecksum)
257 | }
258 |
259 | this.state = STATES.DATABLOCK_SIZE
260 | }
261 |
262 | Decoder.prototype.read_EOS = function () {
263 | if (this.descriptor.streamChecksum) {
264 | var pos = this.pos
265 | if ( this.check_Size(SIZES.EOS) ) return true
266 | var checksum = utils.readUInt32LE(this.buffer, pos)
267 | if ( checksum !== utils.streamChecksum(null, this.currentStreamChecksum) ) {
268 | this.pos = pos
269 | this.emit_Error( 'Invalid stream checksum: ' + checksum.toString(16).toUpperCase() )
270 | return true
271 | }
272 | }
273 |
274 | this.state = STATES.MAGIC
275 | }
276 |
277 | Decoder.prototype._flush = function (done) {
278 | // Error on missing data as no more will be coming
279 | this.notEnoughData = true
280 | this._main(done)
281 | }
282 |
283 | Decoder.prototype._main = function (done) {
284 | var pos = this.pos
285 | var notEnoughData
286 |
287 | while ( !notEnoughData && this.pos < this.buffer.length ) {
288 | if (this.state === STATES.MAGIC)
289 | notEnoughData = this.read_MagicNumber()
290 |
291 | if (this.state === STATES.SKIP_SIZE)
292 | notEnoughData = this.read_SkippableSize()
293 |
294 | if (this.state === STATES.DESCRIPTOR)
295 | notEnoughData = this.read_Descriptor()
296 |
297 | if (this.state === STATES.SIZE)
298 | notEnoughData = this.read_Size()
299 |
300 | if (this.state === STATES.DICTID)
301 | notEnoughData = this.read_DictId()
302 |
303 | if (this.state === STATES.DESCRIPTOR_CHECKSUM)
304 | notEnoughData = this.read_DescriptorChecksum()
305 |
306 | if (this.state === STATES.DATABLOCK_SIZE)
307 | notEnoughData = this.read_DataBlockSize()
308 |
309 | if (this.state === STATES.DATABLOCK_DATA)
310 | notEnoughData = this.read_DataBlockData()
311 |
312 | if (this.state === STATES.DATABLOCK_CHECKSUM)
313 | notEnoughData = this.read_DataBlockChecksum()
314 |
315 | if (this.state === STATES.DATABLOCK_UNCOMPRESS)
316 | notEnoughData = this.uncompress_DataBlock()
317 |
318 | if (this.state === STATES.EOS)
319 | notEnoughData = this.read_EOS()
320 | }
321 |
322 | if (this.pos > pos) {
323 | this.buffer = this.buffer.slice(this.pos)
324 | this.pos = 0
325 | }
326 |
327 | done()
328 | }
329 |
330 | module.exports = Decoder
331 |
--------------------------------------------------------------------------------
/lib/encoder.js:
--------------------------------------------------------------------------------
1 | var Encoder = require('./encoder_stream')
2 |
3 | /**
4 | Encode an LZ4 stream
5 | */
6 | function LZ4_compress (input, options) {
7 | var output = []
8 | var encoder = new Encoder(options)
9 |
10 | encoder.on('data', function (chunk) {
11 | output.push(chunk)
12 | })
13 |
14 | encoder.end(input)
15 |
16 | return Buffer.concat(output)
17 | }
18 |
19 | exports.LZ4_compress = LZ4_compress
20 |
--------------------------------------------------------------------------------
/lib/encoder_stream.js:
--------------------------------------------------------------------------------
1 | var Transform = require('stream').Transform
2 | var inherits = require('util').inherits
3 |
4 | var lz4_static = require('./static')
5 | var utils = lz4_static.utils
6 | var lz4_binding = utils.bindings
7 | var lz4_jsbinding = require('./binding')
8 |
9 | var STATES = lz4_static.STATES
10 | var SIZES = lz4_static.SIZES
11 |
12 | var defaultOptions = {
13 | blockIndependence: true
14 | , blockChecksum: false
15 | , blockMaxSize: 4<<20
16 | , streamSize: false
17 | , streamChecksum: true
18 | , dict: false
19 | , dictId: 0
20 | , highCompression: false
21 | }
22 |
23 | function Encoder (options) {
24 | if ( !(this instanceof Encoder) )
25 | return new Encoder(options)
26 |
27 | Transform.call(this, options)
28 |
29 | // Set the options
30 | var o = options || defaultOptions
31 | if (o !== defaultOptions)
32 | Object.keys(defaultOptions).forEach(function (p) {
33 | if ( !o.hasOwnProperty(p) ) o[p] = defaultOptions[p]
34 | })
35 |
36 | this.options = o
37 |
38 | this.binding = this.options.useJS ? lz4_jsbinding : lz4_binding
39 | this.compress = o.highCompression ? this.binding.compressHC : this.binding.compress
40 |
41 | // Build the stream descriptor from the options
42 | // flags
43 | var descriptor_flg = 0
44 | descriptor_flg = descriptor_flg | (lz4_static.VERSION << 6) // Version
45 | descriptor_flg = descriptor_flg | ((o.blockIndependence & 1) << 5) // Block independence
46 | descriptor_flg = descriptor_flg | ((o.blockChecksum & 1) << 4) // Block checksum
47 | descriptor_flg = descriptor_flg | ((o.streamSize & 1) << 3) // Stream size
48 | descriptor_flg = descriptor_flg | ((o.streamChecksum & 1) << 2) // Stream checksum
49 | // Reserved bit
50 | descriptor_flg = descriptor_flg | (o.dict & 1) // Preset dictionary
51 |
52 | // block maximum size
53 | var descriptor_bd = lz4_static.blockMaxSizes.indexOf(o.blockMaxSize)
54 | if (descriptor_bd < 0)
55 | throw new Error('Invalid blockMaxSize: ' + o.blockMaxSize)
56 |
57 | this.descriptor = { flg: descriptor_flg, bd: (descriptor_bd & 0x7) << 4 }
58 |
59 | // Data being processed
60 | this.buffer = []
61 | this.length = 0
62 |
63 | this.first = true
64 | this.checksum = null
65 | }
66 | inherits(Encoder, Transform)
67 |
68 | // Header = magic number + stream descriptor
69 | Encoder.prototype.headerSize = function () {
70 | var streamSizeSize = this.options.streamSize ? SIZES.DESCRIPTOR : 0
71 | var dictSize = this.options.dict ? SIZES.DICTID : 0
72 |
73 | return SIZES.MAGIC + 1 + 1 + streamSizeSize + dictSize + 1
74 | }
75 |
76 | Encoder.prototype.header = function () {
77 | var headerSize = this.headerSize()
78 | var output = Buffer.alloc(headerSize)
79 |
80 | this.state = STATES.MAGIC
81 | output.writeInt32LE(lz4_static.MAGICNUMBER, 0)
82 |
83 | this.state = STATES.DESCRIPTOR
84 | var descriptor = output.slice(SIZES.MAGIC, output.length - 1)
85 |
86 | // Update the stream descriptor
87 | descriptor.writeUInt8(this.descriptor.flg, 0)
88 | descriptor.writeUInt8(this.descriptor.bd, 1)
89 |
90 | var pos = 2
91 | this.state = STATES.SIZE
92 | if (this.options.streamSize) {
93 | //TODO only 32bits size supported
94 | descriptor.writeInt32LE(0, pos)
95 | descriptor.writeInt32LE(this.size, pos + 4)
96 | pos += SIZES.SIZE
97 | }
98 | this.state = STATES.DICTID
99 | if (this.options.dict) {
100 | descriptor.writeInt32LE(this.dictId, pos)
101 | pos += SIZES.DICTID
102 | }
103 |
104 | this.state = STATES.DESCRIPTOR_CHECKSUM
105 | output.writeUInt8(
106 | utils.descriptorChecksum( descriptor )
107 | , SIZES.MAGIC + pos
108 | )
109 |
110 | return output
111 | }
112 |
113 | Encoder.prototype.update_Checksum = function (data) {
114 | // Calculate the stream checksum
115 | this.state = STATES.CHECKSUM_UPDATE
116 | if (this.options.streamChecksum) {
117 | this.checksum = utils.streamChecksum(data, this.checksum)
118 | }
119 | }
120 |
121 | Encoder.prototype.compress_DataBlock = function (data) {
122 | this.state = STATES.DATABLOCK_COMPRESS
123 | var dbChecksumSize = this.options.blockChecksum ? SIZES.DATABLOCK_CHECKSUM : 0
124 | var maxBufSize = this.binding.compressBound(data.length)
125 | var buf = Buffer.alloc( SIZES.DATABLOCK_SIZE + maxBufSize + dbChecksumSize )
126 | var compressed = buf.slice(SIZES.DATABLOCK_SIZE, SIZES.DATABLOCK_SIZE + maxBufSize)
127 | var compressedSize = this.compress(data, compressed)
128 |
129 | // Set the block size
130 | this.state = STATES.DATABLOCK_SIZE
131 | // Block size shall never be larger than blockMaxSize
132 | // console.log("blockMaxSize", this.options.blockMaxSize, "compressedSize", compressedSize)
133 | if (compressedSize > 0 && compressedSize <= this.options.blockMaxSize) {
134 | // highest bit is 0 (compressed data)
135 | buf.writeUInt32LE(compressedSize, 0)
136 | buf = buf.slice(0, SIZES.DATABLOCK_SIZE + compressedSize + dbChecksumSize)
137 | } else {
138 | // Cannot compress the data, leave it as is
139 | // highest bit is 1 (uncompressed data)
140 | buf.writeInt32LE( 0x80000000 | data.length, 0)
141 | buf = buf.slice(0, SIZES.DATABLOCK_SIZE + data.length + dbChecksumSize)
142 | data.copy(buf, SIZES.DATABLOCK_SIZE);
143 | }
144 |
145 | // Set the block checksum
146 | this.state = STATES.DATABLOCK_CHECKSUM
147 | if (this.options.blockChecksum) {
148 | // xxHash checksum on undecoded data with a seed of 0
149 | var checksum = buf.slice(-dbChecksumSize)
150 | checksum.writeUInt32LE( utils.blockChecksum(buf.slice(SIZES.DATABLOCK_SIZE, -dbChecksumSize)), 0 )
151 | }
152 |
153 | // Update the stream checksum
154 | this.update_Checksum(data)
155 |
156 | this.size += data.length
157 |
158 | return buf
159 | }
160 |
161 | Encoder.prototype._transform = function (data, encoding, done) {
162 | if (data) {
163 | // Buffer the incoming data
164 | this.buffer.push(data)
165 | this.length += data.length
166 | }
167 |
168 | // Stream header
169 | if (this.first) {
170 | this.push( this.header() )
171 | this.first = false
172 | }
173 |
174 | var blockMaxSize = this.options.blockMaxSize
175 | // Not enough data for a block
176 | if ( this.length < blockMaxSize ) return done()
177 |
178 | // Build the data to be compressed
179 | var buf = Buffer.concat(this.buffer, this.length)
180 |
181 | for (var j = 0, i = buf.length; i >= blockMaxSize; i -= blockMaxSize, j += blockMaxSize) {
182 | // Compress the block
183 | this.push( this.compress_DataBlock( buf.slice(j, j + blockMaxSize) ) )
184 | }
185 |
186 | // Set the remaining data
187 | if (i > 0) {
188 | this.buffer = [ buf.slice(j) ]
189 | this.length = this.buffer[0].length
190 | } else {
191 | this.buffer = []
192 | this.length = 0
193 | }
194 |
195 | done()
196 | }
197 |
198 | Encoder.prototype._flush = function (done) {
199 | if (this.first) {
200 | this.push( this.header() )
201 | this.first = false
202 | }
203 |
204 | if (this.length > 0) {
205 | var buf = Buffer.concat(this.buffer, this.length)
206 | this.buffer = []
207 | this.length = 0
208 | var cc = this.compress_DataBlock(buf)
209 | this.push( cc )
210 | }
211 |
212 | if (this.options.streamChecksum) {
213 | this.state = STATES.CHECKSUM
214 | var eos = Buffer.alloc(SIZES.EOS + SIZES.CHECKSUM)
215 | eos.writeUInt32LE( utils.streamChecksum(null, this.checksum), SIZES.EOS )
216 | } else {
217 | var eos = Buffer.alloc(SIZES.EOS)
218 | }
219 |
220 | this.state = STATES.EOS
221 | eos.writeInt32LE(lz4_static.EOS, 0)
222 | this.push(eos)
223 |
224 | done()
225 | }
226 |
227 | module.exports = Encoder
228 |
--------------------------------------------------------------------------------
/lib/lz4.js:
--------------------------------------------------------------------------------
1 | /**
2 | * LZ4 based compression and decompression
3 | * Copyright (c) 2014 Pierre Curto
4 | * MIT Licensed
5 | */
6 |
7 | module.exports = require('./static')
8 |
9 | module.exports.version = "0.5.1"
10 | module.exports.createDecoderStream = require('./decoder_stream')
11 | module.exports.decode = require('./decoder').LZ4_uncompress
12 |
13 | module.exports.createEncoderStream = require('./encoder_stream')
14 | module.exports.encode = require('./encoder').LZ4_compress
15 |
16 | // Expose block decoder and encoders
17 | var bindings = module.exports.utils.bindings
18 |
19 | module.exports.decodeBlock = bindings.uncompress
20 |
21 | module.exports.encodeBound = bindings.compressBound
22 | module.exports.encodeBlock = bindings.compress
23 | module.exports.encodeBlockHC = bindings.compressHC
24 |
--------------------------------------------------------------------------------
/lib/lz4l.js:
--------------------------------------------------------------------------------
1 | lz4.js
--------------------------------------------------------------------------------
/lib/static.js:
--------------------------------------------------------------------------------
1 | /**
2 | * LZ4 based compression and decompression
3 | * Copyright (c) 2014 Pierre Curto
4 | * MIT Licensed
5 | */
6 |
7 | // LZ4 stream constants
8 | exports.MAGICNUMBER = 0x184D2204
9 | exports.MAGICNUMBER_BUFFER = Buffer.alloc(4)
10 | exports.MAGICNUMBER_BUFFER.writeUInt32LE(exports.MAGICNUMBER, 0)
11 |
12 | exports.EOS = 0
13 | exports.EOS_BUFFER = Buffer.alloc(4)
14 | exports.EOS_BUFFER.writeUInt32LE(exports.EOS, 0)
15 |
16 | exports.VERSION = 1
17 |
18 | exports.MAGICNUMBER_SKIPPABLE = 0x184D2A50
19 |
20 | // n/a, n/a, n/a, n/a, 64KB, 256KB, 1MB, 4MB
21 | exports.blockMaxSizes = [ null, null, null, null, 64<<10, 256<<10, 1<<20, 4<<20 ]
22 |
23 | // Compressed file extension
24 | exports.extension = '.lz4'
25 |
26 | // Internal stream states
27 | exports.STATES = {
28 | // Compressed stream
29 | MAGIC: 0
30 | , DESCRIPTOR: 1
31 | , SIZE: 2
32 | , DICTID: 3
33 | , DESCRIPTOR_CHECKSUM: 4
34 | , DATABLOCK_SIZE: 5
35 | , DATABLOCK_DATA: 6
36 | , DATABLOCK_CHECKSUM: 7
37 | , DATABLOCK_UNCOMPRESS: 8
38 | , DATABLOCK_COMPRESS: 9
39 | , CHECKSUM: 10
40 | , CHECKSUM_UPDATE: 11
41 | , EOS: 90
42 | // Skippable chunk
43 | , SKIP_SIZE: 101
44 | , SKIP_DATA: 102
45 | }
46 |
47 | exports.SIZES = {
48 | MAGIC: 4
49 | , DESCRIPTOR: 2
50 | , SIZE: 8
51 | , DICTID: 4
52 | , DESCRIPTOR_CHECKSUM: 1
53 | , DATABLOCK_SIZE: 4
54 | , DATABLOCK_CHECKSUM: 4
55 | , CHECKSUM: 4
56 | , EOS: 4
57 | , SKIP_SIZE: 4
58 | }
59 |
60 | exports.utils = require('./utils')
61 |
--------------------------------------------------------------------------------
/lib/utils-js.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Javascript emulated bindings
3 | */
4 | var XXH = require('xxhashjs').h32 // XXX .h64
5 |
6 | var CHECKSUM_SEED = 0
7 |
8 | // Header checksum is second byte of xxhash using 0 as a seed
9 | exports.descriptorChecksum = function (d) {
10 | return (XXH(d, CHECKSUM_SEED).toNumber() >> 8) & 0xFF
11 | }
12 |
13 | exports.blockChecksum = function (d) {
14 | return XXH(d, CHECKSUM_SEED).toNumber()
15 | }
16 |
17 | exports.streamChecksum = function (d, c) {
18 | if (c === null)
19 | c = XXH(CHECKSUM_SEED)
20 |
21 | if (d === null)
22 | return c.digest().toNumber()
23 |
24 | return c.update(d)
25 | }
26 |
27 | // Provide simple readUInt32LE as the Buffer ones from node and browserify are incompatible
28 | exports.readUInt32LE = function (buffer, offset) {
29 | const val = (buffer[offset]) |
30 | (buffer[offset + 1] << 8) |
31 | (buffer[offset + 2] << 16) |
32 | (buffer[offset + 3] << 24)
33 | // bitwise operators operate on signed values, this trick returns the result unsigned
34 | return val >>> 0;
35 | }
36 |
37 | exports.bindings = require('./binding')
38 |
--------------------------------------------------------------------------------
/lib/utils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Native bindings
3 | */
4 | var XXH = require('../build/Release/xxhash')
5 |
6 | var CHECKSUM_SEED = 0
7 |
8 | // Header checksum is second byte of xxhash using 0 as a seed
9 | exports.descriptorChecksum = function (d) {
10 | return (XXH.xxHash(d, CHECKSUM_SEED) >> 8) & 0xFF
11 | }
12 |
13 | exports.blockChecksum = function (d) {
14 | return XXH.xxHash(d, CHECKSUM_SEED)
15 | }
16 |
17 | exports.streamChecksum = function (d, c) {
18 | if (c === null)
19 | c = XXH.init(CHECKSUM_SEED)
20 |
21 | if (d === null)
22 | return XXH.digest(c)
23 |
24 | XXH.update(c, d)
25 |
26 | return c
27 | }
28 |
29 | // Provide simple readUInt32LE as the Buffer ones from node and browserify are incompatible
30 | exports.readUInt32LE = function (buffer, offset) {
31 | // this is nodejs Buffer.readUInt32LE() implementation...
32 | const val = ((buffer[offset]) |
33 | (buffer[offset + 1] << 8) |
34 | (buffer[offset + 2] << 16)) +
35 | (buffer[offset + 3] * 0x1000000)
36 | // bitwise operators operate on signed values, this trick returns the result unsigned
37 | return val >>> 0;
38 | }
39 |
40 | exports.bindings = require('../build/Release/lz4')
41 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": {
3 | "name": "Pierre Curto"
4 | },
5 | "name": "lz4",
6 | "description": "LZ4 streaming compression and decompression",
7 | "keywords": [
8 | "lz4",
9 | "compression",
10 | "decompression",
11 | "stream"
12 | ],
13 | "version": "0.6.3",
14 | "homepage": "http://github.com/pierrec/node-lz4",
15 | "repository": {
16 | "type": "git",
17 | "url": "git://github.com/pierrec/node-lz4.git"
18 | },
19 | "main": "./lib/lz4.js",
20 | "browser": "./build/lz4.js",
21 | "bugs": {
22 | "url": "http://github.com/pierrec/node-lz4/issues"
23 | },
24 | "gypfile": true,
25 | "licenses": [
26 | {
27 | "type": "MIT",
28 | "url": "http://github.com/pierrec/node-lz4/raw/master/LICENSE"
29 | }
30 | ],
31 | "engines": {
32 | "node": ">= 10.13"
33 | },
34 | "dependencies": {
35 | "buffer": "^5.2.1",
36 | "cuint": "^0.2.2",
37 | "node-addon-api": "^3.2.1",
38 | "xxhashjs": "^0.2.2"
39 | },
40 | "devDependencies": {
41 | "benchmark": "^1.0.0",
42 | "browserify": "^16.2.3",
43 | "jasmine-core": "^2.2.0",
44 | "karma": "^0.12.31",
45 | "karma-chrome-launcher": "^0.1.7",
46 | "karma-cli": "0.0.4",
47 | "karma-firefox-launcher": "^0.1.4",
48 | "karma-jasmine": "^0.3.5",
49 | "karma-mocha": "^0.1.10",
50 | "minify": "^4.1.1",
51 | "mocha": "^2.2.4"
52 | },
53 | "scripts": {
54 | "test": "mocha",
55 | "install": "node-gyp rebuild",
56 | "prepublish": "./build.sh"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/test/block-test.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var assert = require('assert')
3 |
4 | var lz4 = require('..')
5 |
6 | describe('LZ4 block encoder/decoder', function () {
7 | var decoded_data_valid = fs.readFileSync( __dirname + '/../data/test' )
8 |
9 | it('should encode/decode data', function (done) {
10 | var encoded_data = Buffer.alloc( lz4.encodeBound(decoded_data_valid.length) )
11 | var n = lz4.encodeBlock(decoded_data_valid, encoded_data)
12 |
13 | assert( n > 0 )
14 | encoded_data = encoded_data.slice(0, n)
15 |
16 | var decoded_data = Buffer.alloc(decoded_data_valid.length)
17 | n = lz4.decodeBlock(encoded_data, decoded_data)
18 | assert( n === decoded_data_valid.length )
19 | assert( decoded_data.toString() === decoded_data_valid.toString() )
20 |
21 | done()
22 | })
23 |
24 | })
--------------------------------------------------------------------------------
/test/browser/block.js:
--------------------------------------------------------------------------------
1 | describe('Browser block encoding/decoding', function () {
2 | var lz4 = require('lz4')
3 | var Buffer = require('buffer').Buffer
4 |
5 | describe('block', function () {
6 | it('should encode short uncompressible string', function () {
7 | lz4.encodeBlock(Buffer.from('Test'), Buffer.alloc(32))
8 | })
9 |
10 | it('should encode/decode test data', function () {
11 | var decoded_data_valid
12 |
13 | downloadDataFile('test', 'arraybuffer', function (response) {
14 | decoded_data_valid = Buffer.from(new Uint8Array(response))
15 | })
16 |
17 | runs(function () {
18 | expect(decoded_data_valid).toBeDefined()
19 |
20 | var encoded_data = Buffer.alloc(lz4.encodeBound(decoded_data_valid.length))
21 | var decoded_data = Buffer.alloc(decoded_data_valid.length)
22 |
23 | expect(encoded_data).toBeDefined()
24 | expect(decoded_data).toBeDefined()
25 |
26 | var n = lz4.encodeBlock(decoded_data_valid, encoded_data)
27 | expect(n).toBeDefined()
28 | if (n > 0) {
29 | encoded_data = encoded_data.slice(0, n)
30 | n = lz4.decodeBlock(encoded_data, decoded_data)
31 |
32 | expect(n).toEqual(decoded_data_valid.length)
33 |
34 | decoded_data = decoded_data.slice(0, n)
35 | expect( decoded_data.toString() ).toEqual( decoded_data_valid.toString() )
36 | }
37 | })
38 | })
39 |
40 | it('should encode/decode test data', function () {
41 | var decoded_data_valid
42 |
43 | downloadDataFile('test', 'arraybuffer', function (response) {
44 | decoded_data_valid = Buffer.from(new Uint8Array(response))
45 | })
46 |
47 | runs(function () {
48 | expect(decoded_data_valid).toBeDefined()
49 |
50 | var encoded_data = Buffer.alloc(lz4.encodeBound(decoded_data_valid.length) + 4)
51 | var decoded_data = Buffer.alloc(decoded_data_valid.length)
52 |
53 | expect(encoded_data).toBeDefined()
54 | expect(decoded_data).toBeDefined()
55 |
56 | var n = lz4.encodeBlock(decoded_data_valid, encoded_data, 4)
57 | expect(n).toBeDefined()
58 | if (n > 0) {
59 | encoded_data = encoded_data.slice(4, n)
60 | n = lz4.decodeBlock(encoded_data, decoded_data)
61 |
62 | expect(n).toEqual(decoded_data_valid.length)
63 |
64 | decoded_data = decoded_data.slice(0, n)
65 | expect( decoded_data.toString() ).toEqual( decoded_data_valid.toString() )
66 | }
67 | })
68 | })
69 | })
70 | })
--------------------------------------------------------------------------------
/test/browser/checksum.js:
--------------------------------------------------------------------------------
1 | describe('Browser checksum', function () {
2 | var lz4 = require('lz4')
3 | var Buffer = require('buffer').Buffer
4 |
5 | it('should encode/decode test data', function () {
6 | runs(function () {
7 | var data = Buffer.alloc(200)
8 | data.fill(0)
9 |
10 | lz4.decode(lz4.encode(data))
11 | })
12 | })
13 |
14 | it('should encode/decode test data', function () {
15 | runs(function () {
16 | var data = Buffer.alloc(200)
17 | data.fill(16)
18 |
19 | lz4.decode(lz4.encode(data))
20 | })
21 | })
22 |
23 | it('should encode/decode test data', function () {
24 | runs(function () {
25 | var data = Buffer.alloc(200)
26 | data.slice(0, 100).fill(0)
27 | data.slice(100).fill(16)
28 |
29 | lz4.decode(lz4.encode(data))
30 | })
31 | })
32 |
33 | })
--------------------------------------------------------------------------------
/test/browser/decoder.js:
--------------------------------------------------------------------------------
1 | describe('Browser encoding', function () {
2 | var lz4 = require('lz4')
3 | var Buffer = require('buffer').Buffer
4 |
5 | describe('sync', function () {
6 | it('should be able to encode and decode collada file', function () {
7 | var text
8 |
9 | downloadDataFile('sphere.dae', 'text', function (response) {
10 | text = response
11 | })
12 |
13 | runs(function () {
14 | expect(text).toBeDefined()
15 | var encoded_data = lz4.encode(text)
16 | expect(lz4.decode(encoded_data).toString()).toEqual(text)
17 | })
18 | })
19 |
20 | it('should decode collada file encoded by node.js', function () {
21 | var decoded_data, encoded_data
22 |
23 | downloadDataFile('sphere.dae', 'text', function (response) {
24 | decoded_data = response
25 | })
26 |
27 | downloadDataFile('sphere.lz4.dat', 'arraybuffer', function (response) {
28 | encoded_data = Buffer.from(new Uint8Array(response))
29 | })
30 |
31 | runs(function () {
32 | expect(decoded_data).toBeDefined()
33 | expect(encoded_data).toBeDefined()
34 | expect(lz4.decode(encoded_data).toString()).toEqual(decoded_data)
35 | })
36 | })
37 | })
38 | })
--------------------------------------------------------------------------------
/test/browser/encoder.js:
--------------------------------------------------------------------------------
1 | describe('Browser encoding', function () {
2 | var lz4 = require('lz4')
3 | var Buffer = require('buffer').Buffer
4 |
5 | describe('sync', function () {
6 | it('should encode short uncompressible string', function () {
7 | lz4.encode('Test')
8 | })
9 |
10 | it('should encode test data', function () {
11 | var decoded_data, encoded_data
12 |
13 | downloadDataFile('test', 'text', function (response) {
14 | decoded_data = response
15 | })
16 |
17 | downloadDataFile('test.lz4', 'arraybuffer', function (response) {
18 | encoded_data = Buffer.from(new Uint8Array(response))
19 | })
20 |
21 | runs(function () {
22 | expect(decoded_data).toBeDefined()
23 | expect(encoded_data).toBeDefined()
24 | expect(lz4.encode(decoded_data)).toBeDefined()
25 | })
26 | })
27 | })
28 | })
--------------------------------------------------------------------------------
/test/browser/helpers/download_data_file.js:
--------------------------------------------------------------------------------
1 | function downloadDataFile(name, type, cb) {
2 | var loaded = false,
3 | xhr = new XMLHttpRequest()
4 | xhr.open('GET', '/base/data/' + name, true)
5 | xhr.responseType = type
6 |
7 | xhr.onload = function(e) {
8 | cb(this.response)
9 | loaded = true
10 | }
11 |
12 | xhr.send()
13 | waitsFor(function () {
14 | return loaded
15 | })
16 | }
--------------------------------------------------------------------------------
/test/browser/helpers/spec_helper.js:
--------------------------------------------------------------------------------
1 | beforeEach(function () {
2 | this.addMatchers({
3 | toEqualBuffer: function (expected) {
4 | return Buffer.compare(this.actual, expected)
5 | }
6 | });
7 | });
--------------------------------------------------------------------------------
/test/checksum-test.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert')
2 |
3 |
4 | describe('LZ4 checksum', function () {
5 | var lz4 = require('..')
6 |
7 | it('should encode/decode data', function () {
8 | var data = Buffer.alloc(200)
9 | data.fill(0)
10 |
11 | assert.deepEqual(lz4.decode(lz4.encode(data, { blockChecksum: true })), data)
12 | })
13 |
14 | it('should encode/decode data', function () {
15 | var data = Buffer.alloc(200)
16 | data.fill(16)
17 |
18 | assert.deepEqual(lz4.decode(lz4.encode(data, { blockChecksum: true })), data)
19 | })
20 |
21 | it('should encode/decode data', function () {
22 | var data = Buffer.alloc(200)
23 | data.slice(0, 100).fill(0)
24 | data.slice(100).fill(16)
25 |
26 | assert.deepEqual(lz4.decode(lz4.encode(data, { blockChecksum: true })), data)
27 | })
28 |
29 | it('should encode/decode data #107', function () {
30 | const data = Buffer.from('Lorem ipsum dolor sit amet, consectetur adipiscing elit.')
31 |
32 | assert.deepEqual(lz4.decode(lz4.encode(data, { blockChecksum: true })), data)
33 | })
34 |
35 | })
--------------------------------------------------------------------------------
/test/decode-test.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var assert = require('assert')
3 | var lz4 = require('..')
4 |
5 | describe('LZ4 decoder', function () {
6 | var decoded_data = fs.readFileSync( __dirname + '/../data/test' ).toString().replace(/\r/g, '') // cleanup line endings
7 | var decoded_data_medium = fs.readFileSync( __dirname + '/../data/test_medium' ).toString().replace(/\r/g, '') // cleanup line endings
8 | var encoded_data = fs.readFileSync( __dirname + '/../data/test.lz4' )
9 |
10 | describe('sync', function () {
11 | it('should decode data', function (done) {
12 | var decoded = lz4.decode(encoded_data)
13 |
14 | assert.equal( decoded_data, decoded.toString() )
15 | done()
16 | })
17 | })
18 |
19 | describe('async', function () {
20 | it('should decode data', function (done) {
21 | var input = fs.createReadStream( __dirname + '/../data/test.lz4' )
22 | var decoder = lz4.createDecoderStream()
23 | var decoded = ''
24 |
25 | function add (data) {
26 | if (data) decoded += data.toString()
27 | }
28 | decoder.on('data', add)
29 | decoder.on('end', add)
30 | decoder.on('end', function () {
31 | assert.equal( decoded_data, decoded )
32 | done()
33 | })
34 |
35 | input.pipe(decoder)
36 | })
37 |
38 | it('should decode data with small stream chunks', function (done) {
39 | var input = fs.createReadStream( __dirname + '/../data/test_medium.lz4', { bufferSize: 1024 } )
40 | var decoder = lz4.createDecoderStream()
41 | var decoded = ''
42 |
43 | function add (data) {
44 | if (data) decoded += data.toString()
45 | }
46 | decoder.on('data', add)
47 | decoder.on('end', add)
48 | decoder.on('end', function () {
49 | assert.equal( decoded_data_medium, decoded )
50 | done()
51 | })
52 |
53 | input.pipe(decoder)
54 | })
55 | })
56 | })
--------------------------------------------------------------------------------
/test/encode-test.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var assert = require('assert')
3 |
4 | var lz4 = require('..')
5 |
6 | describe('LZ4 encoder', function () {
7 | var decoded_data = fs.readFileSync( __dirname + '/../data/test' )
8 |
9 | function compare (a, b) {
10 | if (a.length !== b.length) return false
11 |
12 | for (var i = 0, n = a.length; i < n; i++) {
13 | if (a[i] !== b[i]) return false
14 | }
15 |
16 | return true
17 | }
18 |
19 | describe('sync', function () {
20 | describe('empty', function () {
21 | it('should encode no data', function (done) {
22 | var empty = Buffer.from("")
23 | var encoded = lz4.encode(empty)
24 |
25 | assert( compare(lz4.decode(encoded), empty) )
26 | done()
27 | })
28 | })
29 |
30 | describe('encoding', function () {
31 | it('should encode data', function (done) {
32 | var encoded = lz4.encode(decoded_data)
33 |
34 | assert( compare(lz4.decode(encoded), decoded_data) )
35 | done()
36 | })
37 | })
38 |
39 | describe('HC encoding', function () {
40 | it('should encode data', function (done) {
41 | var encoded = lz4.encode(decoded_data, { highCompression: true })
42 |
43 | assert( compare(lz4.decode(encoded), decoded_data) )
44 | done()
45 | })
46 | })
47 |
48 | // https://github.com/pierrec/node-lz4/issues/69
49 | describe('HC block compression', function () {
50 | it('decoded should match with original', function (done) {
51 | var str = 'a'.repeat(81) + 'XXXXXX' + 'a'.repeat(65531) + 'XXXXXXaaaaaa'
52 | var input = Buffer.from(str)
53 | var output = Buffer.alloc(lz4.encodeBound(input.length))
54 | var compressedSize = lz4.encodeBlockHC(input, output)
55 | output = output.slice(0, compressedSize)
56 |
57 | var uncompressed = Buffer.alloc(input.length)
58 | var uncompressedSize = lz4.decodeBlock(output, uncompressed)
59 | uncompressed = uncompressed.slice(0, uncompressedSize)
60 |
61 | assert( compare(input, uncompressed) )
62 | done()
63 | })
64 | })
65 | })
66 |
67 | describe('async', function () {
68 | describe('encoding', function () {
69 | it('should encode data', function (done) {
70 | var input = fs.createReadStream( __dirname + '/../data/test' )
71 | var encoder = lz4.createEncoderStream()
72 | var encoded = []
73 |
74 | function add (chunk) {
75 | if (chunk) encoded.push(chunk)
76 | }
77 |
78 | encoder.on('data', add)
79 | encoder.on('end', add)
80 | encoder.on('end', function () {
81 | assert( compare(lz4.decode(Buffer.concat(encoded)), decoded_data) )
82 | done()
83 | })
84 |
85 | input.pipe(encoder)
86 | })
87 | })
88 |
89 | describe('encoding with small chunk size', function () {
90 | it('should encode data', function (done) {
91 | var input = fs.createReadStream( __dirname + '/../data/test' )
92 | var encoder = lz4.createEncoderStream({ blockMaxSize: 64<<10 })
93 | var encoded = []
94 |
95 | function add (chunk) {
96 | if (chunk) encoded.push(chunk)
97 | }
98 |
99 | encoder.on('data', add)
100 | encoder.on('end', add)
101 | encoder.on('end', function () {
102 | assert( compare(lz4.decode(Buffer.concat(encoded)), decoded_data) )
103 | done()
104 | })
105 |
106 | input.pipe(encoder)
107 | })
108 | })
109 |
110 | describe('HC encoding', function () {
111 | it('should encode data', function (done) {
112 | var input = fs.createReadStream( __dirname + '/../data/test' )
113 | var encoder = lz4.createEncoderStream({ highCompression: true })
114 | var encoded = []
115 |
116 | function add (chunk) {
117 | if (chunk) encoded.push(chunk)
118 | }
119 |
120 | encoder.on('data', add)
121 | encoder.on('end', add)
122 | encoder.on('end', function () {
123 | assert( compare(lz4.decode(Buffer.concat(encoded)), decoded_data) )
124 | done()
125 | })
126 |
127 | input.pipe(encoder)
128 | })
129 | })
130 | })
131 | })
132 |
--------------------------------------------------------------------------------
/test/jsencode_decode-test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Test Javascript based encoding
3 | */
4 | var fs = require('fs')
5 | var assert = require('assert')
6 |
7 | var lz4 = require('../lib/binding')
8 |
9 | describe('LZ4 js encoder', function () {
10 |
11 | function compare (a, b) {
12 | if (a.length !== b.length) return false
13 |
14 | for (var i = 0, n = a.length; i < n; i++) {
15 | if (a[i] !== b[i]) return false
16 | }
17 |
18 | return true
19 | }
20 |
21 | it('should encode/decode data', function (done) {
22 | var data = fs.readFileSync( __dirname + '/../data/test' )
23 | var maxSize = lz4.compressBound(data.length)
24 |
25 | var jsencoded = Buffer.alloc(maxSize)
26 | var jsencodedSize = lz4.compress(data, jsencoded)
27 |
28 | assert( jsencodedSize > 0 )
29 | jsencoded = jsencoded.slice(0, jsencodedSize)
30 |
31 | var jsdecoded = Buffer.alloc(data.length)
32 | var jsdecodedSize = lz4.uncompress(jsencoded, jsdecoded)
33 |
34 | assert( jsdecodedSize > 0 )
35 |
36 | assert(
37 | compare(
38 | data
39 | , jsdecoded.slice(0, jsdecodedSize)
40 | )
41 | )
42 | done()
43 | })
44 |
45 | //TODO node v0.10.26 seg faults on this test
46 | false&&it('should encode/decode data #2', function (done) {
47 | var data = Buffer.from("R0lGODlhDAAMAIAAAGZmZv///yH5BAEAAAEALAAAAAAMAAwAAAIYjI8BmbBsHIwPSsXuPbrSj3QRKIrKYl4FADs=")
48 | var maxSize = lz4.compressBound(data.length)
49 |
50 | var jsencoded = Buffer.alloc(maxSize)
51 | var jsencodedSize = lz4.compress(data, jsencoded)
52 |
53 | assert( jsencodedSize > 0 )
54 | jsencoded = jsencoded.slice(0, jsencodedSize)
55 |
56 | var jsdecoded = Buffer.alloc(data.length)
57 | var jsdecodedSize = lz4.uncompress(jsencoded, jsdecoded)
58 |
59 | assert( jsdecodedSize > 0 )
60 |
61 | assert(
62 | compare(
63 | data
64 | , jsdecoded.slice(0, jsdecodedSize)
65 | )
66 | )
67 | done()
68 | })
69 | })
--------------------------------------------------------------------------------