001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.codec.binary; 019 020 import java.io.FilterInputStream; 021 import java.io.IOException; 022 import java.io.InputStream; 023 024 /** 025 * Abstract superclass for Base-N input streams. 026 * 027 * @since 1.5 028 */ 029 public class BaseNCodecInputStream extends FilterInputStream { 030 031 private final boolean doEncode; 032 033 private final BaseNCodec baseNCodec; 034 035 private final byte[] singleByte = new byte[1]; 036 037 protected BaseNCodecInputStream(InputStream in, BaseNCodec baseNCodec, boolean doEncode) { 038 super(in); 039 this.doEncode = doEncode; 040 this.baseNCodec = baseNCodec; 041 } 042 043 /** 044 * Reads one <code>byte</code> from this input stream. 045 * 046 * @return the byte as an integer in the range 0 to 255. Returns -1 if EOF has been reached. 047 * @throws IOException 048 * if an I/O error occurs. 049 */ 050 public int read() throws IOException { 051 int r = read(singleByte, 0, 1); 052 while (r == 0) { 053 r = read(singleByte, 0, 1); 054 } 055 if (r > 0) { 056 return singleByte[0] < 0 ? 256 + singleByte[0] : singleByte[0]; 057 } 058 return -1; 059 } 060 061 /** 062 * Attempts to read <code>len</code> bytes into the specified <code>b</code> array starting at <code>offset</code> 063 * from this InputStream. 064 * 065 * @param b 066 * destination byte array 067 * @param offset 068 * where to start writing the bytes 069 * @param len 070 * maximum number of bytes to read 071 * 072 * @return number of bytes read 073 * @throws IOException 074 * if an I/O error occurs. 075 * @throws NullPointerException 076 * if the byte array parameter is null 077 * @throws IndexOutOfBoundsException 078 * if offset, len or buffer size are invalid 079 */ 080 public int read(byte b[], int offset, int len) throws IOException { 081 if (b == null) { 082 throw new NullPointerException(); 083 } else if (offset < 0 || len < 0) { 084 throw new IndexOutOfBoundsException(); 085 } else if (offset > b.length || offset + len > b.length) { 086 throw new IndexOutOfBoundsException(); 087 } else if (len == 0) { 088 return 0; 089 } else { 090 int readLen = 0; 091 /* 092 Rationale for while-loop on (readLen == 0): 093 ----- 094 Base32.readResults() usually returns > 0 or EOF (-1). In the 095 rare case where it returns 0, we just keep trying. 096 097 This is essentially an undocumented contract for InputStream 098 implementors that want their code to work properly with 099 java.io.InputStreamReader, since the latter hates it when 100 InputStream.read(byte[]) returns a zero. Unfortunately our 101 readResults() call must return 0 if a large amount of the data 102 being decoded was non-base32, so this while-loop enables proper 103 interop with InputStreamReader for that scenario. 104 ----- 105 This is a fix for CODEC-101 106 */ 107 while (readLen == 0) { 108 if (!baseNCodec.hasData()) { 109 byte[] buf = new byte[doEncode ? 4096 : 8192]; 110 int c = in.read(buf); 111 if (doEncode) { 112 baseNCodec.encode(buf, 0, c); 113 } else { 114 baseNCodec.decode(buf, 0, c); 115 } 116 } 117 readLen = baseNCodec.readResults(b, offset, len); 118 } 119 return readLen; 120 } 121 } 122 /** 123 * {@inheritDoc} 124 * 125 * @return false 126 */ 127 public boolean markSupported() { 128 return false; // not an easy job to support marks 129 } 130 131 }