/* This code is part of Freenet. It is distributed under the GNU General
* Public License, version 2 (or at your option any later version). See
* http://www.gnu.org/ for further details of the GPL. */
package freenet.support.io;
import java.io.InputStream;
import java.io.FilterInputStream;
import java.io.OutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
/**
** Utilities for manipulating headers on streams.
**
** @author infinity0
*/
final public class HeaderStreams {
private HeaderStreams() {}
/**
** Create an {@InputStream} which transparently attaches an extra header
** to the underlying stream.
*/
public static InputStream augInput(final byte[] hd, InputStream s) throws IOException {
return new FilterInputStream(s) {
/** index of next byte to read from hd */
private int i = 0;
@Override public int available() throws IOException {
return (hd.length-i) + in.available();
}
@Override public int read() throws IOException {
return (i < hd.length)? ((int)hd[i++])&0xff: in.read();
}
@Override public int read(byte[] buf, int off, int len) throws IOException {
int prev = i;
for (; i<hd.length && len>0; i++, len--, off++) {
buf[off] = hd[i];
}
return (i-prev) + in.read(buf, off, len);
//System.out.println("" + System.identityHashCode(this) + " || augInput read: " + Arrays.toString(buf) + " off " + off + " len " + len);
}
@Override public long skip(long len) throws IOException {
int prev = i;
for (; i<hd.length && len>0; i++, len--) { }
return (i-prev) + in.skip(len);
}
@Override public boolean markSupported() {
// TODO LOW
return false;
}
@Override public void mark(int limit) {
// TODO LOW
}
@Override public void reset() throws IOException {
// TODO LOW
throw new IOException("mark/reset not supported");
}
};
}
/**
** Create an {@OutputStream} which transparently swallows the expected
** header written to the underlying stream.
**
** The {@code write} methods will throw {@link IOException} if bytes
** different from the header are written.
*/
public static OutputStream dimOutput(final byte[] hd, OutputStream s) {
return new FilterOutputStream(s) {
private int i = 0;
@Override public void write(int b) throws IOException {
if (i < hd.length) {
if ((byte)b != hd[i]) { throw new IOException("byte " + i + ": expected '" + hd[i] + "'; got '" + b + "'."); }
i++;
} else {
out.write(b);
}
}
@Override public void write(byte[] buf, int off, int len) throws IOException {
for (; i<hd.length && len>0; i++, len--, off++) {
if (buf[off] != hd[i]) { throw new IOException("byte " + i + ": expected '" + hd[i] + "'; got '" + buf[off] + "'."); }
}
out.write(buf, off, len);
}
};
}
}