LabelValues.java

1
package com.rox.debug.labels;
2
3
import java.util.Locale;
4
import java.util.function.IntUnaryOperator;
5
6
/**
7
 * A label's bytes as text, and back - raw bytes, one per address, for any length of label (a number
8
 * view for multi-byte values can come later). Input accepts {@code $1F}, {@code 0x1F} or {@code 31} per
9
 * byte, separated by whitespace.
10
 */
11
public final class LabelValues {
12
    private static final int MAX_BYTE = 0xFF;
13
    private static final int HEX_RADIX = 16;
14
    private static final int DECIMAL_RADIX = 10;
15
    private static final int MAX_DIGITS = 6;
16
    private static final String WHITESPACE = "\\p{javaWhitespace}+";
17
18
    private LabelValues(){
19
    }
20
21
    /** {@code $01 $02} */
22
    public static String hex(final MemoryLabel label, final IntUnaryOperator peek){
23
        final StringBuilder out = new StringBuilder();
24 2 1. hex : changed conditional boundary → KILLED
2. hex : negated conditional → KILLED
        for (int address = label.start(); address <= label.end(); address++){
25 1 1. hex : negated conditional → KILLED
            if (!out.isEmpty()){
26
                out.append(' ');
27
            }
28
            out.append(String.format("$%02X", peek.applyAsInt(address)));
29
        }
30 1 1. hex : replaced return value with "" for com/rox/debug/labels/LabelValues::hex → KILLED
        return out.toString();
31
    }
32
33
    /** {@code 1 2} */
34
    public static String decimal(final MemoryLabel label, final IntUnaryOperator peek){
35
        final StringBuilder out = new StringBuilder();
36 2 1. decimal : changed conditional boundary → KILLED
2. decimal : negated conditional → KILLED
        for (int address = label.start(); address <= label.end(); address++){
37 1 1. decimal : negated conditional → KILLED
            if (!out.isEmpty()){
38
                out.append(' ');
39
            }
40
            out.append(peek.applyAsInt(address));
41
        }
42 1 1. decimal : replaced return value with "" for com/rox/debug/labels/LabelValues::decimal → KILLED
        return out.toString();
43
    }
44
45
    /**
46
     * One byte per address of {@code label}, from e.g. {@code "$1F"} or {@code "1 0x02 $FF"}.
47
     *
48
     * @throws IllegalArgumentException with a readable reason if it isn't exactly one 0-255 value per byte
49
     */
50
    public static int[] parse(final MemoryLabel label, final String text){
51
        final String trimmed = text.strip();
52 1 1. parse : negated conditional → KILLED
        final String[] tokens = trimmed.isEmpty() ? new String[0] : trimmed.split(WHITESPACE);
53 1 1. parse : negated conditional → KILLED
        if (tokens.length != label.length()){
54
            throw new IllegalArgumentException(String.format("'%s' covers %d byte%s - enter %d value%s, got %d",
55 1 1. parse : negated conditional → KILLED
                    label.name(), label.length(), label.length() == 1 ? "" : "s",
56 1 1. parse : negated conditional → KILLED
                    label.length(), label.length() == 1 ? "" : "s", tokens.length));
57
        }
58
        final int[] values = new int[tokens.length];
59 2 1. parse : changed conditional boundary → KILLED
2. parse : negated conditional → KILLED
        for (int i = 0; i < tokens.length; i++){
60
            values[i] = parseByte(tokens[i]);
61
        }
62 1 1. parse : replaced return value with null for com/rox/debug/labels/LabelValues::parse → KILLED
        return values;
63
    }
64
65
    private static int parseByte(final String token){
66 2 1. parseByte : negated conditional → KILLED
2. parseByte : negated conditional → KILLED
        final boolean hex = token.startsWith("$") || token.toLowerCase(Locale.ROOT).startsWith("0x");
67 2 1. parseByte : negated conditional → KILLED
2. parseByte : negated conditional → KILLED
        final String digits = token.startsWith("$") ? token.substring(1) : hex ? token.substring(2) : token;
68 1 1. parseByte : negated conditional → KILLED
        final int radix = hex ? HEX_RADIX : DECIMAL_RADIX;
69
        //checked by hand rather than trusting parseInt, which would also accept a sign
70 5 1. lambda$parseByte$0 : negated conditional → KILLED
2. lambda$parseByte$0 : changed conditional boundary → KILLED
3. lambda$parseByte$0 : replaced boolean return with true for com/rox/debug/labels/LabelValues::lambda$parseByte$0 → KILLED
4. parseByte : negated conditional → KILLED
5. parseByte : negated conditional → KILLED
        if (digits.isEmpty() || !digits.chars().allMatch(c -> Character.digit(c, radix) >= 0)){
71
            throw new IllegalArgumentException("'" + token + "' isn't a byte value - use e.g. 31, $1F or 0x1F");
72
        }
73
        //anything this long is out of range anyway - and parseInt would overflow on it
74 4 1. parseByte : negated conditional → KILLED
2. parseByte : changed conditional boundary → KILLED
3. parseByte : negated conditional → KILLED
4. parseByte : changed conditional boundary → KILLED
        if (digits.length() > MAX_DIGITS || Integer.parseInt(digits, radix) > MAX_BYTE){
75
            throw new IllegalArgumentException("'" + token + "' is more than a byte holds (0-255, $00-$FF)");
76
        }
77 1 1. parseByte : replaced int return with 0 for com/rox/debug/labels/LabelValues::parseByte → KILLED
        return Integer.parseInt(digits, radix);
78
    }
79
}

