ReplaceAllOutputStream.java

1
/*-
2
 * #%L
3
 * io.earcam.utilitarian.io
4
 * %%
5
 * Copyright (C) 2017 earcam
6
 * %%
7
 * SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
8
 *
9
 * You <b>must</b> choose to accept, in full - any individual or combination of
10
 * the following licenses:
11
 * <ul>
12
 * 	<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li>
13
 * 	<li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li>
14
 * 	<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li>
15
 * 	<li><a href="https://opensource.org/licenses/MIT">MIT</a></li>
16
 * </ul>
17
 * #L%
18
 */
19
package io.earcam.utilitarian.io;
20
21
import java.io.IOException;
22
import java.io.OutputStream;
23
24
import javax.annotation.concurrent.NotThreadSafe;
25
26
/**
27
 * A search and replace filtering {@link OutputStream} wrapper
28
 *
29
 * @see ReplaceAllInputStream
30
 */
31
@SuppressWarnings("squid:S4349") // Sonar: Not applicable IMO
32
@NotThreadSafe
33
public final class ReplaceAllOutputStream extends OutputStream {
34
35
	private final byte[] search;
36
	private final byte[] replace;
37
	private final OutputStream wrapped;
38
	private int position;
39
40
41
	/**
42
	 * Create a new {@link ReplaceAllOutputStream}
43
	 *
44
	 * @param search the byte sequence to search for
45
	 * @param replace the replacement byte sequence to substitute when the {@code search} sequence if found
46
	 * @param output the {@link OutputStream} to operate on
47
	 */
48
	public ReplaceAllOutputStream(byte[] search, byte[] replace, OutputStream output)
49
	{
50
		this.search = search;
51
		this.replace = replace;
52
		this.wrapped = output;
53
		this.position = 0;
54
	}
55
56
57
	@Override
58
	public void write(int b) throws IOException
59
	{
60 1 1. write : negated conditional → KILLED
		if(position == search.length) {
61 1 1. write : removed call to java/io/OutputStream::write → KILLED
			wrapped.write(replace);
62
			position = 0;
63
		}
64 1 1. write : negated conditional → KILLED
		if(search[position] == b) {
65 1 1. write : Replaced integer addition with subtraction → KILLED
			++position;
66
		} else {
67 1 1. write : removed call to java/io/OutputStream::write → KILLED
			wrapped.write(search, 0, position);
68 1 1. write : removed call to java/io/OutputStream::write → KILLED
			wrapped.write(b);
69
			position = 0;
70
		}
71
	}
72
73
74
	@Override
75
	public void close() throws IOException
76
	{
77 2 1. close : changed conditional boundary → SURVIVED
2. close : negated conditional → KILLED
		if(position > 0) {
78 1 1. close : removed call to java/io/OutputStream::write → KILLED
			wrapped.write(search, 0, position);
79
		}
80 1 1. close : removed call to java/io/OutputStream::close → KILLED
		wrapped.close();
81
	}
82
}

Mutations

60

1.1
Location : write
Killed by : io.earcam.utilitarian.io.ReplaceAllOutputStreamTest.replaceSingleOccurrence()
negated conditional → KILLED

61

1.1
Location : write
Killed by : io.earcam.utilitarian.io.ReplaceAllOutputStreamTest.replaceSingleOccurrence()
removed call to java/io/OutputStream::write → KILLED

64

1.1
Location : write
Killed by : io.earcam.utilitarian.io.ReplaceAllOutputStreamTest.replaceSingleOccurrence()
negated conditional → KILLED

65

1.1
Location : write
Killed by : io.earcam.utilitarian.io.ReplaceAllOutputStreamTest.replaceSingleOccurrence()
Replaced integer addition with subtraction → KILLED

67

1.1
Location : write
Killed by : io.earcam.utilitarian.io.ReplaceAllOutputStreamTest.replaceSingleOccurrence()
removed call to java/io/OutputStream::write → KILLED

68

1.1
Location : write
Killed by : io.earcam.utilitarian.io.ReplaceAllOutputStreamTest.replaceSingleOccurrence()
removed call to java/io/OutputStream::write → KILLED

77

1.1
Location : close
Killed by : none
changed conditional boundary → SURVIVED

2.2
Location : close
Killed by : io.earcam.utilitarian.io.ReplaceAllOutputStreamTest.replaceConsecutiveOccurrences()
negated conditional → KILLED

78

1.1
Location : close
Killed by : io.earcam.utilitarian.io.ReplaceAllOutputStreamTest.replaceConsecutiveOccurrences()
removed call to java/io/OutputStream::write → KILLED

80

1.1
Location : close
Killed by : io.earcam.utilitarian.io.ReplaceAllOutputStreamTest.whenClosedThenClosesUnderlying()
removed call to java/io/OutputStream::close → KILLED

Active mutators

Tests examined


Report generated by PIT 1.4.3