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: */package org.pdfbox.io;
031:
032: import java.io.FilterInputStream;
033: import java.io.InputStream;
034: import java.io.IOException;
035:
036: /**
037: * This class represents an ASCII85 stream.
038: *
039: * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
040: * @version $Revision: 1.6 $
041: */
042: public class ASCII85InputStream extends FilterInputStream {
043: private int index;
044: private int n;
045: private boolean eof;
046:
047: private byte[] ascii;
048: private byte[] b;
049:
050: /**
051: * Constructor.
052: *
053: * @param is The input stream to actually read from.
054: */
055: public ASCII85InputStream(InputStream is) {
056: super (is);
057: index = 0;
058: n = 0;
059: eof = false;
060: ascii = new byte[5];
061: b = new byte[4];
062: }
063:
064: /**
065: * This will read the next byte from the stream.
066: *
067: * @return The next byte read from the stream.
068: *
069: * @throws IOException If there is an error reading from the wrapped stream.
070: */
071: public final int read() throws IOException {
072: if (index >= n) {
073: if (eof) {
074: return -1;
075: }
076: index = 0;
077: int k;
078: byte z;
079: do {
080: int zz = (byte) in.read();
081: if (zz == -1) {
082: eof = true;
083: return -1;
084: }
085: z = (byte) zz;
086: } while (z == '\n' || z == '\r' || z == ' ');
087:
088: if (z == '~' || z == 'x') {
089: eof = true;
090: ascii = b = null;
091: n = 0;
092: return -1;
093: } else if (z == 'z') {
094: b[0] = b[1] = b[2] = b[3] = 0;
095: n = 4;
096: } else {
097: ascii[0] = z; // may be EOF here....
098: for (k = 1; k < 5; ++k) {
099: do {
100: int zz = (byte) in.read();
101: if (zz == -1) {
102: eof = true;
103: return -1;
104: }
105: z = (byte) zz;
106: } while (z == '\n' || z == '\r' || z == ' ');
107: ascii[k] = z;
108: if (z == '~' || z == 'x') {
109: break;
110: }
111: }
112: n = k - 1;
113: if (n == 0) {
114: eof = true;
115: ascii = null;
116: b = null;
117: return -1;
118: }
119: if (k < 5) {
120: for (++k; k < 5; ++k) {
121: ascii[k] = 0x21;
122: }
123: eof = true;
124: }
125: // decode stream
126: long t = 0;
127: for (k = 0; k < 5; ++k) {
128: z = (byte) (ascii[k] - 0x21);
129: if (z < 0 || z > 93) {
130: n = 0;
131: eof = true;
132: ascii = null;
133: b = null;
134: throw new IOException(
135: "Invalid data in Ascii85 stream");
136: }
137: t = (t * 85L) + z;
138: }
139: for (k = 3; k >= 0; --k) {
140: b[k] = (byte) (t & 0xFFL);
141: t >>>= 8;
142: }
143: }
144: }
145: return b[index++] & 0xFF;
146: }
147:
148: /**
149: * This will read a chunk of data.
150: *
151: * @param data The buffer to write data to.
152: * @param offset The offset into the data stream.
153: * @param len The number of byte to attempt to read.
154: *
155: * @return The number of bytes actually read.
156: *
157: * @throws IOException If there is an error reading data from the underlying stream.
158: */
159: public final int read(byte[] data, int offset, int len)
160: 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: } else {
168: int t = read();
169: if (t == -1) {
170: return i;
171: }
172: data[i + offset] = (byte) t;
173: }
174: }
175: return len;
176: }
177:
178: /**
179: * This will close the underlying stream and release any resources.
180: *
181: * @throws IOException If there is an error closing the underlying stream.
182: */
183: public void close() throws IOException {
184: ascii = null;
185: eof = true;
186: b = null;
187: super .close();
188: }
189:
190: /**
191: * non supported interface methods.
192: *
193: * @return False always.
194: */
195: public boolean markSupported() {
196: return false;
197: }
198:
199: /**
200: * Unsupported.
201: *
202: * @param nValue ignored.
203: *
204: * @return Always zero.
205: */
206: public long skip(long nValue) {
207: return 0;
208: }
209:
210: /**
211: * Unsupported.
212: *
213: * @return Always zero.
214: */
215: public int available() {
216: return 0;
217: }
218:
219: /**
220: * Unsupported.
221: *
222: * @param readlimit ignored.
223: */
224: public void mark(int readlimit) {
225: }
226:
227: /**
228: * Unsupported.
229: *
230: * @throws IOException telling that this is an unsupported action.
231: */
232: public void reset() throws IOException {
233: throw new IOException("Reset is not supported");
234: }
235: }
|