blob: 4c6217e62637281d0e909e903c414f15393d55e8 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE.txt file distributed with this work for
// additional information regarding copyright ownership. The ASF licenses this
// file to you under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
package org.apache.oodt.commons.io;
import java.io.IOException;
import java.io.OutputStream;
/** This stream writes its output into a byte buffer of fixed length.
*
* For a buffer of size <var>n</var>, only the last <var>n</var> bytes written are ever
* available.
*
* @author Kelly
*/
public class FixedBufferOutputStream extends OutputStream {
/** Construct a fixed buffer output stream.
*
* @param n Size of the buffer.
*/
public FixedBufferOutputStream(int n) {
if (n < 0) throw new IllegalArgumentException("Buffer size must be nonnegative");
buffer = new byte[n];
length = n;
size = 0;
start = 0;
}
public void write(int b) throws IOException {
checkIfClosed();
if (length == 0) return;
if (size < length)
buffer[size++] = (byte) b;
else {
buffer[start] = (byte) b;
start = (start + 1) % length;
}
}
public void write(byte[] a, int off, int len) throws IOException {
checkIfClosed();
if (a == null) throw new NullPointerException("Can't write from a null array");
else if ((off < 0) || (off > a.length) || (len < 0) || ((off + len) > a.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException("Offset " + off + " and length " + len + " not within array bounds");
} else if (len == 0) {
return;
}
if (len > length) {
off += len - length;
len = length;
}
int capacity = length - size;
int insertionIndex = size < length? size : start;
int insertionLength = Math.min(length - insertionIndex, len);
int remaining = len - insertionLength;
System.arraycopy(a, off, buffer, insertionIndex, insertionLength);
if (remaining > 0) {
System.arraycopy(a, off + insertionLength, buffer, 0, remaining);
start = remaining;
} else if (capacity == 0)
start = insertionIndex + insertionLength;
size = Math.min(length, size + len);
}
public void flush() {
// Nothing need be done here
}
public void close() {
start = -1;
}
/** Get the buffer.
*
* This method constructs a new array whose contents is the data written. Its
* size is equal to the smaller of the number of bytes written or the size of the
* fixed buffer passed to the constructor of this class.
*
* @return The buffer.
*/
public byte[] getBuffer() {
byte[] rc = new byte[Math.min(size, length)];
System.arraycopy(buffer, start, rc, 0, size - start);
System.arraycopy(buffer, 0, rc, size - start, start);
return rc;
}
/** Throw an exception if we've been closed.
*
* @throws IOException If this stream has been closed.
*/
private void checkIfClosed() throws IOException {
if (start == -1) throw new IOException("Can't write to closed stream");
}
/** Length of the buffer. */
private int length;
/** Current size of the data in the buffer. */
private int size;
/** Current start offset of the data in the buffer. If negative, buffer is closed. */
private int start;
/** The buffer. */
private byte[] buffer;
}