Mutations

24

1.1
Location : hex
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[method:formatsEachByteAsHexAndAsDecimal()]
changed conditional boundary → KILLED

2.2
Location : hex
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[method:formatsEachByteAsHexAndAsDecimal()]
negated conditional → KILLED

25

1.1
Location : hex
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[method:formatsEachByteAsHexAndAsDecimal()]
negated conditional → KILLED

30

1.1
Location : hex
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[method:formatsEachByteAsHexAndAsDecimal()]
replaced return value with "" for com/rox/debug/labels/LabelValues::hex → KILLED

36

1.1
Location : decimal
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[method:formatsEachByteAsHexAndAsDecimal()]
changed conditional boundary → KILLED

2.2
Location : decimal
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[method:formatsEachByteAsHexAndAsDecimal()]
negated conditional → KILLED

37

1.1
Location : decimal
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[method:formatsEachByteAsHexAndAsDecimal()]
negated conditional → KILLED

42

1.1
Location : decimal
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[method:formatsEachByteAsHexAndAsDecimal()]
replaced return value with "" for com/rox/debug/labels/LabelValues::decimal → KILLED

52

1.1
Location : parse
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#5]
negated conditional → KILLED

53

1.1
Location : parse
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#5]
negated conditional → KILLED

55

1.1
Location : parse
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#2]
negated conditional → KILLED

56

1.1
Location : parse
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#2]
negated conditional → KILLED

59

1.1
Location : parse
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:parsesDecimalAndHexBytes(java.lang.String, int)]/[test-template-invocation:#2]
changed conditional boundary → KILLED

2.2
Location : parse
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#5]
negated conditional → KILLED

62

1.1
Location : parse
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:parsesDecimalAndHexBytes(java.lang.String, int)]/[test-template-invocation:#4]
replaced return value with null for com/rox/debug/labels/LabelValues::parse → KILLED

66

1.1
Location : parseByte
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#10]
negated conditional → KILLED

2.2
Location : parseByte
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#11]
negated conditional → KILLED

67

1.1
Location : parseByte
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#5]
negated conditional → KILLED

2.2
Location : parseByte
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#11]
negated conditional → KILLED

68

1.1
Location : parseByte
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#10]
negated conditional → KILLED

70

1.1
Location : lambda$parseByte$0
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#7]
negated conditional → KILLED

2.2
Location : lambda$parseByte$0
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#10]
changed conditional boundary → KILLED

3.3
Location : lambda$parseByte$0
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#7]
replaced boolean return with true for com/rox/debug/labels/LabelValues::lambda$parseByte$0 → KILLED

4.4
Location : parseByte
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#5]
negated conditional → KILLED

5.5
Location : parseByte
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#7]
negated conditional → KILLED

74

1.1
Location : parseByte
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#10]
negated conditional → KILLED

2.2
Location : parseByte
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:parsesDecimalAndHexBytes(java.lang.String, int)]/[test-template-invocation:#10]
changed conditional boundary → KILLED

3.3
Location : parseByte
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:rejectsWithAReason(java.lang.String, java.lang.String)]/[test-template-invocation:#12]
negated conditional → KILLED

4.4
Location : parseByte
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:parsesDecimalAndHexBytes(java.lang.String, int)]/[test-template-invocation:#6]
changed conditional boundary → KILLED

77

1.1
Location : parseByte
Killed by : com.rox.debug.labels.LabelValuesTest.[engine:junit-jupiter]/[class:com.rox.debug.labels.LabelValuesTest]/[test-template:parsesDecimalAndHexBytes(java.lang.String, int)]/[test-template-invocation:#4]
replaced int return with 0 for com/rox/debug/labels/LabelValues::parseByte → KILLED

Active mutators

Tests examined


Report generated by PIT 1.22.1