1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package org.waarp.compress.zstdunsafe;
35
36 import com.google.common.io.ByteStreams;
37 import org.waarp.common.file.FileUtils;
38 import org.waarp.compress.CompressorCodec;
39 import org.waarp.compress.MalformedInputException;
40
41 import java.io.File;
42 import java.io.FileInputStream;
43 import java.io.FileOutputStream;
44 import java.io.InputStream;
45 import java.io.OutputStream;
46 import java.util.Arrays;
47
48 import static org.waarp.compress.zstdunsafe.Constants.*;
49 import static sun.misc.Unsafe.*;
50
51
52
53
54 public class ZstdUnsafeCodec implements CompressorCodec {
55 private final ZstdFrameDecompressor decompressor =
56 new ZstdFrameDecompressor();
57
58 @Override
59 public final int getDecompressedSize(final byte[] input, final int length) {
60 final long baseAddress = ARRAY_BYTE_BASE_OFFSET;
61 return (int) ZstdFrameDecompressor.getDecompressedSize(input, baseAddress,
62 baseAddress +
63 length);
64 }
65
66 @Override
67 public final int maxCompressedLength(final int uncompressedSize) {
68 long result = (long) uncompressedSize + (uncompressedSize >>> 8);
69 if (uncompressedSize < MAX_BLOCK_SIZE) {
70 result += (MAX_BLOCK_SIZE - uncompressedSize) >>> 11;
71 }
72 return (int) result;
73 }
74
75 @Override
76 public final byte[] compress(final byte[] input, final int length) {
77 try {
78 final int len = maxCompressedLength(length);
79 final byte[] temp = new byte[len];
80 final int finalLen = compress(input, input.length, temp, len);
81 return Arrays.copyOf(temp, finalLen);
82 } catch (final Exception e) {
83 throw new MalformedInputException(e);
84 }
85 }
86
87 @Override
88 public final int compress(final byte[] input, final int inputLength,
89 final byte[] output, final int maxOutputLength) {
90 try {
91 final long inputAddress = ARRAY_BYTE_BASE_OFFSET;
92 final long outputAddress = ARRAY_BYTE_BASE_OFFSET;
93 return ZstdFrameCompressor.compress(input, inputAddress,
94 inputAddress + inputLength, output,
95 outputAddress,
96 outputAddress + maxOutputLength,
97 CompressionParameters.DEFAULT_COMPRESSION_LEVEL);
98 } catch (final Exception e) {
99 throw new MalformedInputException(e);
100 }
101 }
102
103 @Override
104 public final byte[] decompress(final byte[] input, final int length)
105 throws MalformedInputException {
106 try {
107 final int finalLen = getDecompressedSize(input, length);
108 final byte[] decompressed = new byte[finalLen];
109 decompress(input, input.length, decompressed, finalLen);
110 return decompressed;
111 } catch (final Exception e) {
112 throw new MalformedInputException(e);
113 }
114 }
115
116 @Override
117 public final long compress(final File input, final File output)
118 throws MalformedInputException {
119 InputStream inputStream = null;
120 OutputStream outputStream = null;
121 try {
122 final byte[] buffer;
123 inputStream = new FileInputStream(input);
124 buffer = ByteStreams.toByteArray(inputStream);
125 outputStream = new FileOutputStream(output);
126 final byte[] bufferCompression =
127 new byte[maxCompressedLength(buffer.length)];
128 final int length = compress(buffer, buffer.length, bufferCompression,
129 bufferCompression.length);
130 outputStream.write(bufferCompression, 0, length);
131 outputStream.flush();
132 FileUtils.close(outputStream);
133 outputStream = null;
134 return output.length();
135 } catch (final Exception e) {
136 throw new MalformedInputException(e);
137 } finally {
138 FileUtils.close(inputStream);
139 FileUtils.close(outputStream);
140 }
141 }
142
143 @Override
144 public final int decompress(final byte[] input, final int inputLength,
145 final byte[] output, final int maxOutputLength)
146 throws MalformedInputException {
147 try {
148 final long inputAddress = ARRAY_BYTE_BASE_OFFSET;
149 final long inputLimit = inputAddress + inputLength;
150 final long outputAddress = ARRAY_BYTE_BASE_OFFSET;
151 final long outputLimit = outputAddress + maxOutputLength;
152
153 return decompressor.decompress(input, inputAddress, inputLimit, output,
154 outputAddress, outputLimit);
155 } catch (final Exception e) {
156 throw new MalformedInputException(e);
157 }
158 }
159
160 @Override
161 public final long decompress(final File input, final File output)
162 throws MalformedInputException {
163 InputStream inputStream = null;
164 OutputStream outputStream = null;
165 try {
166 final byte[] buffer;
167 inputStream = new FileInputStream(input);
168 final byte[] sourceArray = ByteStreams.toByteArray(inputStream);
169 outputStream = new FileOutputStream(output);
170 buffer = new byte[getDecompressedSize(sourceArray, sourceArray.length)];
171 final int length =
172 decompress(sourceArray, sourceArray.length, buffer, buffer.length);
173 outputStream.write(buffer, 0, length);
174 outputStream.flush();
175 FileUtils.close(outputStream);
176 outputStream = null;
177 return output.length();
178 } catch (final Exception e) {
179 throw new MalformedInputException(e);
180 } finally {
181 FileUtils.close(inputStream);
182 FileUtils.close(outputStream);
183 }
184 }
185 }