1 | package com.renomad.minum.web; | |
2 | ||
3 | import com.renomad.minum.security.ForbiddenUseException; | |
4 | import com.renomad.minum.utils.UtilsException; | |
5 | ||
6 | import java.io.ByteArrayOutputStream; | |
7 | import java.io.IOException; | |
8 | import java.io.InputStream; | |
9 | import java.nio.charset.StandardCharsets; | |
10 | import java.util.Objects; | |
11 | ||
12 | /** | |
13 | * Handy helpful utilities for working with input streams. | |
14 | */ | |
15 | final class InputStreamUtils implements IInputStreamUtils { | |
16 | ||
17 | private final int maxReadLineSizeBytes; | |
18 | ||
19 | public InputStreamUtils(int maxReadLineSizeBytes) { | |
20 | this.maxReadLineSizeBytes = maxReadLineSizeBytes; | |
21 | } | |
22 | ||
23 | @Override | |
24 | public String readLine(InputStream inputStream) throws IOException { | |
25 | final int NEWLINE_DECIMAL = 10; | |
26 | final int CARRIAGE_RETURN_DECIMAL = 13; | |
27 | ||
28 |
1
1. readLine : Replaced integer division with multiplication → SURVIVED |
final var result = new ByteArrayOutputStream(maxReadLineSizeBytes / 3); |
29 |
1
1. readLine : Changed increment from 1 to -1 → KILLED |
for (int i = 0;; i++) { |
30 |
2
1. readLine : changed conditional boundary → SURVIVED 2. readLine : negated conditional → KILLED |
if (i >= maxReadLineSizeBytes) { |
31 |
1
1. readLine : removed call to java/io/InputStream::close → KILLED |
inputStream.close(); |
32 | throw new ForbiddenUseException("client sent more bytes than allowed for a single line. max: " + maxReadLineSizeBytes); | |
33 | } | |
34 | int a = inputStream.read(); | |
35 |
2
1. readLine : replaced return value with "" for com/renomad/minum/web/InputStreamUtils::readLine → SURVIVED 2. readLine : negated conditional → KILLED |
if (a == -1) return result.toString(StandardCharsets.UTF_8); |
36 |
1
1. readLine : negated conditional → KILLED |
if (a == CARRIAGE_RETURN_DECIMAL) continue; |
37 |
1
1. readLine : negated conditional → KILLED |
if (a == NEWLINE_DECIMAL) break; |
38 |
1
1. readLine : removed call to java/io/ByteArrayOutputStream::write → KILLED |
result.write(a); |
39 | } | |
40 |
1
1. readLine : replaced return value with "" for com/renomad/minum/web/InputStreamUtils::readLine → KILLED |
return result.toString(StandardCharsets.UTF_8); |
41 | } | |
42 | ||
43 | @Override | |
44 | public byte[] read(int lengthToRead, InputStream inputStream) { | |
45 | final int typicalBufferSize = 1024 * 8; | |
46 | byte[] buf = new byte[Math.min(lengthToRead, typicalBufferSize)]; // 8k buffer is my understanding of a decent size. Fast, doesn't waste too much space. | |
47 | byte[] data; | |
48 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
49 | int read; | |
50 | int totalRead = 0; | |
51 | try { | |
52 |
2
1. read : changed conditional boundary → KILLED 2. read : negated conditional → KILLED |
while ((read = inputStream.read(buf)) >= 0) { |
53 |
1
1. read : Replaced integer addition with subtraction → KILLED |
totalRead += read; |
54 |
2
1. read : negated conditional → KILLED 2. read : changed conditional boundary → KILLED |
if (totalRead < lengthToRead) { |
55 | // if we haven't gotten everything we wanted, write this to the output and loop again | |
56 |
1
1. read : removed call to java/io/ByteArrayOutputStream::write → KILLED |
baos.write(buf, 0, read); |
57 | } else { | |
58 |
3
1. read : Replaced integer subtraction with addition → SURVIVED 2. read : Replaced integer subtraction with addition → KILLED 3. read : removed call to java/io/ByteArrayOutputStream::write → KILLED |
baos.write(buf, 0, read - (totalRead - lengthToRead)); |
59 | break; | |
60 | } | |
61 | } | |
62 | } catch (IOException ex) { | |
63 | throw new UtilsException(ex); | |
64 | } | |
65 | data = baos.toByteArray(); | |
66 | ||
67 |
1
1. read : negated conditional → KILLED |
if (data.length != lengthToRead) { |
68 | String message = String.format("length of bytes read (%d) must be what we expected (%d)", data.length, lengthToRead); | |
69 | throw new ForbiddenUseException(message); | |
70 | } | |
71 |
1
1. read : replaced return value with null for com/renomad/minum/web/InputStreamUtils::read → KILLED |
return data; |
72 | } | |
73 | ||
74 | @Override | |
75 | public boolean equals(Object o) { | |
76 |
2
1. equals : negated conditional → KILLED 2. equals : replaced boolean return with false for com/renomad/minum/web/InputStreamUtils::equals → KILLED |
if (this == o) return true; |
77 |
3
1. equals : negated conditional → KILLED 2. equals : negated conditional → KILLED 3. equals : replaced boolean return with true for com/renomad/minum/web/InputStreamUtils::equals → KILLED |
if (o == null || getClass() != o.getClass()) return false; |
78 | InputStreamUtils that = (InputStreamUtils) o; | |
79 |
2
1. equals : negated conditional → KILLED 2. equals : replaced boolean return with true for com/renomad/minum/web/InputStreamUtils::equals → KILLED |
return maxReadLineSizeBytes == that.maxReadLineSizeBytes; |
80 | } | |
81 | ||
82 | @Override | |
83 | public int hashCode() { | |
84 |
1
1. hashCode : replaced int return with 0 for com/renomad/minum/web/InputStreamUtils::hashCode → KILLED |
return Objects.hash(maxReadLineSizeBytes); |
85 | } | |
86 | } | |
Mutations | ||
28 |
1.1 |
|
29 |
1.1 |
|
30 |
1.1 2.2 |
|
31 |
1.1 |
|
35 |
1.1 2.2 |
|
36 |
1.1 |
|
37 |
1.1 |
|
38 |
1.1 |
|
40 |
1.1 |
|
52 |
1.1 2.2 |
|
53 |
1.1 |
|
54 |
1.1 2.2 |
|
56 |
1.1 |
|
58 |
1.1 2.2 3.3 |
|
67 |
1.1 |
|
71 |
1.1 |
|
76 |
1.1 2.2 |
|
77 |
1.1 2.2 3.3 |
|
79 |
1.1 2.2 |
|
84 |
1.1 |