| 1 | package com.rox.debug.labels; | |
| 2 | ||
| 3 | import java.util.regex.Pattern; | |
| 4 | ||
| 5 | /** | |
| 6 | * A name for a byte, or a run of bytes, in the CPU's address space - e.g. Zelda's rupee count. Names | |
| 7 | * are letters, digits, {@code _}, {@code .} and {@code -} only, so one always reads back unchanged from | |
| 8 | * a labels file - no whitespace (the field separator) and no {@code #} (the comment marker). | |
| 9 | * | |
| 10 | * @param length how many bytes, from {@code start} - at least 1, and not running past {@code $FFFF} | |
| 11 | */ | |
| 12 | public record MemoryLabel(String name, int start, int length) { | |
| 13 | private static final int MAX_ADDRESS = 0xFFFF; | |
| 14 | private static final Pattern VALID_NAME = Pattern.compile("[A-Za-z0-9_.\\-]+"); | |
| 15 | ||
| 16 | public MemoryLabel { | |
| 17 | if (name == null || !VALID_NAME.matcher(name).matches()){ | |
| 18 | throw new IllegalArgumentException("A label name must be letters, digits, '_', '.' or '-' only, got '" + name + "'"); | |
| 19 | } | |
| 20 | if (start < 0 || start > MAX_ADDRESS){ | |
| 21 | throw new IllegalArgumentException(String.format("Label '%s' starts outside $0000-$FFFF: %d", name, start)); | |
| 22 | } | |
| 23 | if (length < 1){ | |
| 24 | throw new IllegalArgumentException("Label '" + name + "' must cover at least one byte, got " + length); | |
| 25 | } | |
| 26 | if (start + length - 1 > MAX_ADDRESS){ | |
| 27 | throw new IllegalArgumentException(String.format("Label '%s' runs past $FFFF: $%04X + %d bytes", name, start, length)); | |
| 28 | } | |
| 29 | } | |
| 30 | ||
| 31 | /** A single-byte label. */ | |
| 32 | public static MemoryLabel at(final String name, final int address){ | |
| 33 |
1
1. at : replaced return value with null for com/rox/debug/labels/MemoryLabel::at → KILLED |
return new MemoryLabel(name, address, 1); |
| 34 | } | |
| 35 | ||
| 36 | /** A label covering {@code start} to {@code end}, both inclusive. */ | |
| 37 | public static MemoryLabel spanning(final String name, final int start, final int end){ | |
| 38 |
3
1. spanning : replaced return value with null for com/rox/debug/labels/MemoryLabel::spanning → KILLED 2. spanning : Replaced integer subtraction with addition → KILLED 3. spanning : Replaced integer addition with subtraction → KILLED |
return new MemoryLabel(name, start, end - start + 1); |
| 39 | } | |
| 40 | ||
| 41 | /** The last byte covered, inclusive. */ | |
| 42 | public int end(){ | |
| 43 |
3
1. end : Replaced integer subtraction with addition → KILLED 2. end : Replaced integer addition with subtraction → KILLED 3. end : replaced int return with 0 for com/rox/debug/labels/MemoryLabel::end → KILLED |
return start + length - 1; |
| 44 | } | |
| 45 | } | |
Mutations | ||
| 33 |
1.1 |
|
| 38 |
1.1 2.2 3.3 |
|
| 43 |
1.1 2.2 3.3 |