Home | History | Annotate | Download | only in xz
      1 /*
      2  * UncompressedLZMA2OutputStream
      3  *
      4  * Author: Lasse Collin <lasse.collin (at) tukaani.org>
      5  *
      6  * This file has been put into the public domain.
      7  * You can do whatever you want with this file.
      8  */
      9 
     10 package org.tukaani.xz;
     11 
     12 import java.io.DataOutputStream;
     13 import java.io.IOException;
     14 
     15 class UncompressedLZMA2OutputStream extends FinishableOutputStream {
     16     private FinishableOutputStream out;
     17     private final DataOutputStream outData;
     18 
     19     private final byte[] uncompBuf
     20             = new byte[LZMA2OutputStream.COMPRESSED_SIZE_MAX];
     21     private int uncompPos = 0;
     22     private boolean dictResetNeeded = true;
     23 
     24     private boolean finished = false;
     25     private IOException exception = null;
     26 
     27     private final byte[] tempBuf = new byte[1];
     28 
     29     static int getMemoryUsage() {
     30         // uncompBuf + a little extra
     31         return 70;
     32     }
     33 
     34     UncompressedLZMA2OutputStream(FinishableOutputStream out) {
     35         if (out == null)
     36             throw new NullPointerException();
     37 
     38         this.out = out;
     39         outData = new DataOutputStream(out);
     40     }
     41 
     42     public void write(int b) throws IOException {
     43         tempBuf[0] = (byte)b;
     44         write(tempBuf, 0, 1);
     45     }
     46 
     47     public void write(byte[] buf, int off, int len) throws IOException {
     48         if (off < 0 || len < 0 || off + len < 0 || off + len > buf.length)
     49             throw new IndexOutOfBoundsException();
     50 
     51         if (exception != null)
     52             throw exception;
     53 
     54         if (finished)
     55             throw new XZIOException("Stream finished or closed");
     56 
     57         try {
     58             while (len > 0) {
     59                 int copySize = Math.min(uncompBuf.length - uncompPos, len);
     60                 System.arraycopy(buf, off, uncompBuf, uncompPos, copySize);
     61                 len -= copySize;
     62                 uncompPos += copySize;
     63 
     64                 if (uncompPos == uncompBuf.length)
     65                     writeChunk();
     66             }
     67         } catch (IOException e) {
     68             exception = e;
     69             throw e;
     70         }
     71     }
     72 
     73     private void writeChunk() throws IOException {
     74         outData.writeByte(dictResetNeeded ? 0x01 : 0x02);
     75         outData.writeShort(uncompPos - 1);
     76         outData.write(uncompBuf, 0, uncompPos);
     77         uncompPos = 0;
     78         dictResetNeeded = false;
     79     }
     80 
     81     private void writeEndMarker() throws IOException {
     82         if (exception != null)
     83             throw exception;
     84 
     85         if (finished)
     86             throw new XZIOException("Stream finished or closed");
     87 
     88         try {
     89             if (uncompPos > 0)
     90                 writeChunk();
     91 
     92             out.write(0x00);
     93         } catch (IOException e) {
     94             exception = e;
     95             throw e;
     96         }
     97     }
     98 
     99     public void flush() throws IOException {
    100         if (exception != null)
    101             throw exception;
    102 
    103         if (finished)
    104             throw new XZIOException("Stream finished or closed");
    105 
    106         try {
    107             if (uncompPos > 0)
    108                 writeChunk();
    109 
    110             out.flush();
    111         } catch (IOException e) {
    112             exception = e;
    113             throw e;
    114         }
    115     }
    116 
    117     public void finish() throws IOException {
    118         if (!finished) {
    119             writeEndMarker();
    120 
    121             try {
    122                 out.finish();
    123             } catch (IOException e) {
    124                 exception = e;
    125                 throw e;
    126             }
    127 
    128             finished = true;
    129         }
    130     }
    131 
    132     public void close() throws IOException {
    133         if (out != null) {
    134             if (!finished) {
    135                 try {
    136                     writeEndMarker();
    137                 } catch (IOException e) {}
    138             }
    139 
    140             try {
    141                 out.close();
    142             } catch (IOException e) {
    143                 if (exception == null)
    144                     exception = e;
    145             }
    146 
    147             out = null;
    148         }
    149 
    150         if (exception != null)
    151             throw exception;
    152     }
    153 }
    154