ReplaceAllOutputStream.java
/*-
* #%L
* io.earcam.utilitarian.io
* %%
* Copyright (C) 2017 earcam
* %%
* SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
*
* You <b>must</b> choose to accept, in full - any individual or combination of
* the following licenses:
* <ul>
* <li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li>
* <li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li>
* <li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li>
* <li><a href="https://opensource.org/licenses/MIT">MIT</a></li>
* </ul>
* #L%
*/
package io.earcam.utilitarian.io;
import java.io.IOException;
import java.io.OutputStream;
import javax.annotation.concurrent.NotThreadSafe;
/**
* A search and replace filtering {@link OutputStream} wrapper
*
* @see ReplaceAllInputStream
*/
@SuppressWarnings("squid:S4349") // Sonar: Not applicable IMO
@NotThreadSafe
public final class ReplaceAllOutputStream extends OutputStream {
private final byte[] search;
private final byte[] replace;
private final OutputStream wrapped;
private int position;
/**
* Create a new {@link ReplaceAllOutputStream}
*
* @param search the byte sequence to search for
* @param replace the replacement byte sequence to substitute when the {@code search} sequence if found
* @param output the {@link OutputStream} to operate on
*/
public ReplaceAllOutputStream(byte[] search, byte[] replace, OutputStream output)
{
this.search = search;
this.replace = replace;
this.wrapped = output;
this.position = 0;
}
@Override
public void write(int b) throws IOException
{
if(position == search.length) {
wrapped.write(replace);
position = 0;
}
if(search[position] == b) {
++position;
} else {
wrapped.write(search, 0, position);
wrapped.write(b);
position = 0;
}
}
@Override
public void close() throws IOException
{
if(position > 0) {
wrapped.write(search, 0, position);
}
wrapped.close();
}
}