io.earcam.utilitarian.io.ReplaceAllInputStream Maven / Gradle / Ivy
/*-
* #%L
* io.earcam.utilitarian.file
* %%
* Copyright (C) 2017 earcam
* %%
* SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
*
* You must choose to accept, in full - any individual or combination of
* the following licenses:
*
* - BSD-3-Clause
* - EPL-1.0
* - Apache-2.0
* - MIT
*
* #L%
*/
package io.earcam.utilitarian.io;
import static io.earcam.utilitarian.io.MarkSupportedInputStream.ensureMarkSupported;
import java.io.IOException;
import java.io.InputStream;
/**
*
* A search and replace filtering {@link InputStream} wrapper.
*
*
*
* Requires the underlying {@link InputStream} supports mark and reset; so uses
* {@link MarkSupportedInputStream#ensureMarkSupported(InputStream)} to guarantee
* this prerequisite.
*
*
* @see ReplaceAllOutputStream
*/
public final class ReplaceAllInputStream extends InputStream {
private static final int UNPOSITIONED = -1;
private final byte[] search;
private final byte[] replace;
private final InputStream wrapped;
private volatile int position = UNPOSITIONED;
/**
* Create a new {@link ReplaceAllInputStream}
*
* @param search the byte sequence to search for
* @param replace the replacement byte sequence to substitute when the {@code search} sequence if found
* @param input the {@link InputStream} to operate on
*/
public ReplaceAllInputStream(byte[] search, byte[] replace, InputStream input)
{
this.search = search;
this.replace = replace;
this.wrapped = ensureMarkSupported(input);
}
@Override
public int read() throws IOException
{
if(position != UNPOSITIONED && position < replace.length) {
return replace[position++];
}
int read = wrapped.read();
if(read == search[0]) {
wrapped.mark(search.length);
int p = search();
if(p == search.length) {
position = 1;
return replace.length == 0 ? read() : replace[0];
} else {
wrapped.reset();
}
}
position = UNPOSITIONED;
return read;
}
private int search() throws IOException
{
int p = 1;
while(p < search.length && wrapped.read() == search[p]) {
++p;
}
return p;
}
}