ReplaceAllInputStream.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 static io.earcam.utilitarian.io.MarkSupportedInputStream.ensureMarkSupported;
22
23
import java.io.IOException;
24
import java.io.InputStream;
25
26
import javax.annotation.concurrent.NotThreadSafe;
27
28
/**
29
 * <p>
30
 * A search and replace filtering {@link InputStream} wrapper.
31
 * </p>
32
 *
33
 * <p>
34
 * Requires the underlying {@link InputStream} supports mark and reset; so uses
35
 * {@link MarkSupportedInputStream#ensureMarkSupported(InputStream)} to guarantee
36
 * this prerequisite.
37
 * </p>
38
 *
39
 * @see ReplaceAllOutputStream
40
 */
41
@NotThreadSafe
42
public final class ReplaceAllInputStream extends InputStream {
43
44
	private static final int UNPOSITIONED = -1;
45
	private final byte[] search;
46
	private final byte[] replace;
47
	private final InputStream wrapped;
48
	private int position = UNPOSITIONED;
49
50
51
	/**
52
	 * Create a new {@link ReplaceAllInputStream}
53
	 *
54
	 * @param search the byte sequence to search for
55
	 * @param replace the replacement byte sequence to substitute when the {@code search} sequence if found
56
	 * @param input the {@link InputStream} to operate on
57
	 */
58
	public ReplaceAllInputStream(byte[] search, byte[] replace, InputStream input)
59
	{
60
		this.search = search;
61
		this.replace = replace;
62
		this.wrapped = ensureMarkSupported(input);
63
	}
64
65
66
	@Override
67
	public int read() throws IOException
68
	{
69 3 1. read : changed conditional boundary → KILLED
2. read : negated conditional → KILLED
3. read : negated conditional → KILLED
		if(position != UNPOSITIONED && position < replace.length) {
70 3 1. read : Replaced integer addition with subtraction → KILLED
2. read : Replaced bitwise AND with OR → KILLED
3. read : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
			return replace[position++] & 0xFF;
71
		}
72
		int read = wrapped.read();
73 1 1. read : negated conditional → KILLED
		if(read == search[0]) {
74 1 1. read : removed call to java/io/InputStream::mark → KILLED
			wrapped.mark(search.length);
75
			int p = search();
76 1 1. read : negated conditional → KILLED
			if(p == search.length) {
77
				position = 1;
78 3 1. read : Replaced bitwise AND with OR → KILLED
2. read : negated conditional → KILLED
3. read : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
				return replace.length == 0 ? read() : (replace[0] & 0xFF);
79
			} else {
80 1 1. read : removed call to java/io/InputStream::reset → KILLED
				wrapped.reset();
81
			}
82
		}
83
		position = UNPOSITIONED;
84 1 1. read : replaced return of integer sized value with (x == 0 ? 1 : 0) → TIMED_OUT
		return read;
85
	}
86
87
88
	private int search() throws IOException
89
	{
90
		int p = 1;
91 3 1. search : changed conditional boundary → KILLED
2. search : negated conditional → KILLED
3. search : negated conditional → KILLED
		while(p < search.length && wrapped.read() == search[p]) {
92 1 1. search : Changed increment from 1 to -1 → KILLED
			++p;
93
		}
94 1 1. search : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
		return p;
95
	}
96
}

Mutations

69

1.1
Location : read
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.replaceSingleOccurrence()
changed conditional boundary → KILLED

2.2
Location : read
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.falseStartNoOccurrences()
negated conditional → KILLED

3.3
Location : read
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.replaceSingleOccurrence()
negated conditional → KILLED

70

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

2.2
Location : read
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.replaceSingleOccurrence()
Replaced bitwise AND with OR → KILLED

3.3
Location : read
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.replaceSingleOccurrence()
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

73

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

74

1.1
Location : read
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.falseStartNoOccurrences()
removed call to java/io/InputStream::mark → KILLED

76

1.1
Location : read
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.falseStartNoOccurrences()
negated conditional → KILLED

78

1.1
Location : read
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.replaceSingleOccurrence()
Replaced bitwise AND with OR → KILLED

2.2
Location : read
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.replaceSingleOccurrence()
negated conditional → KILLED

3.3
Location : read
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.replaceSingleOccurrence()
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

80

1.1
Location : read
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.falseStartNoOccurrences()
removed call to java/io/InputStream::reset → KILLED

84

1.1
Location : read
Killed by : none
replaced return of integer sized value with (x == 0 ? 1 : 0) → TIMED_OUT

91

1.1
Location : search
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.replaceSingleOccurrence()
changed conditional boundary → KILLED

2.2
Location : search
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.replaceSingleOccurrence()
negated conditional → KILLED

3.3
Location : search
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.replaceSingleOccurrence()
negated conditional → KILLED

92

1.1
Location : search
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.replaceSingleOccurrence()
Changed increment from 1 to -1 → KILLED

94

1.1
Location : search
Killed by : io.earcam.utilitarian.io.ReplaceAllInputStreamTest.replaceSingleOccurrence()
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

Active mutators

Tests examined


Report generated by PIT 1.4.3