001 /*
002 * Copyright (c) 2003, www.pdfbox.org
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without
006 * modification, are permitted provided that the following conditions are met:
007 *
008 * 1. Redistributions of source code must retain the above copyright notice,
009 * this list of conditions and the following disclaimer.
010 * 2. Redistributions in binary form must reproduce the above copyright notice,
011 * this list of conditions and the following disclaimer in the documentation
012 * and/or other materials provided with the distribution.
013 * 3. Neither the name of pdfbox; nor the names of its
014 * contributors may be used to endorse or promote products derived from this
015 * software without specific prior written permission.
016 *
017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
021 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027 *
028 * http://www.pdfbox.org
029 *
030 */
031 package com.imagero.uio.io;
032
033 import java.io.FilterInputStream;
034 import java.io.IOException;
035 import java.io.InputStream;
036
037 /**
038 * This class represents an ASCII85 stream.
039 *
040 * @author Ben Litchfield
041 * @version $Revision: 1.2 $
042 */
043 public class ASCII85InputStream extends FilterInputStream {
044 private int index;
045 private int n;
046 private boolean eof;
047
048 private byte[] ascii;
049 private byte[] b;
050
051 /**
052 * Constructor.
053 *
054 * @param is The input stream to actually read from.
055 */
056 public ASCII85InputStream(InputStream is) {
057 super(is);
058 ascii = new byte[5];
059 b = new byte[4];
060 }
061
062 /**
063 * This will read the next byte from the stream.
064 *
065 * @return The next byte read from the stream.
066 *
067 * @throws IOException If there is an error reading from the wrapped stream.
068 */
069 public final int read() throws IOException {
070 if (index >= n) {
071 if (eof) {
072 return -1;
073 }
074 index = 0;
075 int k;
076 byte z;
077 do {
078 int zz = (byte) in.read();
079 if (zz == -1) {
080 eof = true;
081 return -1;
082 }
083 z = (byte) zz;
084 }
085 while (z == '\n' || z == '\r' || z == ' ');
086
087 if (z == '~' || z == 'x') {
088 eof = true;
089 ascii = b = null;
090 n = 0;
091 return -1;
092 }
093 else if (z == 'z') {
094 b[0] = b[1] = b[2] = b[3] = 0;
095 n = 4;
096 }
097 else {
098 ascii[0] = z; // may be EOF here....
099 for (k = 1; k < 5; ++k) {
100 do {
101 int zz = (byte) in.read();
102 if (zz == -1) {
103 eof = true;
104 return -1;
105 }
106 z = (byte) zz;
107 }
108 while (z == '\n' || z == '\r' || z == ' ');
109 ascii[k] = z;
110 if (z == '~' || z == 'x') {
111 break;
112 }
113 }
114 n = k - 1;
115 if (n == 0) {
116 eof = true;
117 ascii = null;
118 b = null;
119 return -1;
120 }
121 if (k < 5) {
122 for (++k; k < 5; ++k) {
123 ascii[k] = 0x21;
124 }
125 eof = true;
126 }
127 // decode stream
128 long t = 0;
129 for (k = 0; k < 5; ++k) {
130 z = (byte) (ascii[k] - 0x21);
131 if (z < 0 || z > 93) {
132 n = 0;
133 eof = true;
134 ascii = null;
135 b = null;
136 throw new IOException("Invalid data in Ascii85 stream");
137 }
138 t = (t * 85L) + z;
139 }
140 for (k = 3; k >= 0; --k) {
141 b[k] = (byte) (t & 0xFFL);
142 t >>>= 8;
143 }
144 }
145 }
146 return b[index++] & 0xFF;
147 }
148
149 /**
150 * This will read a chunk of data.
151 *
152 * @param data The buffer to write data to.
153 * @param offset The offset into the data stream.
154 * @param len The number of byte to attempt to read.
155 *
156 * @return The number of bytes actually read.
157 *
158 * @throws IOException If there is an error reading data from the underlying stream.
159 */
160 public final int read(byte[] data, int offset, int len) throws IOException {
161 if (eof && index >= n) {
162 return -1;
163 }
164 for (int i = 0; i < len; i++) {
165 if (index < n) {
166 data[i + offset] = b[index++];
167 }
168 else {
169 int t = read();
170 if (t == -1) {
171 return i;
172 }
173 data[i + offset] = (byte) t;
174 }
175 }
176 return len;
177 }
178
179 /**
180 * This will close the underlying stream and release any resources.
181 *
182 * @throws IOException If there is an error closing the underlying stream.
183 */
184 public void close() throws IOException {
185 ascii = null;
186 eof = true;
187 b = null;
188 super.close();
189 }
190
191 /**
192 * non supported interface methods.
193 *
194 * @return False always.
195 */
196 public boolean markSupported() {
197 return false;
198 }
199
200 /**
201 * Unsupported.
202 *
203 * @param nValue ignored.
204 *
205 * @return Always zero.
206 */
207 public long skip(long nValue) {
208 return 0;
209 }
210
211 /**
212 * Unsupported.
213 *
214 * @return Always zero.
215 */
216 public int available() {
217 if (eof) {
218 return 0;
219 }
220 else {
221 return 1;
222 }
223 }
224
225 /**
226 * Unsupported.
227 *
228 * @param readlimit ignored.
229 */
230 public void mark(int readlimit) {
231 }
232
233 /**
234 * Unsupported.
235 *
236 * @throws IOException telling that this is an unsupported action.
237 */
238 public void reset() throws IOException {
239 throw new IOException("Reset is not supported");
240 }
241 }