View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  
21  package org.waarp.compress.zstdjni;
22  
23  import com.github.luben.zstd.Zstd;
24  import com.github.luben.zstd.ZstdInputStream;
25  import com.google.common.io.ByteStreams;
26  import org.waarp.common.file.FileUtils;
27  import org.waarp.compress.CompressorCodec;
28  import org.waarp.compress.MalformedInputException;
29  
30  import java.io.File;
31  import java.io.FileInputStream;
32  import java.io.FileOutputStream;
33  import java.io.InputStream;
34  import java.io.OutputStream;
35  import java.util.Arrays;
36  
37  /**
38   * ZSTD JNI Codec implementation
39   */
40  public class ZstdJniCodec implements CompressorCodec {
41  
42    @Override
43    public final int maxCompressedLength(final int uncompressedSize) {
44      return (int) Zstd.compressBound(uncompressedSize);
45    }
46  
47    @Override
48    public final byte[] compress(final byte[] input, final int length)
49        throws MalformedInputException {
50      try {
51        final int maxDstSize = maxCompressedLength(length);
52        final byte[] target = new byte[maxDstSize];
53        final int realSize = compress(input, length, target, maxDstSize);
54        return Arrays.copyOfRange(target, 0, realSize);
55      } catch (final Exception e) {
56        throw new MalformedInputException(e);
57      }
58    }
59  
60    @Override
61    public final int compress(final byte[] input, final int inputLength,
62                              final byte[] output, final int maxOutputLength) {
63      try {
64        return (int) Zstd.compressByteArray(output, 0, maxOutputLength, input, 0,
65                                            inputLength, 3);
66      } catch (final Exception e) {
67        throw new MalformedInputException(e);
68      }
69    }
70  
71    @Override
72    public final long compress(final File input, final File output)
73        throws MalformedInputException {
74      InputStream inputStream = null;
75      OutputStream outputStream = null;
76      try {
77        final byte[] buffer;
78        inputStream = new FileInputStream(input);
79        buffer = ByteStreams.toByteArray(inputStream);
80        outputStream = new FileOutputStream(output);
81        final byte[] bufferCompression =
82            new byte[maxCompressedLength(buffer.length)];
83        final int length = (int) Zstd.compressByteArray(bufferCompression, 0,
84                                                        bufferCompression.length,
85                                                        buffer, 0, buffer.length,
86                                                        3);
87        outputStream.write(bufferCompression, 0, length);
88        outputStream.flush();
89        FileUtils.close(outputStream);
90        outputStream = null;
91        return output.length();
92      } catch (final Exception e) {
93        throw new MalformedInputException(e);
94      } finally {
95        FileUtils.close(inputStream);
96        FileUtils.close(outputStream);
97      }
98    }
99  
100   @Override
101   public final byte[] decompress(final byte[] compressed, final int length)
102       throws MalformedInputException {
103     try {
104       final int len = getDecompressedSize(compressed, length);
105       final byte[] target = new byte[len];
106       final int finalLen = decompress(compressed, length, target, len);
107       if (finalLen != len) {
108         throw new IllegalStateException(
109             "Issue on suggested decompressed size " + len + " while is " +
110             finalLen);
111       }
112       return target;
113     } catch (final Exception e) {
114       throw new MalformedInputException(e);
115     }
116   }
117 
118   @Override
119   public final int decompress(final byte[] input, final int inputLength,
120                               final byte[] output, final int maxOutputLength) {
121     try {
122       return (int) Zstd.decompressByteArray(output, 0, maxOutputLength, input,
123                                             0, inputLength);
124     } catch (final Exception e) {
125       throw new MalformedInputException(e);
126     }
127   }
128 
129   @Override
130   public final long decompress(final File input, final File output)
131       throws MalformedInputException {
132     InputStream inputStream = null;
133     OutputStream outputStream = null;
134     try {
135       final byte[] buffer;
136       inputStream = new ZstdInputStream(new FileInputStream(input));
137       outputStream = new FileOutputStream(output);
138       FileUtils.copy(Zstd.blockSizeMax(), inputStream, outputStream);
139       outputStream = null;
140       return output.length();
141     } catch (final Exception e) {
142       throw new MalformedInputException(e);
143     } finally {
144       FileUtils.close(inputStream);
145       FileUtils.close(outputStream);
146     }
147   }
148 
149   @Override
150   public final int getDecompressedSize(final byte[] compressed,
151                                        final int length) {
152     return (int) Zstd.decompressedSize(compressed, 0, length);
153   }
154 
155 }