1 // Mozilla has modified this file - see https://hg.mozilla.org/ for details. 2 /* 3 * Licensed to the Apache Software Foundation (ASF) under one or more 4 * contributor license agreements. See the NOTICE file distributed with 5 * this work for additional information regarding copyright ownership. 6 * The ASF licenses this file to You under the Apache License, Version 2.0 7 * (the "License"); you may not use this file except in compliance with 8 * the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.mozilla.apache.commons.codec.binary; 20 21 import java.io.FilterOutputStream; 22 import java.io.IOException; 23 import java.io.OutputStream; 24 25 /** 26 * Abstract superclass for Base-N output streams. 27 * 28 * @since 1.5 29 */ 30 public class BaseNCodecOutputStream extends FilterOutputStream { 31 32 private final boolean doEncode; 33 34 private final BaseNCodec baseNCodec; 35 36 private final byte[] singleByte = new byte[1]; 37 BaseNCodecOutputStream(OutputStream out, BaseNCodec basedCodec, boolean doEncode)38 public BaseNCodecOutputStream(OutputStream out, BaseNCodec basedCodec, boolean doEncode) { 39 super(out); 40 this.baseNCodec = basedCodec; 41 this.doEncode = doEncode; 42 } 43 44 /** 45 * Writes the specified <code>byte</code> to this output stream. 46 * 47 * @param i 48 * source byte 49 * @throws IOException 50 * if an I/O error occurs. 51 */ write(int i)52 public void write(int i) throws IOException { 53 singleByte[0] = (byte) i; 54 write(singleByte, 0, 1); 55 } 56 57 /** 58 * Writes <code>len</code> bytes from the specified <code>b</code> array starting at <code>offset</code> to this 59 * output stream. 60 * 61 * @param b 62 * source byte array 63 * @param offset 64 * where to start reading the bytes 65 * @param len 66 * maximum number of bytes to write 67 * 68 * @throws IOException 69 * if an I/O error occurs. 70 * @throws NullPointerException 71 * if the byte array parameter is null 72 * @throws IndexOutOfBoundsException 73 * if offset, len or buffer size are invalid 74 */ write(byte b[], int offset, int len)75 public void write(byte b[], int offset, int len) throws IOException { 76 if (b == null) { 77 throw new NullPointerException(); 78 } else if (offset < 0 || len < 0) { 79 throw new IndexOutOfBoundsException(); 80 } else if (offset > b.length || offset + len > b.length) { 81 throw new IndexOutOfBoundsException(); 82 } else if (len > 0) { 83 if (doEncode) { 84 baseNCodec.encode(b, offset, len); 85 } else { 86 baseNCodec.decode(b, offset, len); 87 } 88 flush(false); 89 } 90 } 91 92 /** 93 * Flushes this output stream and forces any buffered output bytes to be written out to the stream. If propogate is 94 * true, the wrapped stream will also be flushed. 95 * 96 * @param propogate 97 * boolean flag to indicate whether the wrapped OutputStream should also be flushed. 98 * @throws IOException 99 * if an I/O error occurs. 100 */ flush(boolean propogate)101 private void flush(boolean propogate) throws IOException { 102 int avail = baseNCodec.available(); 103 if (avail > 0) { 104 byte[] buf = new byte[avail]; 105 int c = baseNCodec.readResults(buf, 0, avail); 106 if (c > 0) { 107 out.write(buf, 0, c); 108 } 109 } 110 if (propogate) { 111 out.flush(); 112 } 113 } 114 115 /** 116 * Flushes this output stream and forces any buffered output bytes to be written out to the stream. 117 * 118 * @throws IOException 119 * if an I/O error occurs. 120 */ flush()121 public void flush() throws IOException { 122 flush(true); 123 } 124 125 /** 126 * Closes this output stream and releases any system resources associated with the stream. 127 * 128 * @throws IOException 129 * if an I/O error occurs. 130 */ close()131 public void close() throws IOException { 132 // Notify encoder of EOF (-1). 133 if (doEncode) { 134 baseNCodec.encode(singleByte, 0, -1); 135 } else { 136 baseNCodec.decode(singleByte, 0, -1); 137 } 138 flush(); 139 out.close(); 140 } 141 142 } 143