Yuan.Wang
2 years ago
53 changed files with 987 additions and 182 deletions
@ -0,0 +1,2 @@
|
||||
lz4的源码地址:https://github.com/lz4/lz4 <br> |
||||
版本:1.8.0<br> |
@ -0,0 +1,201 @@
|
||||
package com.fr.third.net.jpountz.lz4; |
||||
|
||||
/* |
||||
* Copyright 2020 Rei Odaira and the lz4-java contributors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
import java.nio.ByteBuffer; |
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Covenience class to include the length of the original decompressed data |
||||
* in the output compressed data, so that the user does not need to save |
||||
* the length at anywhere else. The compressed data must be decompressed by |
||||
* {@link LZ4DecompressorWithLength} and is NOT compatible with any other |
||||
* decompressors in lz4-java or any other lz4 tools. This class deliberately |
||||
* does not extend {@link LZ4Compressor} because they are not interchangable. |
||||
*/ |
||||
|
||||
public class LZ4CompressorWithLength { |
||||
|
||||
private final LZ4Compressor compressor; |
||||
|
||||
/** |
||||
* Creates a new compressor that includes the length of the original |
||||
* decompressed data in the output compressed data. |
||||
* |
||||
* @param compressor compressor to use |
||||
*/ |
||||
public LZ4CompressorWithLength(LZ4Compressor compressor) { |
||||
this.compressor = compressor; |
||||
} |
||||
|
||||
private void putOriginalLength(byte[] dest, int destOff, int originalLength) { |
||||
dest[destOff] = (byte)originalLength; |
||||
dest[destOff + 1] = (byte)(originalLength >> 8); |
||||
dest[destOff + 2] = (byte)(originalLength >> 16); |
||||
dest[destOff + 3] = (byte)(originalLength >> 24); |
||||
} |
||||
|
||||
private void putOriginalLength(ByteBuffer dest, int destOff, int originalLength) { |
||||
dest.put(destOff, (byte)originalLength); |
||||
dest.put(destOff + 1, (byte)(originalLength >> 8)); |
||||
dest.put(destOff + 2, (byte)(originalLength >> 16)); |
||||
dest.put(destOff + 3, (byte)(originalLength >> 24)); |
||||
} |
||||
|
||||
/** |
||||
* Returns the maximum compressed length for an input of size <code>length</code>. |
||||
* |
||||
* @param length the input size in bytes |
||||
* @return the maximum compressed length in bytes |
||||
*/ |
||||
public int maxCompressedLength(int length) { |
||||
return compressor.maxCompressedLength(length) + 4; |
||||
} |
||||
|
||||
/** |
||||
* Convenience method, equivalent to calling |
||||
* {@link #compress(byte[], int, int) compress(src, 0, src.length)}. |
||||
* |
||||
* @param src the source data |
||||
* @return the compressed data |
||||
*/ |
||||
public byte[] compress(byte[] src) { |
||||
return compress(src, 0, src.length); |
||||
} |
||||
|
||||
/** |
||||
* Convenience method which returns <code>src[srcOff:srcOff+srcLen]</code> |
||||
* compressed. |
||||
* <p><b><span style="color:red">Warning</span></b>: this method has an |
||||
* important overhead due to the fact that it needs to allocate a buffer to |
||||
* compress into, and then needs to resize this buffer to the actual |
||||
* compressed length.</p> |
||||
* <p>Here is how this method is implemented:</p> |
||||
* <pre> |
||||
* final int maxCompressedLength = maxCompressedLength(srcLen); |
||||
* final byte[] compressed = new byte[maxCompressedLength]; |
||||
* final int compressedLength = compress(src, srcOff, srcLen, compressed, 0); |
||||
* return Arrays.copyOf(compressed, compressedLength); |
||||
* </pre> |
||||
* |
||||
* @param src the source data |
||||
* @param srcOff the start offset in src |
||||
* @param srcLen the number of bytes to compress |
||||
* @return the compressed data |
||||
*/ |
||||
public byte[] compress(byte[] src, int srcOff, int srcLen) { |
||||
final int maxCompressedLength = maxCompressedLength(srcLen); |
||||
final byte[] compressed = new byte[maxCompressedLength]; |
||||
final int compressedLength = compress(src, srcOff, srcLen, compressed, 0); |
||||
return Arrays.copyOf(compressed, compressedLength); |
||||
} |
||||
|
||||
/** |
||||
* Convenience method, equivalent to calling |
||||
* {@link #compress(byte[], int, int, byte[], int) compress(src, 0, src.length, dest, 0)}. |
||||
* |
||||
* @param src the source data |
||||
* @param dest the destination buffer |
||||
* @throws LZ4Exception if dest is too small |
||||
* @return the compressed size |
||||
*/ |
||||
public int compress(byte[] src, byte[] dest) { |
||||
return compress(src, 0, src.length, dest, 0); |
||||
} |
||||
|
||||
/** |
||||
* Convenience method, equivalent to calling |
||||
* {@link #compress(byte[], int, int, byte[], int, int) compress(src, srcOff, srcLen, dest, destOff, dest.length - destOff)}. |
||||
* |
||||
* @param src the source data |
||||
* @param srcOff the start offset in src |
||||
* @param srcLen the number of bytes to compress |
||||
* @param dest the destination buffer |
||||
* @param destOff the start offset in dest |
||||
* @throws LZ4Exception if dest is too small |
||||
* @return the compressed size |
||||
*/ |
||||
public int compress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff) { |
||||
return compress(src, srcOff, srcLen, dest, destOff, dest.length - destOff); |
||||
} |
||||
|
||||
/** |
||||
* Compresses <code>src[srcOff:srcOff+srcLen]</code> into |
||||
* <code>dest[destOff:destOff+maxDestLen]</code> and returns the compressed |
||||
* length. |
||||
* |
||||
* This method will throw a {@link LZ4Exception} if this compressor is unable |
||||
* to compress the input into less than <code>maxDestLen</code> bytes. To |
||||
* prevent this exception to be thrown, you should make sure that |
||||
* <code>maxDestLen >= maxCompressedLength(srcLen)</code>. |
||||
* |
||||
* @param src the source data |
||||
* @param srcOff the start offset in src |
||||
* @param srcLen the number of bytes to compress |
||||
* @param dest the destination buffer |
||||
* @param destOff the start offset in dest |
||||
* @param maxDestLen the maximum number of bytes to write in dest |
||||
* @throws LZ4Exception if maxDestLen is too small |
||||
* @return the compressed size |
||||
*/ |
||||
public int compress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen) { |
||||
final int compressedLength = compressor.compress(src, srcOff, srcLen, dest, destOff + 4, maxDestLen - 4); |
||||
putOriginalLength(dest, destOff, srcLen); |
||||
return compressedLength + 4; |
||||
} |
||||
|
||||
/** |
||||
* Compresses <code>src</code> into <code>dest</code>. Calling this method |
||||
* will update the positions of both {@link ByteBuffer}s. |
||||
* |
||||
* @param src the source data |
||||
* @param dest the destination buffer |
||||
* @throws LZ4Exception if dest is too small |
||||
*/ |
||||
public void compress(ByteBuffer src, ByteBuffer dest) { |
||||
final int compressedLength = compress(src, src.position(), src.remaining(), dest, dest.position(), dest.remaining()); |
||||
src.position(src.limit()); |
||||
dest.position(dest.position() + compressedLength); |
||||
} |
||||
|
||||
/** |
||||
* Compresses <code>src[srcOff:srcOff+srcLen]</code> into |
||||
* <code>dest[destOff:destOff+maxDestLen]</code> and returns the compressed |
||||
* length. |
||||
* |
||||
* This method will throw a {@link LZ4Exception} if this compressor is unable |
||||
* to compress the input into less than <code>maxDestLen</code> bytes. To |
||||
* prevent this exception to be thrown, you should make sure that |
||||
* <code>maxDestLen >= maxCompressedLength(srcLen)</code>. |
||||
* |
||||
* {@link ByteBuffer} positions remain unchanged. |
||||
* |
||||
* @param src the source data |
||||
* @param srcOff the start offset in src |
||||
* @param srcLen the number of bytes to compress |
||||
* @param dest the destination buffer |
||||
* @param destOff the start offset in dest |
||||
* @param maxDestLen the maximum number of bytes to write in dest |
||||
* @throws LZ4Exception if maxDestLen is too small |
||||
* @return the compressed size |
||||
*/ |
||||
public int compress(ByteBuffer src, int srcOff, int srcLen, ByteBuffer dest, int destOff, int maxDestLen) { |
||||
final int compressedLength = compressor.compress(src, srcOff, srcLen, dest, destOff + 4, maxDestLen - 4); |
||||
putOriginalLength(dest, destOff, srcLen); |
||||
return compressedLength + 4; |
||||
} |
||||
} |
@ -0,0 +1,277 @@
|
||||
package com.fr.third.net.jpountz.lz4; |
||||
|
||||
/* |
||||
* Copyright 2020 Rei Odaira and the lz4-java contributors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
import java.nio.ByteBuffer; |
||||
|
||||
/** |
||||
* Convenience class to decompress data compressed by {@link LZ4CompressorWithLength}. |
||||
* This decompressor is NOT compatible with any other compressors in lz4-java |
||||
* or any other lz4 tools. |
||||
* The user does not need to specify the length of the compressed data or |
||||
* original data because the length of the original decompressed data is |
||||
* included in the compressed data. |
||||
*/ |
||||
|
||||
public class LZ4DecompressorWithLength { |
||||
|
||||
private final LZ4FastDecompressor fastDecompressor; |
||||
private final LZ4SafeDecompressor safeDecompressor; |
||||
|
||||
/** |
||||
* Returns the decompressed length of compressed data in <code>src</code>. |
||||
* |
||||
* @param src the compressed data |
||||
* @return the decompressed length |
||||
*/ |
||||
public static int getDecompressedLength(byte[] src) { |
||||
return getDecompressedLength(src, 0); |
||||
} |
||||
|
||||
/** |
||||
* Returns the decompressed length of compressed data in <code>src[srcOff:]</code>. |
||||
* |
||||
* @param src the compressed data |
||||
* @param srcOff the start offset in src |
||||
* @return the decompressed length |
||||
*/ |
||||
public static int getDecompressedLength(byte[] src, int srcOff) { |
||||
return (src[srcOff] & 0xFF) | (src[srcOff + 1] & 0xFF) << 8 | (src[srcOff + 2] & 0xFF) << 16 | src[srcOff + 3] << 24; |
||||
} |
||||
|
||||
/** |
||||
* Returns the decompressed length of compressed data in <code>src</code>. |
||||
* |
||||
* @param src the compressed data |
||||
* @return the decompressed length |
||||
*/ |
||||
public static int getDecompressedLength(ByteBuffer src) { |
||||
return getDecompressedLength(src, src.position()); |
||||
} |
||||
|
||||
/** |
||||
* Returns the decompressed length of compressed data in <code>src[srcOff:]</code>. |
||||
* |
||||
* @param src the compressed data |
||||
* @param srcOff the start offset in src |
||||
* @return the decompressed length |
||||
*/ |
||||
public static int getDecompressedLength(ByteBuffer src, int srcOff) { |
||||
return (src.get(srcOff) & 0xFF) | (src.get(srcOff + 1) & 0xFF) << 8 | (src.get(srcOff + 2) & 0xFF) << 16 | src.get(srcOff + 3) << 24; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new decompressor to decompress data compressed by {@link LZ4CompressorWithLength}. |
||||
* Note that it is deprecated to use a JNI-binding instance of {@link LZ4FastDecompressor}. |
||||
* Please see {@link LZ4Factory#nativeInstance()} for details. |
||||
* |
||||
* @param fastDecompressor fast decompressor to use |
||||
*/ |
||||
public LZ4DecompressorWithLength(LZ4FastDecompressor fastDecompressor) { |
||||
this.fastDecompressor = fastDecompressor; |
||||
this.safeDecompressor = null; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new decompressor to decompress data compressed by {@link LZ4CompressorWithLength}. |
||||
* |
||||
* @param safeDecompressor safe decompressor to use |
||||
*/ |
||||
public LZ4DecompressorWithLength(LZ4SafeDecompressor safeDecompressor) { |
||||
this.fastDecompressor = null; |
||||
this.safeDecompressor = safeDecompressor; |
||||
} |
||||
|
||||
/** |
||||
* Convenience method, equivalent to calling |
||||
* {@link #decompress(byte[], int, byte[], int) decompress(src, 0, dest, 0)}. |
||||
* |
||||
* @param src the compressed data |
||||
* @param dest the destination buffer to store the decompressed data |
||||
* @return the number of bytes read to restore the original input |
||||
*/ |
||||
public int decompress(byte[] src, byte[] dest) { |
||||
return decompress(src, 0, dest, 0); |
||||
} |
||||
|
||||
/** |
||||
* When {@link LZ4FastDecompressor} was specified to the constructor, |
||||
* decompresses <code>src[srcOff:]</code> into <code>dest[destOff:]</code> |
||||
* and returns the number of bytes read from <code>src</code>, and |
||||
* when {@link LZ4SafeDecompressor} was specified to the constructor, |
||||
* decompresses <code>src[srcOff:src.length]</code> into <code>dest[destOff:]</code> |
||||
* and returns the number of decompressed bytes written into <code>dest</code>. |
||||
* |
||||
* @param src the compressed data |
||||
* @param srcOff the start offset in src |
||||
* @param dest the destination buffer to store the decompressed data |
||||
* @param destOff the start offset in dest |
||||
* @return the number of bytes read to restore the original input (when {@link LZ4FastDecompressor} is used), or the number of decompressed bytes (when {@link LZ4SafeDecompressor} is used) |
||||
*/ |
||||
public int decompress(byte[] src, int srcOff, byte[] dest, int destOff) { |
||||
if (safeDecompressor != null) { |
||||
return decompress(src, srcOff, src.length - srcOff, dest, destOff); |
||||
} |
||||
final int destLen = getDecompressedLength(src, srcOff); |
||||
return fastDecompressor.decompress(src, srcOff + 4, dest, destOff, destLen) + 4; |
||||
} |
||||
|
||||
/** |
||||
* When {@link LZ4FastDecompressor} was specified to the constructor, |
||||
* decompresses <code>src[srcOff:]</code> into <code>dest[destOff:]</code> |
||||
* and returns the number of bytes read from <code>src</code>, and |
||||
* when {@link LZ4SafeDecompressor} was specified to the constructor, |
||||
* decompresses <code>src[srcOff:srcOff+srcLen]</code> into <code>dest[destOff:]</code> |
||||
* and returns the number of decompressed bytes written into <code>dest</code>. |
||||
* |
||||
* @param src the compressed data |
||||
* @param srcOff the start offset in src |
||||
* @param srcLen the exact size of the compressed data (ignored when {@link LZ4FastDecompressor} is used) |
||||
* @param dest the destination buffer to store the decompressed data |
||||
* @param destOff the start offset in dest |
||||
* @return the number of bytes read to restore the original input (when {@link LZ4FastDecompressor} is used), or the number of decompressed bytes (when {@link LZ4SafeDecompressor} is used) |
||||
*/ |
||||
public int decompress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff) { |
||||
if (safeDecompressor == null) { |
||||
return decompress(src, srcOff, dest, destOff); |
||||
} |
||||
final int destLen = getDecompressedLength(src, srcOff); |
||||
return safeDecompressor.decompress(src, srcOff + 4, srcLen - 4, dest, destOff, destLen); |
||||
} |
||||
|
||||
/** |
||||
* Convenience method, equivalent to calling |
||||
* {@link #decompress(byte[], int) decompress(src, 0)}. |
||||
* |
||||
* @param src the compressed data |
||||
* @return the decompressed data |
||||
*/ |
||||
public byte[] decompress(byte[] src) { |
||||
return decompress(src, 0); |
||||
} |
||||
|
||||
/** |
||||
* Convenience method which returns <code>src[srcOff:]</code> |
||||
* decompressed when {@link LZ4FastDecompressor} was specified to the constructor, |
||||
* or <code>src[srcOff:src.length]</code> decompressed when |
||||
* {@link LZ4SafeDecompressor} was specified to the constructor. |
||||
* <p><b><span style="color:red">Warning</span></b>: this method has an |
||||
* important overhead due to the fact that it needs to allocate a buffer to |
||||
* decompress into. |
||||
* |
||||
* @param src the compressed data |
||||
* @param srcOff the start offset in src |
||||
* @return the decompressed data |
||||
*/ |
||||
public byte[] decompress(byte[] src, int srcOff) { |
||||
if (safeDecompressor != null) { |
||||
return decompress(src, srcOff, src.length - srcOff); |
||||
} |
||||
final int destLen = getDecompressedLength(src, srcOff); |
||||
return fastDecompressor.decompress(src, srcOff + 4, destLen); |
||||
} |
||||
|
||||
/** |
||||
* Convenience method which returns <code>src[srcOff:]</code> |
||||
* decompressed when {@link LZ4FastDecompressor} was specified to the constructor, |
||||
* or <code>src[srcOff:srcOff+srcLen]</code> decompressed when |
||||
* {@link LZ4SafeDecompressor} was specified to the constructor. |
||||
* <p><b><span style="color:red">Warning</span></b>: this method has an |
||||
* important overhead due to the fact that it needs to allocate a buffer to |
||||
* decompress into. |
||||
* |
||||
* @param src the compressed data |
||||
* @param srcOff the start offset in src |
||||
* @param srcLen the exact size of the compressed data (ignored when {@link LZ4FastDecompressor} is used) |
||||
* @return the decompressed data |
||||
*/ |
||||
public byte[] decompress(byte[] src, int srcOff, int srcLen) { |
||||
if (safeDecompressor == null) { |
||||
return decompress(src, srcOff); |
||||
} |
||||
final int destLen = getDecompressedLength(src, srcOff); |
||||
return safeDecompressor.decompress(src, srcOff + 4, srcLen - 4, destLen); |
||||
} |
||||
|
||||
/** |
||||
* Decompresses <code>src</code> into <code>dest</code>. |
||||
* When {@link LZ4SafeDecompressor} was specified to the constructor, |
||||
* <code>src</code>'s {@link ByteBuffer#remaining()} must be exactly the size |
||||
* of the compressed data. This method moves the positions of the buffers. |
||||
* |
||||
* @param src the compressed data |
||||
* @param dest the destination buffer to store the decompressed data |
||||
*/ |
||||
public void decompress(ByteBuffer src, ByteBuffer dest) { |
||||
final int destLen = getDecompressedLength(src, src.position()); |
||||
if (safeDecompressor == null) { |
||||
final int read = fastDecompressor.decompress(src, src.position() + 4, dest, dest.position(), destLen); |
||||
src.position(src.position() + 4 + read); |
||||
dest.position(dest.position() + destLen); |
||||
} else { |
||||
final int written = safeDecompressor.decompress(src, src.position() + 4, src.remaining() - 4, dest, dest.position(), destLen); |
||||
src.position(src.limit()); |
||||
dest.position(dest.position() + written); |
||||
} |
||||
} |
||||
|
||||
/** When {@link LZ4FastDecompressor} was specified to the constructor, |
||||
* decompresses <code>src[srcOff:]</code> into <code>dest[destOff:]</code> |
||||
* and returns the number of bytes read from <code>src</code>, and |
||||
* when {@link LZ4SafeDecompressor} was specified to the constructor, |
||||
* decompresses <code>src[srcOff:src.remaining()]</code> into <code>dest[destOff:]</code> |
||||
* and returns the number of decompressed bytes written into <code>dest</code>. |
||||
* The positions and limits of the {@link ByteBuffer}s remain unchanged. |
||||
* |
||||
* @param src the compressed data |
||||
* @param srcOff the start offset in src |
||||
* @param dest the destination buffer to store the decompressed data |
||||
* @param destOff the start offset in dest |
||||
* @return the number of bytes read to restore the original input (when {@link LZ4FastDecompressor} is used), or the number of decompressed bytes (when {@link LZ4SafeDecompressor} is used) |
||||
*/ |
||||
public int decompress(ByteBuffer src, int srcOff, ByteBuffer dest, int destOff) { |
||||
if (safeDecompressor != null) { |
||||
return decompress(src, srcOff, src.remaining() - srcOff, dest, destOff); |
||||
} |
||||
final int destLen = getDecompressedLength(src, srcOff); |
||||
return fastDecompressor.decompress(src, srcOff + 4, dest, destOff, destLen) + 4; |
||||
} |
||||
|
||||
/** |
||||
* When {@link LZ4FastDecompressor} was specified to the constructor, |
||||
* decompresses <code>src[srcOff:]</code> into <code>dest[destOff:]</code> |
||||
* and returns the number of bytes read from <code>src</code>, and |
||||
* when {@link LZ4SafeDecompressor} was specified to the constructor, |
||||
* decompresses <code>src[srcOff:srcOff+srcLen]</code> into <code>dest[destOff:]</code> |
||||
* and returns the number of decompressed bytes written into <code>dest</code>. |
||||
* The positions and limits of the {@link ByteBuffer}s remain unchanged. |
||||
* |
||||
* @param src the compressed data |
||||
* @param srcOff the start offset in src |
||||
* @param srcLen the exact size of the compressed data (ignored when {@link LZ4FastDecompressor} is used) |
||||
* @param dest the destination buffer to store the decompressed data |
||||
* @param destOff the start offset in dest |
||||
* @return the number of bytes read to restore the original input (when {@link LZ4FastDecompressor} is used), or the number of decompressed bytes (when {@link LZ4SafeDecompressor} is used) |
||||
*/ |
||||
public int decompress(ByteBuffer src, int srcOff, int srcLen, ByteBuffer dest, int destOff) { |
||||
if (safeDecompressor == null) { |
||||
return decompress(src, srcOff, dest, destOff); |
||||
} |
||||
final int destLen = getDecompressedLength(src, srcOff); |
||||
return safeDecompressor.decompress(src, srcOff + 4, srcLen - 4, dest, destOff, destLen); |
||||
} |
||||
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue