OSDN Git Service

Add new source files
[armadillo/armadillo1.git] / src / jp / sfjp / armadillo / compression / lzhuf / LzssInputStream.java
1 package jp.sfjp.armadillo.compression.lzhuf;
2
3 import java.io.*;
4
5 public final class LzssInputStream extends FilterInputStream {
6
7     private final int dictionarySize;
8     private final int matchSize;
9     private final int threshold;
10     private final int bufferLength;
11
12     private boolean closed;
13     private LzssDecoderReadable input;
14     private byte[] buffer;
15     private int bufferedSize = 0;
16     private int index = 0;
17     private int limit = 0;
18
19     public LzssInputStream(LzssDecoderReadable input,
20                            int dictionarySize,
21                            int matchSize,
22                            int threshold) {
23         super(null);
24         this.input = input;
25         this.dictionarySize = dictionarySize;
26         this.matchSize = matchSize;
27         this.threshold = threshold;
28         this.bufferLength = dictionarySize + matchSize;
29         this.buffer = new byte[bufferLength];
30     }
31
32     @Override
33     public int read() throws IOException {
34         if (closed)
35             throw new IOException("stream already closed");
36         try {
37             if (bufferedSize < 1)
38                 if (fillBuffer(1) > 0)
39                     return -1;
40             --bufferedSize;
41             return buffer[++index] & 0xFF;
42         }
43         catch (RuntimeException ex) {
44             throw new LzhufException("decode error", ex);
45         }
46     }
47
48     @Override
49     public int read(byte[] b, int off, int len) throws IOException {
50         if (closed)
51             throw new IOException("stream already closed");
52         try {
53             int offset = off;
54             int remaining = len;
55             while (remaining > 0) {
56                 if (remaining > bufferedSize && fillBuffer(remaining) == remaining)
57                     break;
58                 int length = (remaining <= bufferedSize) ? remaining : bufferedSize;
59                 if (index < limit) {
60                     System.arraycopy(buffer, index, b, offset, length);
61                     index += length;
62                 }
63                 else {
64                     int length1 = (index + length > buffer.length) ? buffer.length - index : length;
65                     System.arraycopy(buffer, index, b, offset, length1);
66                     index += length1;
67                     int length2 = length - length1;
68                     if (length2 > 0) {
69                         System.arraycopy(buffer, 0, b, offset + length1, length2);
70                         index = length2;
71                     }
72                 }
73                 remaining -= length;
74                 bufferedSize -= length;
75             }
76             return (len == remaining) ? len : len - remaining;
77         }
78         catch (RuntimeException ex) {
79             throw new LzhufException("decode error", ex);
80         }
81     }
82
83     private int fillBuffer(int requiredSize) throws IOException {
84         final int fill = Math.min(requiredSize, dictionarySize);
85         while (bufferedSize < fill) {
86             int code = input.read();
87             if (code == -1) {
88                 break;
89             }
90             if (code >= 0x100) {
91                 int length = (code & 0xFF) + threshold;
92                 int offset = input.readOffset();
93                 assert length <= matchSize;
94                 int srcIndex = limit - offset - 1;
95                 if (srcIndex < 0)
96                     srcIndex += bufferLength;
97                 for (int i = 0; i < length; i++) {
98                     buffer[limit++] = buffer[srcIndex++];
99                     if (srcIndex >= bufferLength)
100                         srcIndex -= bufferLength;
101                     if (limit >= bufferLength)
102                         limit -= bufferLength;
103                 }
104                 bufferedSize += length;
105             }
106             else {
107                 buffer[limit++] = (byte)(code & 0xFF);
108                 if (limit >= bufferLength)
109                     limit -= bufferLength;
110                 ++bufferedSize;
111             }
112         }
113         return requiredSize - bufferedSize;
114     }
115
116     @Override
117     public long skip(long n) throws IOException {
118         long remaining = n;
119         byte[] bytes = new byte[8192];
120         while (remaining > 0) {
121             long requiredLength = Math.min(bytes.length, remaining);
122             assert requiredLength <= Integer.MAX_VALUE;
123             remaining -= read(bytes, 0, (int)requiredLength);
124         }
125         return n - remaining;
126     }
127
128     @Override
129     public void close() throws IOException {
130         if (closed)
131             throw new IOException("stream already closed");
132         input.close();
133     }
134
135 }