diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java index 48f915a75aa80d1c987ff58395aa36534cbf8a6f..92ee5d3fc3386ea3516fd323564e49e44e009eef 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java @@ -22,19 +22,22 @@ */ package com.oracle.truffle.r.runtime; +import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.ProcessBuilder.Redirect; +import java.util.Arrays; import java.util.zip.GZIPInputStream; import com.oracle.truffle.r.runtime.conn.GZIPConnections.GZIPRConnection; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; +import org.tukaani.xz.LZMA2InputStream; + /** - * Abstracts the implementation of the various forms of compression used in R. Since the C API for - * LZMA is very complex (as used by GnuR), we use an 'xz' subprocess to do the work. + * Abstracts the implementation of the various forms of compression used in R. */ public class RCompression { public enum Type { @@ -98,7 +101,8 @@ public class RCompression { case BZIP2: throw RInternalError.unimplemented("BZIP2 compression"); case LZMA: - return lzmaUncompress(udata, cdata); + byte[] udataCopy = Arrays.copyOf(udata, udata.length); + return lzmaUncompressInternal(udataCopy, cdata); default: assert false; return false; @@ -160,6 +164,20 @@ public class RCompression { } + private static boolean lzmaUncompressInternal(byte[] udata, byte[] data) { + int dictSize = udata.length < LZMA2InputStream.DICT_SIZE_MIN ? LZMA2InputStream.DICT_SIZE_MIN : udata.length; + try (LZMA2InputStream lzmaStream = new LZMA2InputStream(new ByteArrayInputStream(data), dictSize)) { + int totalRead = 0; + int n; + while ((n = lzmaStream.read(udata, totalRead, udata.length - totalRead)) > 0) { + totalRead += n; + } + return totalRead == udata.length; + } catch (IOException ex) { + return false; + } + } + private static boolean lzmaUncompress(byte[] udata, byte[] data) { int rc; ProcessBuilder pb = new ProcessBuilder("xz", "--decompress", "--format=raw", "--lzma2", "--stdout"); diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py index ce81b0b2cf17024c81bac57e7754702a520a4153..c780314a49120d84d5d6784fc13edffc2a5ce8b0 100644 --- a/mx.fastr/suite.py +++ b/mx.fastr/suite.py @@ -73,6 +73,16 @@ suite = { "resource" : "true" }, + "APACHE-COMMONS-COMPRESS" : { + "urls" : ["http://central.maven.org/maven2/org/apache/commons/commons-compress/1.12/commons-compress-1.12.jar"], + "sha1" : "84caa68576e345eb5e7ae61a0e5a9229eb100d7b" + }, + + "TUKAANI_XZ" : { + "urls" : ["http://central.maven.org/maven2/org/tukaani/xz/1.5/xz-1.5.jar"], + "sha1" : "9c64274b7dbb65288237216e3fae7877fd3f2bee", + }, + "ANTLR-3.5" : { "path" : "libdownloads/antlr-runtime-3.5.jar", "urls" : ["http://central.maven.org/maven2/org/antlr/antlr-runtime/3.5/antlr-runtime-3.5.jar"], @@ -315,6 +325,8 @@ suite = { "dependencies" : [ "truffle:TRUFFLE_API", "truffle:TRUFFLE_DEBUG", + "APACHE-COMMONS-COMPRESS", + "TUKAANI_XZ", ], "checkstyle" : "com.oracle.truffle.r.runtime", "javaCompliance" : "1.8",