├── .classpath
├── .gitignore
├── .gitmodules
├── .project
├── .settings
├── org.eclipse.jdt.core.prefs
└── org.eclipse.jdt.ui.prefs
├── CHANGES.md
├── LICENSE.txt
├── README.md
├── build.xml
├── ivy-pure-java.xml
├── ivy.xml
├── lz4-java.bnd
├── lz4-pure-java.bnd
└── src
├── build
├── gen_sources.mvel
├── pom-pure-java.template
├── pom.template
└── source_templates
│ ├── compress.template
│ ├── compress_hc.template
│ ├── compressor.template
│ ├── compressor_hc.template
│ ├── decompress.template
│ ├── decompressor.template
│ ├── hashtable.template
│ ├── xxhash32.template
│ ├── xxhash32_hash.template
│ ├── xxhash32_streaming.template
│ ├── xxhash64.template
│ ├── xxhash64_hash.template
│ └── xxhash64_streaming.template
├── java-unsafe
└── net
│ └── jpountz
│ ├── lz4
│ └── LZ4UnsafeUtils.java
│ └── util
│ └── UnsafeUtils.java
├── java
├── net
│ └── jpountz
│ │ ├── lz4
│ │ ├── LZ4BlockInputStream.java
│ │ ├── LZ4BlockOutputStream.java
│ │ ├── LZ4ByteBufferUtils.java
│ │ ├── LZ4Compressor.java
│ │ ├── LZ4CompressorWithLength.java
│ │ ├── LZ4Constants.java
│ │ ├── LZ4Decompressor.java
│ │ ├── LZ4DecompressorWithLength.java
│ │ ├── LZ4Exception.java
│ │ ├── LZ4Factory.java
│ │ ├── LZ4FastDecompressor.java
│ │ ├── LZ4FrameInputStream.java
│ │ ├── LZ4FrameOutputStream.java
│ │ ├── LZ4HCJNICompressor.java
│ │ ├── LZ4JNI.java
│ │ ├── LZ4JNICompressor.java
│ │ ├── LZ4JNIFastDecompressor.java
│ │ ├── LZ4JNISafeDecompressor.java
│ │ ├── LZ4SafeDecompressor.java
│ │ ├── LZ4SafeUtils.java
│ │ ├── LZ4UnknownSizeDecompressor.java
│ │ ├── LZ4Utils.java
│ │ └── package.html
│ │ ├── util
│ │ ├── ByteBufferUtils.java
│ │ ├── Native.java
│ │ ├── SafeUtils.java
│ │ ├── Utils.java
│ │ └── package.html
│ │ └── xxhash
│ │ ├── AbstractStreamingXXHash32Java.java
│ │ ├── AbstractStreamingXXHash64Java.java
│ │ ├── StreamingXXHash32.java
│ │ ├── StreamingXXHash32JNI.java
│ │ ├── StreamingXXHash64.java
│ │ ├── StreamingXXHash64JNI.java
│ │ ├── XXHash32.java
│ │ ├── XXHash32JNI.java
│ │ ├── XXHash64.java
│ │ ├── XXHash64JNI.java
│ │ ├── XXHashConstants.java
│ │ ├── XXHashFactory.java
│ │ ├── XXHashJNI.java
│ │ └── package.html
└── overview.html
├── jni
├── net_jpountz_lz4_LZ4JNI.c
└── net_jpountz_xxhash_XXHashJNI.c
├── resources
└── net
│ └── jpountz
│ └── util
│ ├── darwin
│ ├── aarch64
│ │ └── liblz4-java.dylib
│ └── x86_64
│ │ └── liblz4-java.dylib
│ ├── linux
│ ├── aarch64
│ │ └── liblz4-java.so
│ ├── amd64
│ │ └── liblz4-java.so
│ ├── i386
│ │ └── liblz4-java.so
│ ├── ppc64le
│ │ └── liblz4-java.so
│ └── s390x
│ │ └── liblz4-java.so
│ └── win32
│ └── amd64
│ └── liblz4-java.so
├── test-resources
└── calgary
│ ├── README
│ ├── book1
│ ├── geo
│ └── pic
└── test
└── net
└── jpountz
├── example
├── LZ4Example.java
└── XXHashExample.java
├── lz4
├── AbstractLZ4Test.java
├── Instances.java
├── LZ4BlockStreamingTest.java
├── LZ4FactoryTest.java
├── LZ4FrameIOStreamTest.java
└── LZ4Test.java
└── xxhash
├── XXHash32Test.java
├── XXHash64Test.java
└── XXHashFactoryTest.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
25 | * Instances of this class are thread-safe.
26 | */
27 | public abstract class LZ4Compressor {
28 |
29 | /**
30 | * Returns the maximum compressed length for an input of size length
.
31 | *
32 | * @param length the input size in bytes
33 | * @return the maximum compressed length in bytes
34 | */
35 | @SuppressWarnings("static-method")
36 | public final int maxCompressedLength(int length) {
37 | return LZ4Utils.maxCompressedLength(length);
38 | }
39 |
40 | /**
41 | * Compresses src[srcOff:srcOff+srcLen]
into
42 | * dest[destOff:destOff+maxDestLen]
and returns the compressed
43 | * length.
44 | *
45 | * This method will throw a {@link LZ4Exception} if this compressor is unable
46 | * to compress the input into less than maxDestLen
bytes. To
47 | * prevent this exception to be thrown, you should make sure that
48 | * maxDestLen >= maxCompressedLength(srcLen)
.
49 | *
50 | * @param src the source data
51 | * @param srcOff the start offset in src
52 | * @param srcLen the number of bytes to compress
53 | * @param dest the destination buffer
54 | * @param destOff the start offset in dest
55 | * @param maxDestLen the maximum number of bytes to write in dest
56 | * @throws LZ4Exception if maxDestLen is too small
57 | * @return the compressed size
58 | */
59 | public abstract int compress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen);
60 |
61 | /**
62 | * Compresses src[srcOff:srcOff+srcLen]
into
63 | * dest[destOff:destOff+maxDestLen]
and returns the compressed
64 | * length.
65 | *
66 | * This method will throw a {@link LZ4Exception} if this compressor is unable
67 | * to compress the input into less than maxDestLen
bytes. To
68 | * prevent this exception to be thrown, you should make sure that
69 | * maxDestLen >= maxCompressedLength(srcLen)
.
70 | *
71 | * {@link ByteBuffer} positions remain unchanged.
72 | *
73 | * @param src the source data
74 | * @param srcOff the start offset in src
75 | * @param srcLen the number of bytes to compress
76 | * @param dest the destination buffer
77 | * @param destOff the start offset in dest
78 | * @param maxDestLen the maximum number of bytes to write in dest
79 | * @throws LZ4Exception if maxDestLen is too small
80 | * @return the compressed size
81 | */
82 | public abstract int compress(ByteBuffer src, int srcOff, int srcLen, ByteBuffer dest, int destOff, int maxDestLen);
83 |
84 | /**
85 | * Convenience method, equivalent to calling
86 | * {@link #compress(byte[], int, int, byte[], int, int) compress(src, srcOff, srcLen, dest, destOff, dest.length - destOff)}.
87 | *
88 | * @param src the source data
89 | * @param srcOff the start offset in src
90 | * @param srcLen the number of bytes to compress
91 | * @param dest the destination buffer
92 | * @param destOff the start offset in dest
93 | * @throws LZ4Exception if dest is too small
94 | * @return the compressed size
95 | */
96 | public final int compress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff) {
97 | return compress(src, srcOff, srcLen, dest, destOff, dest.length - destOff);
98 | }
99 |
100 | /**
101 | * Convenience method, equivalent to calling
102 | * {@link #compress(byte[], int, int, byte[], int) compress(src, 0, src.length, dest, 0)}.
103 | *
104 | * @param src the source data
105 | * @param dest the destination buffer
106 | * @throws LZ4Exception if dest is too small
107 | * @return the compressed size
108 | */
109 | public final int compress(byte[] src, byte[] dest) {
110 | return compress(src, 0, src.length, dest, 0);
111 | }
112 |
113 | /**
114 | * Convenience method which returns src[srcOff:srcOff+srcLen]
115 | * compressed.
116 | *
Warning: this method has an 117 | * important overhead due to the fact that it needs to allocate a buffer to 118 | * compress into, and then needs to resize this buffer to the actual 119 | * compressed length.
120 | *Here is how this method is implemented:
121 | *122 | * final int maxCompressedLength = maxCompressedLength(srcLen); 123 | * final byte[] compressed = new byte[maxCompressedLength]; 124 | * final int compressedLength = compress(src, srcOff, srcLen, compressed, 0); 125 | * return Arrays.copyOf(compressed, compressedLength); 126 | *127 | * 128 | * @param src the source data 129 | * @param srcOff the start offset in src 130 | * @param srcLen the number of bytes to compress 131 | * @return the compressed data 132 | */ 133 | public final byte[] compress(byte[] src, int srcOff, int srcLen) { 134 | final int maxCompressedLength = maxCompressedLength(srcLen); 135 | final byte[] compressed = new byte[maxCompressedLength]; 136 | final int compressedLength = compress(src, srcOff, srcLen, compressed, 0); 137 | return Arrays.copyOf(compressed, compressedLength); 138 | } 139 | 140 | /** 141 | * Convenience method, equivalent to calling 142 | * {@link #compress(byte[], int, int) compress(src, 0, src.length)}. 143 | * 144 | * @param src the source data 145 | * @return the compressed data 146 | */ 147 | public final byte[] compress(byte[] src) { 148 | return compress(src, 0, src.length); 149 | } 150 | 151 | /** 152 | * Compresses
src
into dest
. Calling this method
153 | * will update the positions of both {@link ByteBuffer}s.
154 | *
155 | * @param src the source data
156 | * @param dest the destination buffer
157 | * @throws LZ4Exception if dest is too small
158 | */
159 | public final void compress(ByteBuffer src, ByteBuffer dest) {
160 | final int cpLen = compress(src, src.position(), src.remaining(), dest, dest.position(), dest.remaining());
161 | src.position(src.limit());
162 | dest.position(dest.position() + cpLen);
163 | }
164 |
165 | @Override
166 | public String toString() {
167 | return getClass().getSimpleName();
168 | }
169 |
170 | }
171 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/LZ4Constants.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.lz4;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 |
20 | enum LZ4Constants {
21 | ;
22 |
23 | static final int DEFAULT_COMPRESSION_LEVEL = 8+1;
24 | static final int MAX_COMPRESSION_LEVEL = 16+1;
25 |
26 | static final int MEMORY_USAGE = 14;
27 | static final int NOT_COMPRESSIBLE_DETECTION_LEVEL = 6;
28 |
29 | static final int MIN_MATCH = 4;
30 |
31 | static final int HASH_LOG = MEMORY_USAGE - 2;
32 | static final int HASH_TABLE_SIZE = 1 << HASH_LOG;
33 |
34 | static final int SKIP_STRENGTH = Math.max(NOT_COMPRESSIBLE_DETECTION_LEVEL, 2);
35 | static final int COPY_LENGTH = 8;
36 | static final int LAST_LITERALS = 5;
37 | static final int MF_LIMIT = COPY_LENGTH + MIN_MATCH;
38 | static final int MIN_LENGTH = MF_LIMIT + 1;
39 |
40 | static final int MAX_DISTANCE = 1 << 16;
41 |
42 | static final int ML_BITS = 4;
43 | static final int ML_MASK = (1 << ML_BITS) - 1;
44 | static final int RUN_BITS = 8 - ML_BITS;
45 | static final int RUN_MASK = (1 << RUN_BITS) - 1;
46 |
47 | static final int LZ4_64K_LIMIT = (1 << 16) + (MF_LIMIT - 1);
48 | static final int HASH_LOG_64K = HASH_LOG + 1;
49 | static final int HASH_TABLE_SIZE_64K = 1 << HASH_LOG_64K;
50 |
51 | static final int HASH_LOG_HC = 15;
52 | static final int HASH_TABLE_SIZE_HC = 1 << HASH_LOG_HC;
53 | static final int OPTIMAL_ML = ML_MASK - 1 + MIN_MATCH;
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/LZ4Decompressor.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.lz4;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | /**
20 | * @deprecated Use {@link LZ4FastDecompressor} instead.
21 | */
22 | @Deprecated
23 | public interface LZ4Decompressor {
24 |
25 | int decompress(byte[] src, int srcOff, byte[] dest, int destOff, int destLen);
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/LZ4Exception.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.lz4;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | /**
20 | * LZ4 compression or decompression error.
21 | */
22 | public class LZ4Exception extends RuntimeException {
23 |
24 | private static final long serialVersionUID = 1L;
25 |
26 | public LZ4Exception(String msg, Throwable t) {
27 | super(msg, t);
28 | }
29 |
30 | public LZ4Exception(String msg) {
31 | super(msg);
32 | }
33 |
34 | public LZ4Exception() {
35 | super();
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/LZ4FastDecompressor.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.lz4;
2 |
3 | import java.nio.ByteBuffer;
4 |
5 | /*
6 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 |
21 | /**
22 | * LZ4 decompressor that requires the size of the original input to be known.
23 | * Use {@link LZ4SafeDecompressor} if you only know the size of the
24 | * compressed stream.
25 | * 26 | * From lz4-java 1.6.0, it is deprecated to use a JNI-binding instance 27 | * of this class; i.e., an instasnce returned by 28 | * {@link LZ4Factory#fastDecompressor()} of {@link LZ4Factory#nativeInstance()}. 29 | * Please see {@link LZ4Factory#nativeInstance()} for details. 30 | *
31 | * Instances of this class are thread-safe.
32 | *
33 | * @see LZ4Factory#nativeInstance()
34 | */
35 | public abstract class LZ4FastDecompressor implements LZ4Decompressor {
36 |
37 | /** Decompresses src[srcOff:]
into dest[destOff:destOff+destLen]
38 | * and returns the number of bytes read from src
.
39 | * destLen
must be exactly the size of the decompressed data.
40 | *
41 | * @param src the compressed data
42 | * @param srcOff the start offset in src
43 | * @param dest the destination buffer to store the decompressed data
44 | * @param destOff the start offset in dest
45 | * @param destLen the exact size of the original input
46 | * @return the number of bytes read to restore the original input
47 | */
48 | public abstract int decompress(byte[] src, int srcOff, byte[] dest, int destOff, int destLen);
49 |
50 | /** Decompresses src[srcOff:]
into dest[destOff:destOff+destLen]
51 | * and returns the number of bytes read from src
.
52 | * destLen
must be exactly the size of the decompressed data.
53 | * The positions and limits of the {@link ByteBuffer}s remain unchanged.
54 | *
55 | * @param src the compressed data
56 | * @param srcOff the start offset in src
57 | * @param dest the destination buffer to store the decompressed data
58 | * @param destOff the start offset in dest
59 | * @param destLen the exact size of the original input
60 | * @return the number of bytes read to restore the original input
61 | */
62 | public abstract int decompress(ByteBuffer src, int srcOff, ByteBuffer dest, int destOff, int destLen);
63 |
64 | /**
65 | * Convenience method, equivalent to calling
66 | * {@link #decompress(byte[], int, byte[], int, int) decompress(src, 0, dest, 0, destLen)}.
67 | *
68 | * @param src the compressed data
69 | * @param dest the destination buffer to store the decompressed data
70 | * @param destLen the exact size of the original input
71 | * @return the number of bytes read to restore the original input
72 | */
73 | public final int decompress(byte[] src, byte[] dest, int destLen) {
74 | return decompress(src, 0, dest, 0, destLen);
75 | }
76 |
77 | /**
78 | * Convenience method, equivalent to calling
79 | * {@link #decompress(byte[], byte[], int) decompress(src, dest, dest.length)}.
80 | *
81 | * @param src the compressed data
82 | * @param dest the destination buffer to store the decompressed data
83 | * @return the number of bytes read to restore the original input
84 | */
85 | public final int decompress(byte[] src, byte[] dest) {
86 | return decompress(src, dest, dest.length);
87 | }
88 |
89 | /**
90 | * Convenience method which returns src[srcOff:?]
91 | * decompressed.
92 | *
Warning: this method has an 93 | * important overhead due to the fact that it needs to allocate a buffer to 94 | * decompress into.
95 | *Here is how this method is implemented:
96 | *97 | * final byte[] decompressed = new byte[destLen]; 98 | * decompress(src, srcOff, decompressed, 0, destLen); 99 | * return decompressed; 100 | *101 | * 102 | * @param src the compressed data 103 | * @param srcOff the start offset in src 104 | * @param destLen the exact size of the original input 105 | * @return the decompressed data 106 | */ 107 | public final byte[] decompress(byte[] src, int srcOff, int destLen) { 108 | final byte[] decompressed = new byte[destLen]; 109 | decompress(src, srcOff, decompressed, 0, destLen); 110 | return decompressed; 111 | } 112 | 113 | /** 114 | * Convenience method, equivalent to calling 115 | * {@link #decompress(byte[], int, int) decompress(src, 0, destLen)}. 116 | * 117 | * @param src the compressed data 118 | * @param destLen the exact size of the original input 119 | * @return the decompressed data 120 | */ 121 | public final byte[] decompress(byte[] src, int destLen) { 122 | return decompress(src, 0, destLen); 123 | } 124 | 125 | /** 126 | * Decompresses
src
into dest
. dest
's
127 | * {@link ByteBuffer#remaining()} must be exactly the size of the decompressed
128 | * data. This method moves the positions of the buffers.
129 | *
130 | * @param src the compressed data
131 | * @param dest the destination buffer to store the decompressed data
132 | */
133 | public final void decompress(ByteBuffer src, ByteBuffer dest) {
134 | final int read = decompress(src, src.position(), dest, dest.position(), dest.remaining());
135 | dest.position(dest.limit());
136 | src.position(src.position() + read);
137 | }
138 |
139 | @Override
140 | public String toString() {
141 | return getClass().getSimpleName();
142 | }
143 |
144 | }
145 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/LZ4HCJNICompressor.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.lz4;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import static net.jpountz.lz4.LZ4Constants.DEFAULT_COMPRESSION_LEVEL;
20 |
21 | import java.nio.ByteBuffer;
22 |
23 | import net.jpountz.util.ByteBufferUtils;
24 | import net.jpountz.util.SafeUtils;
25 |
26 | /**
27 | * High compression {@link LZ4Compressor}s implemented with JNI bindings to the
28 | * original C implementation of LZ4.
29 | */
30 | final class LZ4HCJNICompressor extends LZ4Compressor {
31 |
32 | public static final LZ4HCJNICompressor INSTANCE = new LZ4HCJNICompressor();
33 | private static LZ4Compressor SAFE_INSTANCE;
34 |
35 | private final int compressionLevel;
36 |
37 | LZ4HCJNICompressor() { this(DEFAULT_COMPRESSION_LEVEL); }
38 | LZ4HCJNICompressor(int compressionLevel) {
39 | this.compressionLevel = compressionLevel;
40 | }
41 |
42 | @Override
43 | public int compress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen) {
44 | SafeUtils.checkRange(src, srcOff, srcLen);
45 | SafeUtils.checkRange(dest, destOff, maxDestLen);
46 | final int result = LZ4JNI.LZ4_compressHC(src, null, srcOff, srcLen, dest, null, destOff, maxDestLen, compressionLevel);
47 | if (result <= 0) {
48 | throw new LZ4Exception();
49 | }
50 | return result;
51 | }
52 |
53 | @Override
54 | public int compress(ByteBuffer src, int srcOff, int srcLen, ByteBuffer dest, int destOff, int maxDestLen) {
55 | ByteBufferUtils.checkNotReadOnly(dest);
56 | ByteBufferUtils.checkRange(src, srcOff, srcLen);
57 | ByteBufferUtils.checkRange(dest, destOff, maxDestLen);
58 |
59 | if ((src.hasArray() || src.isDirect()) && (dest.hasArray() || dest.isDirect())) {
60 | byte[] srcArr = null, destArr = null;
61 | ByteBuffer srcBuf = null, destBuf = null;
62 | if (src.hasArray()) {
63 | srcArr = src.array();
64 | srcOff += src.arrayOffset();
65 | } else {
66 | assert src.isDirect();
67 | srcBuf = src;
68 | }
69 | if (dest.hasArray()) {
70 | destArr = dest.array();
71 | destOff += dest.arrayOffset();
72 | } else {
73 | assert dest.isDirect();
74 | destBuf = dest;
75 | }
76 |
77 | final int result = LZ4JNI.LZ4_compressHC(srcArr, srcBuf, srcOff, srcLen, destArr, destBuf, destOff, maxDestLen, compressionLevel);
78 | if (result <= 0) {
79 | throw new LZ4Exception();
80 | }
81 | return result;
82 | } else {
83 | LZ4Compressor safeInstance = SAFE_INSTANCE;
84 | if (safeInstance == null) {
85 | safeInstance = SAFE_INSTANCE = LZ4Factory.safeInstance().highCompressor(compressionLevel);
86 | }
87 | return safeInstance.compress(src, srcOff, srcLen, dest, destOff, maxDestLen);
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/LZ4JNI.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.lz4;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.nio.ByteBuffer;
20 |
21 | import net.jpountz.util.Native;
22 |
23 |
24 | /**
25 | * JNI bindings to the original C implementation of LZ4.
26 | */
27 | enum LZ4JNI {
28 | ;
29 |
30 | static {
31 | Native.load();
32 | init();
33 | }
34 |
35 | static native void init();
36 | static native int LZ4_compress_limitedOutput(byte[] srcArray, ByteBuffer srcBuffer, int srcOff, int srcLen, byte[] destArray, ByteBuffer destBuffer, int destOff, int maxDestLen);
37 | static native int LZ4_compressHC(byte[] srcArray, ByteBuffer srcBuffer, int srcOff, int srcLen, byte[] destArray, ByteBuffer destBuffer, int destOff, int maxDestLen, int compressionLevel);
38 | static native int LZ4_decompress_fast(byte[] srcArray, ByteBuffer srcBuffer, int srcOff, byte[] destArray, ByteBuffer destBuffer, int destOff, int destLen);
39 | static native int LZ4_decompress_safe(byte[] srcArray, ByteBuffer srcBuffer, int srcOff, int srcLen, byte[] destArray, ByteBuffer destBuffer, int destOff, int maxDestLen);
40 | static native int LZ4_compressBound(int len);
41 |
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/LZ4JNICompressor.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.lz4;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import static net.jpountz.util.ByteBufferUtils.checkNotReadOnly;
20 | import static net.jpountz.util.ByteBufferUtils.checkRange;
21 | import static net.jpountz.util.SafeUtils.checkRange;
22 |
23 | import java.nio.ByteBuffer;
24 |
25 | /**
26 | * Fast {@link LZ4FastCompressor}s implemented with JNI bindings to the original C
27 | * implementation of LZ4.
28 | */
29 | final class LZ4JNICompressor extends LZ4Compressor {
30 |
31 | public static final LZ4Compressor INSTANCE = new LZ4JNICompressor();
32 | private static LZ4Compressor SAFE_INSTANCE;
33 |
34 | @Override
35 | public int compress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen) {
36 | checkRange(src, srcOff, srcLen);
37 | checkRange(dest, destOff, maxDestLen);
38 | final int result = LZ4JNI.LZ4_compress_limitedOutput(src, null, srcOff, srcLen, dest, null, destOff, maxDestLen);
39 | if (result <= 0) {
40 | throw new LZ4Exception("maxDestLen is too small");
41 | }
42 | return result;
43 | }
44 |
45 | @Override
46 | public int compress(ByteBuffer src, int srcOff, int srcLen, ByteBuffer dest, int destOff, int maxDestLen) {
47 | checkNotReadOnly(dest);
48 | checkRange(src, srcOff, srcLen);
49 | checkRange(dest, destOff, maxDestLen);
50 |
51 | if ((src.hasArray() || src.isDirect()) && (dest.hasArray() || dest.isDirect())) {
52 | byte[] srcArr = null, destArr = null;
53 | ByteBuffer srcBuf = null, destBuf = null;
54 | if (src.hasArray()) {
55 | srcArr = src.array();
56 | srcOff += src.arrayOffset();
57 | } else {
58 | assert src.isDirect();
59 | srcBuf = src;
60 | }
61 | if (dest.hasArray()) {
62 | destArr = dest.array();
63 | destOff += dest.arrayOffset();
64 | } else {
65 | assert dest.isDirect();
66 | destBuf = dest;
67 | }
68 |
69 | final int result = LZ4JNI.LZ4_compress_limitedOutput(srcArr, srcBuf, srcOff, srcLen, destArr, destBuf, destOff, maxDestLen);
70 | if (result <= 0) {
71 | throw new LZ4Exception("maxDestLen is too small");
72 | }
73 | return result;
74 | } else {
75 | LZ4Compressor safeInstance = SAFE_INSTANCE;
76 | if (safeInstance == null) {
77 | safeInstance = SAFE_INSTANCE = LZ4Factory.safeInstance().fastCompressor();
78 | }
79 | return safeInstance.compress(src, srcOff, srcLen, dest, destOff, maxDestLen);
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/LZ4JNIFastDecompressor.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.lz4;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 |
20 | import java.nio.ByteBuffer;
21 |
22 | import net.jpountz.util.ByteBufferUtils;
23 | import net.jpountz.util.SafeUtils;
24 |
25 |
26 | /**
27 | * {@link LZ4FastDecompressor} implemented with JNI bindings to the original C
28 | * implementation of LZ4.
29 | */
30 | final class LZ4JNIFastDecompressor extends LZ4FastDecompressor {
31 |
32 | public static final LZ4JNIFastDecompressor INSTANCE = new LZ4JNIFastDecompressor();
33 | private static LZ4FastDecompressor SAFE_INSTANCE;
34 |
35 | @Override
36 | public final int decompress(byte[] src, int srcOff, byte[] dest, int destOff, int destLen) {
37 | SafeUtils.checkRange(src, srcOff);
38 | SafeUtils.checkRange(dest, destOff, destLen);
39 | final int result = LZ4JNI.LZ4_decompress_fast(src, null, srcOff, dest, null, destOff, destLen);
40 | if (result < 0) {
41 | throw new LZ4Exception("Error decoding offset " + (srcOff - result) + " of input buffer");
42 | }
43 | return result;
44 | }
45 |
46 | @Override
47 | public int decompress(ByteBuffer src, int srcOff, ByteBuffer dest, int destOff, int destLen) {
48 | ByteBufferUtils.checkNotReadOnly(dest);
49 | ByteBufferUtils.checkRange(src, srcOff);
50 | ByteBufferUtils.checkRange(dest, destOff, destLen);
51 |
52 | if ((src.hasArray() || src.isDirect()) && (dest.hasArray() || dest.isDirect())) {
53 | byte[] srcArr = null, destArr = null;
54 | ByteBuffer srcBuf = null, destBuf = null;
55 | if (src.hasArray()) {
56 | srcArr = src.array();
57 | srcOff += src.arrayOffset();
58 | } else {
59 | assert src.isDirect();
60 | srcBuf = src;
61 | }
62 | if (dest.hasArray()) {
63 | destArr = dest.array();
64 | destOff += dest.arrayOffset();
65 | } else {
66 | assert dest.isDirect();
67 | destBuf = dest;
68 | }
69 |
70 | final int result = LZ4JNI.LZ4_decompress_fast(srcArr, srcBuf, srcOff, destArr, destBuf, destOff, destLen);
71 | if (result < 0) {
72 | throw new LZ4Exception("Error decoding offset " + (srcOff - result) + " of input buffer");
73 | }
74 | return result;
75 | } else {
76 | LZ4FastDecompressor safeInstance = SAFE_INSTANCE;
77 | if (safeInstance == null) {
78 | safeInstance = SAFE_INSTANCE = LZ4Factory.safeInstance().fastDecompressor();
79 | }
80 | return safeInstance.decompress(src, srcOff, dest, destOff, destLen);
81 | }
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/LZ4JNISafeDecompressor.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.lz4;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 |
20 | import java.nio.ByteBuffer;
21 |
22 | import net.jpountz.util.ByteBufferUtils;
23 | import net.jpountz.util.SafeUtils;
24 |
25 | /**
26 | * {@link LZ4SafeDecompressor} implemented with JNI bindings to the original C
27 | * implementation of LZ4.
28 | */
29 | final class LZ4JNISafeDecompressor extends LZ4SafeDecompressor {
30 |
31 | public static final LZ4JNISafeDecompressor INSTANCE = new LZ4JNISafeDecompressor();
32 | private static LZ4SafeDecompressor SAFE_INSTANCE;
33 |
34 | @Override
35 | public final int decompress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen) {
36 | SafeUtils.checkRange(src, srcOff, srcLen);
37 | SafeUtils.checkRange(dest, destOff, maxDestLen);
38 | final int result = LZ4JNI.LZ4_decompress_safe(src, null, srcOff, srcLen, dest, null, destOff, maxDestLen);
39 | if (result < 0) {
40 | throw new LZ4Exception("Error decoding offset " + (srcOff - result) + " of input buffer");
41 | }
42 | return result;
43 | }
44 |
45 | @Override
46 | public int decompress(ByteBuffer src, int srcOff, int srcLen, ByteBuffer dest, int destOff, int maxDestLen) {
47 | ByteBufferUtils.checkNotReadOnly(dest);
48 | ByteBufferUtils.checkRange(src, srcOff, srcLen);
49 | ByteBufferUtils.checkRange(dest, destOff, maxDestLen);
50 |
51 | if ((src.hasArray() || src.isDirect()) && (dest.hasArray() || dest.isDirect())) {
52 | byte[] srcArr = null, destArr = null;
53 | ByteBuffer srcBuf = null, destBuf = null;
54 | if (src.hasArray()) {
55 | srcArr = src.array();
56 | srcOff += src.arrayOffset();
57 | } else {
58 | assert src.isDirect();
59 | srcBuf = src;
60 | }
61 | if (dest.hasArray()) {
62 | destArr = dest.array();
63 | destOff += dest.arrayOffset();
64 | } else {
65 | assert dest.isDirect();
66 | destBuf = dest;
67 | }
68 |
69 | final int result = LZ4JNI.LZ4_decompress_safe(srcArr, srcBuf, srcOff, srcLen, destArr, destBuf, destOff, maxDestLen);
70 | if (result < 0) {
71 | throw new LZ4Exception("Error decoding offset " + (srcOff - result) + " of input buffer");
72 | }
73 | return result;
74 | } else {
75 | LZ4SafeDecompressor safeInstance = SAFE_INSTANCE;
76 | if (safeInstance == null) {
77 | safeInstance = SAFE_INSTANCE = LZ4Factory.safeInstance().safeDecompressor();
78 | }
79 | return safeInstance.decompress(src, srcOff, srcLen, dest, destOff, maxDestLen);
80 | }
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/LZ4SafeDecompressor.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.lz4;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.nio.ByteBuffer;
20 | import java.util.Arrays;
21 |
22 | /**
23 | * LZ4 decompressor that requires the size of the compressed data to be known.
24 | *
25 | * Implementations of this class are usually a little slower than those of
26 | * {@link LZ4FastDecompressor} but do not require the size of the original data to
27 | * be known.
28 | */
29 | public abstract class LZ4SafeDecompressor implements LZ4UnknownSizeDecompressor {
30 |
31 | /**
32 | * Decompresses src[srcOff:srcOff+srcLen]
into
33 | * dest[destOff:destOff+maxDestLen]
and returns the number of
34 | * decompressed bytes written into dest
.
35 | *
36 | * @param src the compressed data
37 | * @param srcOff the start offset in src
38 | * @param srcLen the exact size of the compressed data
39 | * @param dest the destination buffer to store the decompressed data
40 | * @param destOff the start offset in dest
41 | * @param maxDestLen the maximum number of bytes to write in dest
42 | * @return the original input size
43 | * @throws LZ4Exception if maxDestLen is too small
44 | */
45 | public abstract int decompress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen);
46 |
47 | /**
48 | * Decompresses src[srcOff:srcOff+srcLen]
into
49 | * dest[destOff:destOff+maxDestLen]
and returns the number of
50 | * decompressed bytes written into dest
.
51 | * The positions and limits of the {@link ByteBuffer}s remain unchanged.
52 | *
53 | * @param src the compressed data
54 | * @param srcOff the start offset in src
55 | * @param srcLen the exact size of the compressed data
56 | * @param dest the destination buffer to store the decompressed data
57 | * @param destOff the start offset in dest
58 | * @param maxDestLen the maximum number of bytes to write in dest
59 | * @return the original input size
60 | * @throws LZ4Exception if maxDestLen is too small
61 | */
62 | public abstract int decompress(ByteBuffer src, int srcOff, int srcLen, ByteBuffer dest, int destOff, int maxDestLen);
63 |
64 | /**
65 | * Convenience method, equivalent to calling
66 | * {@link #decompress(byte[], int, int, byte[], int, int) decompress(src, srcOff, srcLen, dest, destOff, dest.length - destOff)}.
67 | *
68 | * @param src the compressed data
69 | * @param srcOff the start offset in src
70 | * @param srcLen the exact size of the compressed data
71 | * @param dest the destination buffer to store the decompressed data
72 | * @param destOff the start offset in dest
73 | * @return the original input size
74 | * @throws LZ4Exception if dest is too small
75 | */
76 | public final int decompress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff) {
77 | return decompress(src, srcOff, srcLen, dest, destOff, dest.length - destOff);
78 | }
79 |
80 | /**
81 | * Convenience method, equivalent to calling
82 | * {@link #decompress(byte[], int, int, byte[], int) decompress(src, 0, src.length, dest, 0)}
83 | *
84 | * @param src the compressed data
85 | * @param dest the destination buffer to store the decompressed data
86 | * @return the original input size
87 | * @throws LZ4Exception if dest is too small
88 | */
89 | public final int decompress(byte[] src, byte[] dest) {
90 | return decompress(src, 0, src.length, dest, 0);
91 | }
92 |
93 | /**
94 | * Convenience method which returns src[srcOff:srcOff+srcLen]
95 | * decompressed.
96 | *
Warning: this method has an 97 | * important overhead due to the fact that it needs to allocate a buffer to 98 | * decompress into, and then needs to resize this buffer to the actual 99 | * decompressed length.
100 | *Here is how this method is implemented:
101 | *102 | * byte[] decompressed = new byte[maxDestLen]; 103 | * final int decompressedLength = decompress(src, srcOff, srcLen, decompressed, 0, maxDestLen); 104 | * if (decompressedLength != decompressed.length) { 105 | * decompressed = Arrays.copyOf(decompressed, decompressedLength); 106 | * } 107 | * return decompressed; 108 | *109 | * 110 | * @param src the compressed data 111 | * @param srcOff the start offset in src 112 | * @param srcLen the exact size of the compressed data 113 | * @param maxDestLen the maximum number of bytes to write in dest 114 | * @return the decompressed data 115 | * @throws LZ4Exception if maxDestLen is too small 116 | */ 117 | public final byte[] decompress(byte[] src, int srcOff, int srcLen, int maxDestLen) { 118 | byte[] decompressed = new byte[maxDestLen]; 119 | final int decompressedLength = decompress(src, srcOff, srcLen, decompressed, 0, maxDestLen); 120 | if (decompressedLength != decompressed.length) { 121 | decompressed = Arrays.copyOf(decompressed, decompressedLength); 122 | } 123 | return decompressed; 124 | } 125 | 126 | /** 127 | * Convenience method, equivalent to calling 128 | * {@link #decompress(byte[], int, int, int) decompress(src, 0, src.length, maxDestLen)}. 129 | * 130 | * @param src the compressed data 131 | * @param maxDestLen the maximum number of bytes to write in dest 132 | * @return the decompressed data 133 | * @throws LZ4Exception if maxDestLen is too small 134 | */ 135 | public final byte[] decompress(byte[] src, int maxDestLen) { 136 | return decompress(src, 0, src.length, maxDestLen); 137 | } 138 | 139 | /** 140 | * Decompresses
src
into dest
. src
's
141 | * {@link ByteBuffer#remaining()} must be exactly the size of the compressed
142 | * data. This method moves the positions of the buffers.
143 | * @param src the compressed data
144 | * @param dest the destination buffer to store the decompressed data
145 | * @throws LZ4Exception if dest is too small
146 | */
147 | public final void decompress(ByteBuffer src, ByteBuffer dest) {
148 | final int decompressed = decompress(src, src.position(), src.remaining(), dest, dest.position(), dest.remaining());
149 | src.position(src.limit());
150 | dest.position(dest.position() + decompressed);
151 | }
152 |
153 | @Override
154 | public String toString() {
155 | return getClass().getSimpleName();
156 | }
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/LZ4SafeUtils.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.lz4;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import static net.jpountz.lz4.LZ4Constants.LAST_LITERALS;
20 | import static net.jpountz.lz4.LZ4Constants.ML_BITS;
21 | import static net.jpountz.lz4.LZ4Constants.ML_MASK;
22 | import static net.jpountz.lz4.LZ4Constants.RUN_MASK;
23 | import net.jpountz.util.SafeUtils;
24 |
25 | enum LZ4SafeUtils {
26 | ;
27 |
28 | static int hash(byte[] buf, int i) {
29 | return LZ4Utils.hash(SafeUtils.readInt(buf, i));
30 | }
31 |
32 | static int hash64k(byte[] buf, int i) {
33 | return LZ4Utils.hash64k(SafeUtils.readInt(buf, i));
34 | }
35 |
36 | static boolean readIntEquals(byte[] buf, int i, int j) {
37 | return buf[i] == buf[j] && buf[i+1] == buf[j+1] && buf[i+2] == buf[j+2] && buf[i+3] == buf[j+3];
38 | }
39 |
40 | static void safeIncrementalCopy(byte[] dest, int matchOff, int dOff, int matchLen) {
41 | for (int i = 0; i < matchLen; ++i) {
42 | dest[dOff + i] = dest[matchOff + i];
43 | }
44 | }
45 |
46 | static void wildIncrementalCopy(byte[] dest, int matchOff, int dOff, int matchCopyEnd) {
47 | do {
48 | copy8Bytes(dest, matchOff, dest, dOff);
49 | matchOff += 8;
50 | dOff += 8;
51 | } while (dOff < matchCopyEnd);
52 | }
53 |
54 | static void copy8Bytes(byte[] src, int sOff, byte[] dest, int dOff) {
55 | for (int i = 0; i < 8; ++i) {
56 | dest[dOff + i] = src[sOff + i];
57 | }
58 | }
59 |
60 | static int commonBytes(byte[] b, int o1, int o2, int limit) {
61 | int count = 0;
62 | while (o2 < limit && b[o1++] == b[o2++]) {
63 | ++count;
64 | }
65 | return count;
66 | }
67 |
68 | static int commonBytesBackward(byte[] b, int o1, int o2, int l1, int l2) {
69 | int count = 0;
70 | while (o1 > l1 && o2 > l2 && b[--o1] == b[--o2]) {
71 | ++count;
72 | }
73 | return count;
74 | }
75 |
76 | static void safeArraycopy(byte[] src, int sOff, byte[] dest, int dOff, int len) {
77 | System.arraycopy(src, sOff, dest, dOff, len);
78 | }
79 |
80 | static void wildArraycopy(byte[] src, int sOff, byte[] dest, int dOff, int len) {
81 | try {
82 | for (int i = 0; i < len; i += 8) {
83 | copy8Bytes(src, sOff + i, dest, dOff + i);
84 | }
85 | } catch (ArrayIndexOutOfBoundsException e) {
86 | throw new LZ4Exception("Malformed input at offset " + sOff);
87 | }
88 | }
89 |
90 | static int encodeSequence(byte[] src, int anchor, int matchOff, int matchRef, int matchLen, byte[] dest, int dOff, int destEnd) {
91 | final int runLen = matchOff - anchor;
92 | final int tokenOff = dOff++;
93 |
94 | if (dOff + runLen + (2 + 1 + LAST_LITERALS) + (runLen >>> 8) > destEnd) {
95 | throw new LZ4Exception("maxDestLen is too small");
96 | }
97 |
98 | int token;
99 | if (runLen >= RUN_MASK) {
100 | token = (byte) (RUN_MASK << ML_BITS);
101 | dOff = writeLen(runLen - RUN_MASK, dest, dOff);
102 | } else {
103 | token = runLen << ML_BITS;
104 | }
105 |
106 | // copy literals
107 | wildArraycopy(src, anchor, dest, dOff, runLen);
108 | dOff += runLen;
109 |
110 | // encode offset
111 | final int matchDec = matchOff - matchRef;
112 | dest[dOff++] = (byte) matchDec;
113 | dest[dOff++] = (byte) (matchDec >>> 8);
114 |
115 | // encode match len
116 | matchLen -= 4;
117 | if (dOff + (1 + LAST_LITERALS) + (matchLen >>> 8) > destEnd) {
118 | throw new LZ4Exception("maxDestLen is too small");
119 | }
120 | if (matchLen >= ML_MASK) {
121 | token |= ML_MASK;
122 | dOff = writeLen(matchLen - RUN_MASK, dest, dOff);
123 | } else {
124 | token |= matchLen;
125 | }
126 |
127 | dest[tokenOff] = (byte) token;
128 |
129 | return dOff;
130 | }
131 |
132 | static int lastLiterals(byte[] src, int sOff, int srcLen, byte[] dest, int dOff, int destEnd) {
133 | final int runLen = srcLen;
134 |
135 | if (dOff + runLen + 1 + (runLen + 255 - RUN_MASK) / 255 > destEnd) {
136 | throw new LZ4Exception();
137 | }
138 |
139 | if (runLen >= RUN_MASK) {
140 | dest[dOff++] = (byte) (RUN_MASK << ML_BITS);
141 | dOff = writeLen(runLen - RUN_MASK, dest, dOff);
142 | } else {
143 | dest[dOff++] = (byte) (runLen << ML_BITS);
144 | }
145 | // copy literals
146 | System.arraycopy(src, sOff, dest, dOff, runLen);
147 | dOff += runLen;
148 |
149 | return dOff;
150 | }
151 |
152 | static int writeLen(int len, byte[] dest, int dOff) {
153 | while (len >= 0xFF) {
154 | dest[dOff++] = (byte) 0xFF;
155 | len -= 0xFF;
156 | }
157 | dest[dOff++] = (byte) len;
158 | return dOff;
159 | }
160 |
161 | static class Match {
162 | int start, ref, len;
163 |
164 | void fix(int correction) {
165 | start += correction;
166 | ref += correction;
167 | len -= correction;
168 | }
169 |
170 | int end() {
171 | return start + len;
172 | }
173 | }
174 |
175 | static void copyTo(Match m1, Match m2) {
176 | m2.len = m1.len;
177 | m2.start = m1.start;
178 | m2.ref = m1.ref;
179 | }
180 |
181 | }
182 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/LZ4UnknownSizeDecompressor.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.lz4;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | /**
20 | * @deprecated Use {@link LZ4SafeDecompressor} instead.
21 | */
22 | @Deprecated
23 | public interface LZ4UnknownSizeDecompressor {
24 |
25 | int decompress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen);
26 |
27 | int decompress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff);
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/LZ4Utils.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.lz4;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import static net.jpountz.lz4.LZ4Constants.HASH_LOG;
20 | import static net.jpountz.lz4.LZ4Constants.HASH_LOG_64K;
21 | import static net.jpountz.lz4.LZ4Constants.HASH_LOG_HC;
22 | import static net.jpountz.lz4.LZ4Constants.LAST_LITERALS;
23 | import static net.jpountz.lz4.LZ4Constants.MIN_MATCH;
24 | import static net.jpountz.lz4.LZ4Constants.ML_BITS;
25 | import static net.jpountz.lz4.LZ4Constants.ML_MASK;
26 | import static net.jpountz.lz4.LZ4Constants.RUN_MASK;
27 | import net.jpountz.util.SafeUtils;
28 |
29 | enum LZ4Utils {
30 | ;
31 |
32 | private static final int MAX_INPUT_SIZE = 0x7E000000;
33 |
34 | static int maxCompressedLength(int length) {
35 | if (length < 0) {
36 | throw new IllegalArgumentException("length must be >= 0, got " + length);
37 | } else if (length >= MAX_INPUT_SIZE) {
38 | throw new IllegalArgumentException("length must be < " + MAX_INPUT_SIZE);
39 | }
40 | return length + length / 255 + 16;
41 | }
42 |
43 | static int hash(int i) {
44 | return (i * -1640531535) >>> ((MIN_MATCH * 8) - HASH_LOG);
45 | }
46 |
47 | static int hash64k(int i) {
48 | return (i * -1640531535) >>> ((MIN_MATCH * 8) - HASH_LOG_64K);
49 | }
50 |
51 | static int hashHC(int i) {
52 | return (i * -1640531535) >>> ((MIN_MATCH * 8) - HASH_LOG_HC);
53 | }
54 |
55 | static class Match {
56 | int start, ref, len;
57 |
58 | void fix(int correction) {
59 | start += correction;
60 | ref += correction;
61 | len -= correction;
62 | }
63 |
64 | int end() {
65 | return start + len;
66 | }
67 | }
68 |
69 | static void copyTo(Match m1, Match m2) {
70 | m2.len = m1.len;
71 | m2.start = m1.start;
72 | m2.ref = m1.ref;
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/lz4/package.html:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 | LZ4 compression. The entry point of the API is the 23 | {@link net.jpountz.lz4.LZ4Factory} class, which gives access to 24 | {@link net.jpountz.lz4.LZ4Compressor compressors} and 25 | {@link net.jpountz.lz4.LZ4SafeDecompressor decompressors}.
26 | 27 | 28 |Sample usage:
29 | 30 |31 | LZ4Factory factory = LZ4Factory.fastestInstance(); 32 | 33 | byte[] data = "12345345234572".getBytes("UTF-8"); 34 | final int decompressedLength = data.length; 35 | 36 | // compress data 37 | LZ4Compressor compressor = factory.fastCompressor(); 38 | int maxCompressedLength = compressor.maxCompressedLength(decompressedLength); 39 | byte[] compressed = new byte[maxCompressedLength]; 40 | int compressedLength = compressor.compress(data, 0, decompressedLength, compressed, 0, maxCompressedLength); 41 | 42 | // decompress data 43 | // - method 1: when the decompressed length is known 44 | LZ4FastDecompressor decompressor = factory.fastDecompressor(); 45 | byte[] restored = new byte[decompressedLength]; 46 | int compressedLength2 = decompressor.decompress(compressed, 0, restored, 0, decompressedLength); 47 | // compressedLength == compressedLength2 48 | 49 | // - method 2: when the compressed length is known (a little slower) 50 | // the destination buffer needs to be over-sized 51 | LZ4SafeDecompressor decompressor2 = factory.safeDecompressor(); 52 | int decompressedLength2 = decompressor2.decompress(compressed, 0, compressedLength, restored, 0); 53 | // decompressedLength == decompressedLength2 54 |55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/java/net/jpountz/util/ByteBufferUtils.java: -------------------------------------------------------------------------------- 1 | package net.jpountz.util; 2 | 3 | /* 4 | * Copyright 2020 Adrien Grand and the lz4-java contributors. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import java.nio.ByteBuffer; 20 | import java.nio.ByteOrder; 21 | import java.nio.ReadOnlyBufferException; 22 | 23 | public enum ByteBufferUtils { 24 | ; 25 | 26 | public static void checkRange(ByteBuffer buf, int off, int len) { 27 | SafeUtils.checkLength(len); 28 | if (len > 0) { 29 | checkRange(buf, off); 30 | checkRange(buf, off + len - 1); 31 | } 32 | } 33 | 34 | public static void checkRange(ByteBuffer buf, int off) { 35 | if (off < 0 || off >= buf.capacity()) { 36 | throw new ArrayIndexOutOfBoundsException(off); 37 | } 38 | } 39 | 40 | public static ByteBuffer inLittleEndianOrder(ByteBuffer buf) { 41 | if (buf.order().equals(ByteOrder.LITTLE_ENDIAN)) { 42 | return buf; 43 | } else { 44 | return buf.duplicate().order(ByteOrder.LITTLE_ENDIAN); 45 | } 46 | } 47 | 48 | public static ByteBuffer inNativeByteOrder(ByteBuffer buf) { 49 | if (buf.order().equals(Utils.NATIVE_BYTE_ORDER)) { 50 | return buf; 51 | } else { 52 | return buf.duplicate().order(Utils.NATIVE_BYTE_ORDER); 53 | } 54 | } 55 | 56 | public static byte readByte(ByteBuffer buf, int i) { 57 | return buf.get(i); 58 | } 59 | 60 | public static void writeInt(ByteBuffer buf, int i, int v) { 61 | assert buf.order() == Utils.NATIVE_BYTE_ORDER; 62 | buf.putInt(i, v); 63 | } 64 | 65 | public static int readInt(ByteBuffer buf, int i) { 66 | assert buf.order() == Utils.NATIVE_BYTE_ORDER; 67 | return buf.getInt(i); 68 | } 69 | 70 | public static int readIntLE(ByteBuffer buf, int i) { 71 | assert buf.order() == ByteOrder.LITTLE_ENDIAN; 72 | return buf.getInt(i); 73 | } 74 | 75 | public static void writeLong(ByteBuffer buf, int i, long v) { 76 | assert buf.order() == Utils.NATIVE_BYTE_ORDER; 77 | buf.putLong(i, v); 78 | } 79 | 80 | public static long readLong(ByteBuffer buf, int i) { 81 | assert buf.order() == Utils.NATIVE_BYTE_ORDER; 82 | return buf.getLong(i); 83 | } 84 | 85 | public static long readLongLE(ByteBuffer buf, int i) { 86 | assert buf.order() == ByteOrder.LITTLE_ENDIAN; 87 | return buf.getLong(i); 88 | } 89 | 90 | public static void writeByte(ByteBuffer dest, int off, int i) { 91 | dest.put(off, (byte) i); 92 | } 93 | 94 | public static void writeShortLE(ByteBuffer dest, int off, int i) { 95 | dest.put(off, (byte) i); 96 | dest.put(off + 1, (byte) (i >>> 8)); 97 | } 98 | 99 | public static void checkNotReadOnly(ByteBuffer buffer) { 100 | if (buffer.isReadOnly()) { 101 | throw new ReadOnlyBufferException(); 102 | } 103 | } 104 | 105 | public static int readShortLE(ByteBuffer buf, int i) { 106 | return (buf.get(i) & 0xFF) | ((buf.get(i+1) & 0xFF) << 8); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/java/net/jpountz/util/Native.java: -------------------------------------------------------------------------------- 1 | package net.jpountz.util; 2 | 3 | /* 4 | * Copyright 2020 Adrien Grand and the lz4-java contributors. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import java.io.File; 20 | import java.io.FileOutputStream; 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.io.FilenameFilter; 24 | 25 | /** FOR INTERNAL USE ONLY */ 26 | public enum Native { 27 | ; 28 | 29 | private enum OS { 30 | // Even on Windows, the default compiler from cpptasks (gcc) uses .so as a shared lib extension 31 | WINDOWS("win32", "so"), LINUX("linux", "so"), MAC("darwin", "dylib"), SOLARIS("solaris", "so"); 32 | public final String name, libExtension; 33 | 34 | private OS(String name, String libExtension) { 35 | this.name = name; 36 | this.libExtension = libExtension; 37 | } 38 | } 39 | 40 | private static String arch() { 41 | return System.getProperty("os.arch"); 42 | } 43 | 44 | private static OS os() { 45 | String osName = System.getProperty("os.name"); 46 | if (osName.contains("Linux")) { 47 | return OS.LINUX; 48 | } else if (osName.contains("Mac")) { 49 | return OS.MAC; 50 | } else if (osName.contains("Windows")) { 51 | return OS.WINDOWS; 52 | } else if (osName.contains("Solaris") || osName.contains("SunOS")) { 53 | return OS.SOLARIS; 54 | } else { 55 | throw new UnsupportedOperationException("Unsupported operating system: " 56 | + osName); 57 | } 58 | } 59 | 60 | private static String resourceName() { 61 | OS os = os(); 62 | String packagePrefix = Native.class.getPackage().getName().replace('.', '/'); 63 | 64 | return "/" + packagePrefix + "/" + os.name + "/" + arch() + "/liblz4-java." + os.libExtension; 65 | } 66 | 67 | private static boolean loaded = false; 68 | 69 | public static synchronized boolean isLoaded() { 70 | return loaded; 71 | } 72 | 73 | private static void cleanupOldTempLibs() { 74 | String tempFolder = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath(); 75 | File dir = new File(tempFolder); 76 | 77 | File[] tempLibFiles = dir.listFiles(new FilenameFilter() { 78 | private final String searchPattern = "liblz4-java-"; 79 | public boolean accept(File dir, String name) { 80 | return name.startsWith(searchPattern) && !name.endsWith(".lck"); 81 | } 82 | }); 83 | if(tempLibFiles != null) { 84 | for(File tempLibFile : tempLibFiles) { 85 | File lckFile = new File(tempLibFile.getAbsolutePath() + ".lck"); 86 | if(!lckFile.exists()) { 87 | try { 88 | tempLibFile.delete(); 89 | } 90 | catch(SecurityException e) { 91 | System.err.println("Failed to delete old temp lib" + e.getMessage()); 92 | } 93 | } 94 | } 95 | } 96 | } 97 | 98 | public static synchronized void load() { 99 | if (loaded) { 100 | return; 101 | } 102 | 103 | cleanupOldTempLibs(); 104 | 105 | // Try to load lz4-java (liblz4-java.so on Linux) from the java.library.path. 106 | try { 107 | System.loadLibrary("lz4-java"); 108 | loaded = true; 109 | return; 110 | } catch (UnsatisfiedLinkError ex) { 111 | // Doesn't exist, so proceed to loading bundled library. 112 | } 113 | 114 | String resourceName = resourceName(); 115 | InputStream is = Native.class.getResourceAsStream(resourceName); 116 | if (is == null) { 117 | throw new UnsupportedOperationException("Unsupported OS/arch, cannot find " + resourceName + ". Please try building from source."); 118 | } 119 | File tempLib = null; 120 | File tempLibLock = null; 121 | try { 122 | // Create the .lck file first to avoid a race condition 123 | // with other concurrently running Java processes using lz4-java. 124 | tempLibLock = File.createTempFile("liblz4-java-", "." + os().libExtension + ".lck"); 125 | tempLib = new File(tempLibLock.getAbsolutePath().replaceFirst(".lck$", "")); 126 | // copy to tempLib 127 | try (FileOutputStream out = new FileOutputStream(tempLib)) { 128 | byte[] buf = new byte[4096]; 129 | while (true) { 130 | int read = is.read(buf); 131 | if (read == -1) { 132 | break; 133 | } 134 | out.write(buf, 0, read); 135 | } 136 | } 137 | System.load(tempLib.getAbsolutePath()); 138 | loaded = true; 139 | } catch (IOException e) { 140 | throw new ExceptionInInitializerError("Cannot unpack liblz4-java: " + e); 141 | } finally { 142 | if (!loaded) { 143 | if (tempLib != null && tempLib.exists()) { 144 | if (!tempLib.delete()) { 145 | throw new ExceptionInInitializerError("Cannot unpack liblz4-java / cannot delete a temporary native library " + tempLib); 146 | } 147 | } 148 | if (tempLibLock != null && tempLibLock.exists()) { 149 | if (!tempLibLock.delete()) { 150 | throw new ExceptionInInitializerError("Cannot unpack liblz4-java / cannot delete a temporary lock file " + tempLibLock); 151 | } 152 | } 153 | } else { 154 | final String keepEnv = System.getenv("LZ4JAVA_KEEP_TEMP_JNI_LIB"); 155 | final String keepProp = System.getProperty("lz4java.jnilib.temp.keep"); 156 | if ((keepEnv == null || !keepEnv.equals("true")) && 157 | (keepProp == null || !keepProp.equals("true"))) 158 | tempLib.deleteOnExit(); 159 | tempLibLock.deleteOnExit(); 160 | } 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/java/net/jpountz/util/SafeUtils.java: -------------------------------------------------------------------------------- 1 | package net.jpountz.util; 2 | 3 | /* 4 | * Copyright 2020 Adrien Grand and the lz4-java contributors. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import java.nio.ByteOrder; 20 | 21 | public enum SafeUtils { 22 | ; 23 | 24 | public static void checkRange(byte[] buf, int off) { 25 | if (off < 0 || off >= buf.length) { 26 | throw new ArrayIndexOutOfBoundsException(off); 27 | } 28 | } 29 | 30 | public static void checkRange(byte[] buf, int off, int len) { 31 | checkLength(len); 32 | if (len > 0) { 33 | checkRange(buf, off); 34 | checkRange(buf, off + len - 1); 35 | } 36 | } 37 | 38 | public static void checkLength(int len) { 39 | if (len < 0) { 40 | throw new IllegalArgumentException("lengths must be >= 0"); 41 | } 42 | } 43 | 44 | public static byte readByte(byte[] buf, int i) { 45 | return buf[i]; 46 | } 47 | 48 | public static int readIntBE(byte[] buf, int i) { 49 | return ((buf[i] & 0xFF) << 24) | ((buf[i+1] & 0xFF) << 16) | ((buf[i+2] & 0xFF) << 8) | (buf[i+3] & 0xFF); 50 | } 51 | 52 | public static int readIntLE(byte[] buf, int i) { 53 | return (buf[i] & 0xFF) | ((buf[i+1] & 0xFF) << 8) | ((buf[i+2] & 0xFF) << 16) | ((buf[i+3] & 0xFF) << 24); 54 | } 55 | 56 | public static int readInt(byte[] buf, int i) { 57 | if (Utils.NATIVE_BYTE_ORDER == ByteOrder.BIG_ENDIAN) { 58 | return readIntBE(buf, i); 59 | } else { 60 | return readIntLE(buf, i); 61 | } 62 | } 63 | 64 | public static long readLongLE(byte[] buf, int i) { 65 | return (buf[i] & 0xFFL) | ((buf[i+1] & 0xFFL) << 8) | ((buf[i+2] & 0xFFL) << 16) | ((buf[i+3] & 0xFFL) << 24) 66 | | ((buf[i+4] & 0xFFL) << 32) | ((buf[i+5] & 0xFFL) << 40) | ((buf[i+6] & 0xFFL) << 48) | ((buf[i+7] & 0xFFL) << 56); 67 | } 68 | 69 | public static void writeShortLE(byte[] buf, int off, int v) { 70 | buf[off++] = (byte) v; 71 | buf[off++] = (byte) (v >>> 8); 72 | } 73 | 74 | public static void writeInt(int[] buf, int off, int v) { 75 | buf[off] = v; 76 | } 77 | 78 | public static int readInt(int[] buf, int off) { 79 | return buf[off]; 80 | } 81 | 82 | public static void writeByte(byte[] dest, int off, int i) { 83 | dest[off] = (byte) i; 84 | } 85 | 86 | public static void writeShort(short[] buf, int off, int v) { 87 | buf[off] = (short) v; 88 | } 89 | 90 | public static int readShortLE(byte[] buf, int i) { 91 | return (buf[i] & 0xFF) | ((buf[i+1] & 0xFF) << 8); 92 | } 93 | 94 | public static int readShort(short[] buf, int off) { 95 | return buf[off] & 0xFFFF; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/java/net/jpountz/util/Utils.java: -------------------------------------------------------------------------------- 1 | package net.jpountz.util; 2 | 3 | /* 4 | * Copyright 2020 Adrien Grand and the lz4-java contributors. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import java.nio.ByteOrder; 20 | 21 | public enum Utils { 22 | ; 23 | 24 | public static final ByteOrder NATIVE_BYTE_ORDER = ByteOrder.nativeOrder(); 25 | 26 | private static final boolean unalignedAccessAllowed; 27 | static { 28 | String arch = System.getProperty("os.arch"); 29 | unalignedAccessAllowed = arch.equals("i386") || arch.equals("x86") 30 | || arch.equals("amd64") || arch.equals("x86_64") 31 | || arch.equals("aarch64") || arch.equals("ppc64le"); 32 | } 33 | 34 | public static boolean isUnalignedAccessAllowed() { 35 | return unalignedAccessAllowed; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/java/net/jpountz/util/package.html: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 |
Utility classes.
23 | 24 | 25 | -------------------------------------------------------------------------------- /src/java/net/jpountz/xxhash/AbstractStreamingXXHash32Java.java: -------------------------------------------------------------------------------- 1 | package net.jpountz.xxhash; 2 | 3 | /* 4 | * Copyright 2020 Adrien Grand and the lz4-java contributors. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import static net.jpountz.xxhash.XXHashConstants.PRIME1; 20 | import static net.jpountz.xxhash.XXHashConstants.PRIME2; 21 | 22 | abstract class AbstractStreamingXXHash32Java extends StreamingXXHash32 { 23 | 24 | int v1, v2, v3, v4, memSize; 25 | long totalLen; 26 | final byte[] memory; 27 | 28 | AbstractStreamingXXHash32Java(int seed) { 29 | super(seed); 30 | memory = new byte[16]; 31 | reset(); 32 | } 33 | 34 | @Override 35 | public void reset() { 36 | v1 = seed + PRIME1 + PRIME2; 37 | v2 = seed + PRIME2; 38 | v3 = seed + 0; 39 | v4 = seed - PRIME1; 40 | totalLen = 0; 41 | memSize = 0; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/java/net/jpountz/xxhash/AbstractStreamingXXHash64Java.java: -------------------------------------------------------------------------------- 1 | package net.jpountz.xxhash; 2 | 3 | /* 4 | * Copyright 2020 Linnaea Von Lavia and the lz4-java contributors. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import static net.jpountz.xxhash.XXHashConstants.PRIME64_1; 20 | import static net.jpountz.xxhash.XXHashConstants.PRIME64_2; 21 | 22 | abstract class AbstractStreamingXXHash64Java extends StreamingXXHash64 { 23 | 24 | int memSize; 25 | long v1, v2, v3, v4; 26 | long totalLen; 27 | final byte[] memory; 28 | 29 | AbstractStreamingXXHash64Java(long seed) { 30 | super(seed); 31 | memory = new byte[32]; 32 | reset(); 33 | } 34 | 35 | @Override 36 | public void reset() { 37 | v1 = seed + PRIME64_1 + PRIME64_2; 38 | v2 = seed + PRIME64_2; 39 | v3 = seed + 0; 40 | v4 = seed - PRIME64_1; 41 | totalLen = 0; 42 | memSize = 0; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/java/net/jpountz/xxhash/StreamingXXHash32.java: -------------------------------------------------------------------------------- 1 | package net.jpountz.xxhash; 2 | 3 | import java.util.zip.Checksum; 4 | import java.io.Closeable; 5 | 6 | /* 7 | * Copyright 2020 Adrien Grand and the lz4-java contributors. 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | */ 21 | 22 | 23 | 24 | /** 25 | * Streaming interface for {@link XXHash32}. 26 | *27 | * This API is compatible with the {@link XXHash32 block API} and the following 28 | * code samples are equivalent: 29 | *
30 | * int hash(XXHashFactory xxhashFactory, byte[] buf, int off, int len, int seed) { 31 | * return xxhashFactory.hash32().hash(buf, off, len, seed); 32 | * } 33 | *34 | *
35 | * int hash(XXHashFactory xxhashFactory, byte[] buf, int off, int len, int seed) { 36 | * StreamingXXHash32 sh32 = xxhashFactory.newStreamingHash32(seed); 37 | * sh32.update(buf, off, len); 38 | * return sh32.getValue(); 39 | * } 40 | *41 | *
42 | * Instances of this class are not thread-safe. 43 | */ 44 | public abstract class StreamingXXHash32 implements Closeable { 45 | 46 | interface Factory { 47 | 48 | StreamingXXHash32 newStreamingHash(int seed); 49 | 50 | } 51 | 52 | final int seed; 53 | 54 | StreamingXXHash32(int seed) { 55 | this.seed = seed; 56 | } 57 | 58 | /** 59 | * Returns the value of the checksum. 60 | * 61 | * @return the checksum 62 | */ 63 | public abstract int getValue(); 64 | 65 | /** 66 | * Updates the value of the hash with buf[off:off+len]. 67 | * 68 | * @param buf the input data 69 | * @param off the start offset in buf 70 | * @param len the number of bytes to hash 71 | */ 72 | public abstract void update(byte[] buf, int off, int len); 73 | 74 | /** 75 | * Resets this instance to the state it had right after instantiation. The 76 | * seed remains unchanged. 77 | */ 78 | public abstract void reset(); 79 | 80 | /** 81 | * Releases any system resources associated with this instance. 82 | * It is not mandatory to call this method after using this instance 83 | * because the system resources are released anyway when this instance 84 | * is reclaimed by GC. 85 | */ 86 | @Override 87 | public void close() { 88 | } 89 | 90 | @Override 91 | public String toString() { 92 | return getClass().getSimpleName() + "(seed=" + seed + ")"; 93 | } 94 | 95 | /** 96 | * Returns a {@link Checksum} view of this instance. Modifications to the view 97 | * will modify this instance too and vice-versa. 98 | * 99 | * @return the {@link Checksum} object representing this instance 100 | */ 101 | public final Checksum asChecksum() { 102 | return new Checksum() { 103 | 104 | @Override 105 | public long getValue() { 106 | return StreamingXXHash32.this.getValue() & 0xFFFFFFFL; 107 | } 108 | 109 | @Override 110 | public void reset() { 111 | StreamingXXHash32.this.reset(); 112 | } 113 | 114 | @Override 115 | public void update(int b) { 116 | StreamingXXHash32.this.update(new byte[] {(byte) b}, 0, 1); 117 | } 118 | 119 | @Override 120 | public void update(byte[] b, int off, int len) { 121 | StreamingXXHash32.this.update(b, off, len); 122 | } 123 | 124 | @Override 125 | public String toString() { 126 | return StreamingXXHash32.this.toString(); 127 | } 128 | 129 | }; 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/java/net/jpountz/xxhash/StreamingXXHash32JNI.java: -------------------------------------------------------------------------------- 1 | package net.jpountz.xxhash; 2 | 3 | /* 4 | * Copyright 2020 Adrien Grand and the lz4-java contributors. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | /** 20 | * Fast {@link StreamingXXHash32} implemented with JNI bindings. 21 | * The methods are synchronized to avoid a race condition 22 | * between freeing the native memory in finalize() and using it in 23 | * reset(), getValue(), and update(). Note that GC can call finalize() 24 | * after calling checkState() and before using XXHashJNI if the caller 25 | * does not retain a reference to this object. 26 | */ 27 | final class StreamingXXHash32JNI extends StreamingXXHash32 { 28 | 29 | static class Factory implements StreamingXXHash32.Factory { 30 | 31 | public static final StreamingXXHash32.Factory INSTANCE = new Factory(); 32 | 33 | @Override 34 | public StreamingXXHash32 newStreamingHash(int seed) { 35 | return new StreamingXXHash32JNI(seed); 36 | } 37 | 38 | } 39 | 40 | private long state; 41 | 42 | StreamingXXHash32JNI(int seed) { 43 | super(seed); 44 | state = XXHashJNI.XXH32_init(seed); 45 | } 46 | 47 | private void checkState() { 48 | if (state == 0) { 49 | throw new AssertionError("Already finalized"); 50 | } 51 | } 52 | 53 | @Override 54 | public synchronized void reset() { 55 | checkState(); 56 | XXHashJNI.XXH32_free(state); 57 | state = XXHashJNI.XXH32_init(seed); 58 | } 59 | 60 | @Override 61 | public synchronized int getValue() { 62 | checkState(); 63 | return XXHashJNI.XXH32_digest(state); 64 | } 65 | 66 | @Override 67 | public synchronized void update(byte[] bytes, int off, int len) { 68 | checkState(); 69 | XXHashJNI.XXH32_update(state, bytes, off, len); 70 | } 71 | 72 | @Override 73 | public synchronized void close() { 74 | if (state != 0) { 75 | super.close(); 76 | XXHashJNI.XXH32_free(state); 77 | state = 0; 78 | } 79 | } 80 | 81 | @Override 82 | protected synchronized void finalize() throws Throwable { 83 | super.finalize(); 84 | if (state != 0) { 85 | // free memory 86 | XXHashJNI.XXH32_free(state); 87 | state = 0; 88 | } 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/java/net/jpountz/xxhash/StreamingXXHash64.java: -------------------------------------------------------------------------------- 1 | package net.jpountz.xxhash; 2 | 3 | import java.util.zip.Checksum; 4 | import java.io.Closeable; 5 | 6 | /* 7 | * Copyright 2020 Linnaea Von Lavia and the lz4-java contributors. 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | */ 21 | 22 | 23 | 24 | /** 25 | * Streaming interface for {@link XXHash64}. 26 | *
27 | * This API is compatible with the {@link XXHash64 block API} and the following 28 | * code samples are equivalent: 29 | *
30 | * long hash(XXHashFactory xxhashFactory, byte[] buf, int off, int len, long seed) { 31 | * return xxhashFactory.hash64().hash(buf, off, len, seed); 32 | * } 33 | *34 | *
35 | * long hash(XXHashFactory xxhashFactory, byte[] buf, int off, int len, long seed) { 36 | * StreamingXXHash64 sh64 = xxhashFactory.newStreamingHash64(seed); 37 | * sh64.update(buf, off, len); 38 | * return sh64.getValue(); 39 | * } 40 | *41 | *
42 | * Instances of this class are not thread-safe. 43 | */ 44 | public abstract class StreamingXXHash64 implements Closeable { 45 | 46 | interface Factory { 47 | 48 | StreamingXXHash64 newStreamingHash(long seed); 49 | 50 | } 51 | 52 | final long seed; 53 | 54 | StreamingXXHash64(long seed) { 55 | this.seed = seed; 56 | } 57 | 58 | /** 59 | * Returns the value of the checksum. 60 | * 61 | * @return the checksum 62 | */ 63 | public abstract long getValue(); 64 | 65 | /** 66 | * Updates the value of the hash with buf[off:off+len]. 67 | * 68 | * @param buf the input data 69 | * @param off the start offset in buf 70 | * @param len the number of bytes to hash 71 | */ 72 | public abstract void update(byte[] buf, int off, int len); 73 | 74 | /** 75 | * Resets this instance to the state it had right after instantiation. The 76 | * seed remains unchanged. 77 | */ 78 | public abstract void reset(); 79 | 80 | /** 81 | * Releases any system resources associated with this instance. 82 | * It is not mandatory to call this method after using this instance 83 | * because the system resources are released anyway when this instance 84 | * is reclaimed by GC. 85 | */ 86 | @Override 87 | public void close() { 88 | } 89 | 90 | @Override 91 | public String toString() { 92 | return getClass().getSimpleName() + "(seed=" + seed + ")"; 93 | } 94 | 95 | /** 96 | * Returns a {@link Checksum} view of this instance. Modifications to the view 97 | * will modify this instance too and vice-versa. 98 | * 99 | * @return the {@link Checksum} object representing this instance 100 | */ 101 | public final Checksum asChecksum() { 102 | return new Checksum() { 103 | 104 | @Override 105 | public long getValue() { 106 | return StreamingXXHash64.this.getValue(); 107 | } 108 | 109 | @Override 110 | public void reset() { 111 | StreamingXXHash64.this.reset(); 112 | } 113 | 114 | @Override 115 | public void update(int b) { 116 | StreamingXXHash64.this.update(new byte[] {(byte) b}, 0, 1); 117 | } 118 | 119 | @Override 120 | public void update(byte[] b, int off, int len) { 121 | StreamingXXHash64.this.update(b, off, len); 122 | } 123 | 124 | @Override 125 | public String toString() { 126 | return StreamingXXHash64.this.toString(); 127 | } 128 | 129 | }; 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/java/net/jpountz/xxhash/StreamingXXHash64JNI.java: -------------------------------------------------------------------------------- 1 | package net.jpountz.xxhash; 2 | 3 | /* 4 | * Copyright 2020 Linnaea Von Lavia and the lz4-java contributors. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | 20 | /** 21 | * Fast {@link StreamingXXHash64} implemented with JNI bindings. 22 | * The methods are synchronized to avoid a race condition 23 | * between freeing the native memory in finalize() and using it in 24 | * reset(), getValue(), and update(). Note that GC can call finalize() 25 | * after calling checkState() and before using XXHashJNI if the caller 26 | * does not retain a reference to this object. 27 | */ 28 | final class StreamingXXHash64JNI extends StreamingXXHash64 { 29 | 30 | static class Factory implements StreamingXXHash64.Factory { 31 | 32 | public static final StreamingXXHash64.Factory INSTANCE = new Factory(); 33 | 34 | @Override 35 | public StreamingXXHash64 newStreamingHash(long seed) { 36 | return new StreamingXXHash64JNI(seed); 37 | } 38 | 39 | } 40 | 41 | private long state; 42 | 43 | StreamingXXHash64JNI(long seed) { 44 | super(seed); 45 | state = XXHashJNI.XXH64_init(seed); 46 | } 47 | 48 | private void checkState() { 49 | if (state == 0) { 50 | throw new AssertionError("Already finalized"); 51 | } 52 | } 53 | 54 | @Override 55 | public synchronized void reset() { 56 | checkState(); 57 | XXHashJNI.XXH64_free(state); 58 | state = XXHashJNI.XXH64_init(seed); 59 | } 60 | 61 | @Override 62 | public synchronized long getValue() { 63 | checkState(); 64 | return XXHashJNI.XXH64_digest(state); 65 | } 66 | 67 | @Override 68 | public synchronized void update(byte[] bytes, int off, int len) { 69 | checkState(); 70 | XXHashJNI.XXH64_update(state, bytes, off, len); 71 | } 72 | 73 | @Override 74 | public synchronized void close() { 75 | if (state != 0) { 76 | super.close(); 77 | XXHashJNI.XXH64_free(state); 78 | state = 0; 79 | } 80 | } 81 | 82 | 83 | @Override 84 | protected synchronized void finalize() throws Throwable { 85 | super.finalize(); 86 | if (state != 0) { 87 | // free memory 88 | XXHashJNI.XXH64_free(state); 89 | state = 0; 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/java/net/jpountz/xxhash/XXHash32.java: -------------------------------------------------------------------------------- 1 | package net.jpountz.xxhash; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | /* 6 | * Copyright 2020 Adrien Grand and the lz4-java contributors. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | /** 22 | * A 32-bits hash. 23 | *
24 | * Instances of this class are thread-safe.
25 | */
26 | public abstract class XXHash32 {
27 |
28 | /**
29 | * Computes the 32-bits hash of buf[off:off+len]
using seed
30 | * seed
.
31 | *
32 | * @param buf the input data
33 | * @param off the start offset in buf
34 | * @param len the number of bytes to hash
35 | * @param seed the seed to use
36 | * @return the hash value
37 | */
38 | public abstract int hash(byte[] buf, int off, int len, int seed);
39 |
40 | /**
41 | * Computes the hash of the given slice of the {@link ByteBuffer}.
42 | * {@link ByteBuffer#position() position} and {@link ByteBuffer#limit() limit}
43 | * are not modified.
44 | *
45 | * @param buf the input data
46 | * @param off the start offset in buf
47 | * @param len the number of bytes to hash
48 | * @param seed the seed to use
49 | * @return the hash value
50 | */
51 | public abstract int hash(ByteBuffer buf, int off, int len, int seed);
52 |
53 | /**
54 | * Computes the hash of the given {@link ByteBuffer}. The
55 | * {@link ByteBuffer#position() position} is moved in order to reflect bytes
56 | * which have been read.
57 | *
58 | * @param buf the input data
59 | * @param seed the seed to use
60 | * @return the hash value
61 | */
62 | public final int hash(ByteBuffer buf, int seed) {
63 | final int hash = hash(buf, buf.position(), buf.remaining(), seed);
64 | buf.position(buf.limit());
65 | return hash;
66 | }
67 |
68 | @Override
69 | public String toString() {
70 | return getClass().getSimpleName();
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/xxhash/XXHash32JNI.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.xxhash;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import static net.jpountz.util.ByteBufferUtils.checkRange;
20 | import static net.jpountz.util.SafeUtils.checkRange;
21 |
22 | import java.nio.ByteBuffer;
23 |
24 | final class XXHash32JNI extends XXHash32 {
25 |
26 | public static final XXHash32 INSTANCE = new XXHash32JNI();
27 | private static XXHash32 SAFE_INSTANCE;
28 |
29 | @Override
30 | public int hash(byte[] buf, int off, int len, int seed) {
31 | checkRange(buf, off, len);
32 | return XXHashJNI.XXH32(buf, off, len, seed);
33 | }
34 |
35 | @Override
36 | public int hash(ByteBuffer buf, int off, int len, int seed) {
37 | if (buf.isDirect()) {
38 | checkRange(buf, off, len);
39 | return XXHashJNI.XXH32BB(buf, off, len, seed);
40 | } else if (buf.hasArray()) {
41 | return hash(buf.array(), off + buf.arrayOffset(), len, seed);
42 | } else {
43 | XXHash32 safeInstance = SAFE_INSTANCE;
44 | if (safeInstance == null) {
45 | safeInstance = SAFE_INSTANCE = XXHashFactory.safeInstance().hash32();
46 | }
47 | return safeInstance.hash(buf, off, len, seed);
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/xxhash/XXHash64.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.xxhash;
2 |
3 | import java.nio.ByteBuffer;
4 |
5 | /*
6 | * Copyright 2020 Linnaea Von Lavia and the lz4-java contributors.
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 |
21 | /**
22 | * A 64-bits hash.
23 | *
24 | * Instances of this class are thread-safe.
25 | */
26 | public abstract class XXHash64 {
27 |
28 | /**
29 | * Computes the 64-bits hash of buf[off:off+len]
using seed
30 | * seed
.
31 | *
32 | * @param buf the input data
33 | * @param off the start offset in buf
34 | * @param len the number of bytes to hash
35 | * @param seed the seed to use
36 | * @return the hash value
37 | */
38 | public abstract long hash(byte[] buf, int off, int len, long seed);
39 |
40 | /**
41 | * Computes the hash of the given slice of the {@link ByteBuffer}.
42 | * {@link ByteBuffer#position() position} and {@link ByteBuffer#limit() limit}
43 | * are not modified.
44 | *
45 | * @param buf the input data
46 | * @param off the start offset in buf
47 | * @param len the number of bytes to hash
48 | * @param seed the seed to use
49 | * @return the hash value
50 | */
51 | public abstract long hash(ByteBuffer buf, int off, int len, long seed);
52 |
53 | /**
54 | * Computes the hash of the given {@link ByteBuffer}. The
55 | * {@link ByteBuffer#position() position} is moved in order to reflect bytes
56 | * which have been read.
57 | *
58 | * @param buf the input data
59 | * @param seed the seed to use
60 | * @return the hash value
61 | */
62 | public final long hash(ByteBuffer buf, long seed) {
63 | final long hash = hash(buf, buf.position(), buf.remaining(), seed);
64 | buf.position(buf.limit());
65 | return hash;
66 | }
67 |
68 | @Override
69 | public String toString() {
70 | return getClass().getSimpleName();
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/xxhash/XXHash64JNI.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.xxhash;
2 |
3 | /*
4 | * Copyright 2020 Linnaea Von Lavia and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import static net.jpountz.util.ByteBufferUtils.checkRange;
20 | import static net.jpountz.util.SafeUtils.checkRange;
21 |
22 | import java.nio.ByteBuffer;
23 |
24 | final class XXHash64JNI extends XXHash64 {
25 |
26 | public static final XXHash64 INSTANCE = new XXHash64JNI();
27 | private static XXHash64 SAFE_INSTANCE;
28 |
29 | @Override
30 | public long hash(byte[] buf, int off, int len, long seed) {
31 | checkRange(buf, off, len);
32 | return XXHashJNI.XXH64(buf, off, len, seed);
33 | }
34 |
35 | @Override
36 | public long hash(ByteBuffer buf, int off, int len, long seed) {
37 | if (buf.isDirect()) {
38 | checkRange(buf, off, len);
39 | return XXHashJNI.XXH64BB(buf, off, len, seed);
40 | } else if (buf.hasArray()) {
41 | return hash(buf.array(), off + buf.arrayOffset(), len, seed);
42 | } else {
43 | XXHash64 safeInstance = SAFE_INSTANCE;
44 | if (safeInstance == null) {
45 | safeInstance = SAFE_INSTANCE = XXHashFactory.safeInstance().hash64();
46 | }
47 | return safeInstance.hash(buf, off, len, seed);
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/xxhash/XXHashConstants.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.xxhash;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | enum XXHashConstants {
20 | ;
21 |
22 | static final int PRIME1 = -1640531535;
23 | static final int PRIME2 = -2048144777;
24 | static final int PRIME3 = -1028477379;
25 | static final int PRIME4 = 668265263;
26 | static final int PRIME5 = 374761393;
27 |
28 | static final long PRIME64_1 = -7046029288634856825L; //11400714785074694791
29 | static final long PRIME64_2 = -4417276706812531889L; //14029467366897019727
30 | static final long PRIME64_3 = 1609587929392839161L;
31 | static final long PRIME64_4 = -8796714831421723037L; //9650029242287828579
32 | static final long PRIME64_5 = 2870177450012600261L;
33 | }
34 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/xxhash/XXHashJNI.java:
--------------------------------------------------------------------------------
1 | package net.jpountz.xxhash;
2 |
3 | /*
4 | * Copyright 2020 Adrien Grand and the lz4-java contributors.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.nio.ByteBuffer;
20 |
21 | import net.jpountz.util.Native;
22 |
23 | enum XXHashJNI {
24 | ;
25 |
26 | static {
27 | Native.load();
28 | init();
29 | }
30 |
31 | private static native void init();
32 | static native int XXH32(byte[] input, int offset, int len, int seed);
33 | static native int XXH32BB(ByteBuffer input, int offset, int len, int seed);
34 | static native long XXH32_init(int seed);
35 | static native void XXH32_update(long state, byte[] input, int offset, int len);
36 | static native int XXH32_digest(long state);
37 | static native void XXH32_free(long state);
38 |
39 | static native long XXH64(byte[] input, int offset, int len, long seed);
40 | static native long XXH64BB(ByteBuffer input, int offset, int len, long seed);
41 | static native long XXH64_init(long seed);
42 | static native void XXH64_update(long state, byte[] input, int offset, int len);
43 | static native long XXH64_digest(long state);
44 | static native void XXH64_free(long state);
45 | }
46 |
--------------------------------------------------------------------------------
/src/java/net/jpountz/xxhash/package.html:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
xxhash hashing. This package supports both block hashing via 23 | {@link net.jpountz.xxhash.XXHash32} and streaming hashing via 24 | {@link net.jpountz.xxhash.StreamingXXHash32}. Have a look at 25 | {@link net.jpountz.xxhash.XXHashFactory} to know how to get instances of these 26 | interfaces.
27 | 28 |Streaming hashing is a little slower but doesn't require to load the whole 29 | stream into memory.
30 | 31 |Sample block usage:
32 | 33 |34 | XXHashFactory factory = XXHashFactory.fastestInstance(); 35 | 36 | byte[] data = "12345345234572".getBytes("UTF-8"); 37 | 38 | XXHash32 hash32 = factory.hash32(); 39 | int seed = 0x9747b28c; // used to initialize the hash value, use whatever 40 | // value you want, but always the same 41 | int hash = hash32.hash(data, 0, data.length, seed); 42 |43 | 44 |
Sample streaming usage:
45 | 46 |47 | XXHashFactory factory = XXHashFactory.fastestInstance(); 48 | 49 | byte[] data = "12345345234572".getBytes("UTF-8"); 50 | ByteArrayInputStream in = new ByteArrayInputStream(data); 51 | 52 | int seed = 0x9747b28c; // used to initialize the hash value, use whatever 53 | // value you want, but always the same 54 | StreamingXXHash32 hash32 = factory.newStreamingHash32(seed); 55 | byte[] buf = new byte[8]; // for real-world usage, use a larger buffer, like 8192 bytes 56 | for (;;) { 57 | int read = in.read(buf); 58 | if (read == -1) { 59 | break; 60 | } 61 | hash32.update(buf, 0, read); 62 | } 63 | int hash = hash32.getValue(); 64 |65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/java/overview.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 |
LZ4 - Java is a Java port of the popular 23 | lz4 compression algorithms and 24 | xxHash hashing algorithm.
25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/jni/net_jpountz_lz4_LZ4JNI.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Adrien Grand and the lz4-java contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "lz4.h" 18 | #include "lz4hc.h" 19 | #include "net_jpountz_lz4_LZ4JNI.h" 20 | 21 | static jclass OutOfMemoryError; 22 | 23 | /* 24 | * Class: net_jpountz_lz4_LZ4 25 | * Method: init 26 | * Signature: ()V 27 | */ 28 | JNIEXPORT void JNICALL Java_net_jpountz_lz4_LZ4JNI_init 29 | (JNIEnv *env, jclass cls) { 30 | OutOfMemoryError = (*env)->FindClass(env, "java/lang/OutOfMemoryError"); 31 | } 32 | 33 | static void throw_OOM(JNIEnv *env) { 34 | (*env)->ThrowNew(env, OutOfMemoryError, "Out of memory"); 35 | } 36 | 37 | /* 38 | * Class: net_jpountz_lz4_LZ4JNI 39 | * Method: LZ4_compress_limitedOutput 40 | * Signature: ([BLjava/nio/ByteBuffer;II[BLjava/nio/ByteBuffer;II)I 41 | * 42 | * Though LZ4_compress_limitedOutput is no longer called as it was deprecated, 43 | * keep the method name of LZ4_compress_limitedOutput for backward compatibility, 44 | * so that the old JNI bindings in src/resources can still be used. 45 | */ 46 | JNIEXPORT jint JNICALL Java_net_jpountz_lz4_LZ4JNI_LZ4_1compress_1limitedOutput 47 | (JNIEnv *env, jclass cls, jbyteArray srcArray, jobject srcBuffer, jint srcOff, jint srcLen, jbyteArray destArray, jobject destBuffer, jint destOff, jint maxDestLen) { 48 | 49 | char* in; 50 | char* out; 51 | jint compressed; 52 | 53 | if (srcArray != NULL) { 54 | in = (char*) (*env)->GetPrimitiveArrayCritical(env, srcArray, 0); 55 | } else { 56 | in = (char*) (*env)->GetDirectBufferAddress(env, srcBuffer); 57 | } 58 | 59 | if (in == NULL) { 60 | throw_OOM(env); 61 | return 0; 62 | } 63 | 64 | if (destArray != NULL) { 65 | out = (char*) (*env)->GetPrimitiveArrayCritical(env, destArray, 0); 66 | } else { 67 | out = (char*) (*env)->GetDirectBufferAddress(env, destBuffer); 68 | } 69 | 70 | if (out == NULL) { 71 | throw_OOM(env); 72 | return 0; 73 | } 74 | 75 | compressed = LZ4_compress_default(in + srcOff, out + destOff, srcLen, maxDestLen); 76 | 77 | if (srcArray != NULL) { 78 | (*env)->ReleasePrimitiveArrayCritical(env, srcArray, in, 0); 79 | } 80 | if (destArray != NULL) { 81 | (*env)->ReleasePrimitiveArrayCritical(env, destArray, out, 0); 82 | } 83 | 84 | return compressed; 85 | 86 | } 87 | 88 | /* 89 | * Class: net_jpountz_lz4_LZ4JNI 90 | * Method: LZ4_compressHC 91 | * Signature: ([BLjava/nio/ByteBuffer;II[BLjava/nio/ByteBuffer;III)I 92 | */ 93 | JNIEXPORT jint JNICALL Java_net_jpountz_lz4_LZ4JNI_LZ4_1compressHC 94 | (JNIEnv *env, jclass cls, jbyteArray srcArray, jobject srcBuffer, jint srcOff, jint srcLen, jbyteArray destArray, jobject destBuffer, jint destOff, jint maxDestLen, jint compressionLevel) { 95 | 96 | char* in; 97 | char* out; 98 | jint compressed; 99 | 100 | if (srcArray != NULL) { 101 | in = (char*) (*env)->GetPrimitiveArrayCritical(env, srcArray, 0); 102 | } else { 103 | in = (char*) (*env)->GetDirectBufferAddress(env, srcBuffer); 104 | } 105 | 106 | if (in == NULL) { 107 | throw_OOM(env); 108 | return 0; 109 | } 110 | 111 | if (destArray != NULL) { 112 | out = (char*) (*env)->GetPrimitiveArrayCritical(env, destArray, 0); 113 | } else { 114 | out = (char*) (*env)->GetDirectBufferAddress(env, destBuffer); 115 | } 116 | 117 | if (out == NULL) { 118 | throw_OOM(env); 119 | return 0; 120 | } 121 | 122 | compressed = LZ4_compress_HC(in + srcOff, out + destOff, srcLen, maxDestLen, compressionLevel); 123 | 124 | if (srcArray != NULL) { 125 | (*env)->ReleasePrimitiveArrayCritical(env, srcArray, in, 0); 126 | } 127 | if (destArray != NULL) { 128 | (*env)->ReleasePrimitiveArrayCritical(env, destArray, out, 0); 129 | } 130 | 131 | return compressed; 132 | 133 | } 134 | 135 | /* 136 | * Class: net_jpountz_lz4_LZ4JNI 137 | * Method: LZ4_decompress_fast 138 | * Signature: ([BLjava/nio/ByteBuffer;I[BLjava/nio/ByteBuffer;II)I 139 | */ 140 | JNIEXPORT jint JNICALL Java_net_jpountz_lz4_LZ4JNI_LZ4_1decompress_1fast 141 | (JNIEnv *env, jclass cls, jbyteArray srcArray, jobject srcBuffer, jint srcOff, jbyteArray destArray, jobject destBuffer, jint destOff, jint destLen) { 142 | 143 | char* in; 144 | char* out; 145 | jint compressed; 146 | 147 | if (srcArray != NULL) { 148 | in = (char*) (*env)->GetPrimitiveArrayCritical(env, srcArray, 0); 149 | } else { 150 | in = (char*) (*env)->GetDirectBufferAddress(env, srcBuffer); 151 | } 152 | 153 | if (in == NULL) { 154 | throw_OOM(env); 155 | return 0; 156 | } 157 | 158 | if (destArray != NULL) { 159 | out = (char*) (*env)->GetPrimitiveArrayCritical(env, destArray, 0); 160 | } else { 161 | out = (char*) (*env)->GetDirectBufferAddress(env, destBuffer); 162 | } 163 | 164 | if (out == NULL) { 165 | throw_OOM(env); 166 | return 0; 167 | } 168 | 169 | compressed = LZ4_decompress_fast(in + srcOff, out + destOff, destLen); 170 | 171 | if (srcArray != NULL) { 172 | (*env)->ReleasePrimitiveArrayCritical(env, srcArray, in, 0); 173 | } 174 | if (destArray != NULL) { 175 | (*env)->ReleasePrimitiveArrayCritical(env, destArray, out, 0); 176 | } 177 | 178 | return compressed; 179 | 180 | } 181 | 182 | /* 183 | * Class: net_jpountz_lz4_LZ4JNI 184 | * Method: LZ4_decompress_safe 185 | * Signature: ([BLjava/nio/ByteBuffer;II[BLjava/nio/ByteBuffer;II)I 186 | */ 187 | JNIEXPORT jint JNICALL Java_net_jpountz_lz4_LZ4JNI_LZ4_1decompress_1safe 188 | (JNIEnv *env, jclass cls, jbyteArray srcArray, jobject srcBuffer, jint srcOff, jint srcLen, jbyteArray destArray, jobject destBuffer, jint destOff, jint maxDestLen) { 189 | 190 | char* in; 191 | char* out; 192 | jint decompressed; 193 | 194 | if (srcArray != NULL) { 195 | in = (char*) (*env)->GetPrimitiveArrayCritical(env, srcArray, 0); 196 | } else { 197 | in = (char*) (*env)->GetDirectBufferAddress(env, srcBuffer); 198 | } 199 | 200 | if (in == NULL) { 201 | throw_OOM(env); 202 | return 0; 203 | } 204 | 205 | if (destArray != NULL) { 206 | out = (char*) (*env)->GetPrimitiveArrayCritical(env, destArray, 0); 207 | } else { 208 | out = (char*) (*env)->GetDirectBufferAddress(env, destBuffer); 209 | } 210 | 211 | if (out == NULL) { 212 | throw_OOM(env); 213 | return 0; 214 | } 215 | 216 | decompressed = LZ4_decompress_safe(in + srcOff, out + destOff, srcLen, maxDestLen); 217 | 218 | if (srcArray != NULL) { 219 | (*env)->ReleasePrimitiveArrayCritical(env, srcArray, in, 0); 220 | } 221 | if (destArray != NULL) { 222 | (*env)->ReleasePrimitiveArrayCritical(env, destArray, out, 0); 223 | } 224 | 225 | return decompressed; 226 | 227 | } 228 | 229 | /* 230 | * Class: net_jpountz_lz4_LZ4JNI 231 | * Method: LZ4_compressBound 232 | * Signature: (I)I 233 | */ 234 | JNIEXPORT jint JNICALL Java_net_jpountz_lz4_LZ4JNI_LZ4_1compressBound 235 | (JNIEnv *env, jclass cls, jint len) { 236 | 237 | return LZ4_compressBound(len); 238 | 239 | } 240 | -------------------------------------------------------------------------------- /src/jni/net_jpountz_xxhash_XXHashJNI.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Adrien Grand and the lz4-java contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include