|
20 | 20 |
|
21 | 21 | import java.math.BigInteger; |
22 | 22 | import java.nio.ByteOrder; |
23 | | -import java.util.HashMap; |
| 23 | +import java.util.ArrayList; |
| 24 | +import java.util.Collections; |
| 25 | +import java.util.Comparator; |
24 | 26 | import java.util.List; |
25 | 27 | import java.util.Map; |
| 28 | +import java.util.Objects; |
| 29 | +import java.util.TreeMap; |
26 | 30 |
|
27 | 31 | import org.eclipse.jdt.annotation.NonNullByDefault; |
28 | 32 | import org.eclipse.jdt.annotation.Nullable; |
@@ -132,7 +136,19 @@ public final class IntegerDeclaration extends Declaration implements ISimpleData |
132 | 136 | private final long fAlignment; |
133 | 137 | private final String fClock; |
134 | 138 | private boolean fVarint = false; |
135 | | - private Map<String, List<IntegerRange>> fMappings = new HashMap<>(); |
| 139 | + private static class IntervalNode { |
| 140 | + final long start, end; |
| 141 | + final String name; |
| 142 | + |
| 143 | + IntervalNode(long start, long end, String name) { |
| 144 | + this.start = start; |
| 145 | + this.end = end; |
| 146 | + this.name = name; |
| 147 | + } |
| 148 | + } |
| 149 | + |
| 150 | + private Map<String, List<IntegerRange>> fMappings = new TreeMap<>(); |
| 151 | + private List<IntervalNode> fIntervalTree = new ArrayList<>(); |
136 | 152 |
|
137 | 153 | // ------------------------------------------------------------------------ |
138 | 154 | // Constructors |
@@ -426,7 +442,20 @@ public Map<String, List<IntegerRange>> getMappings() { |
426 | 442 | * a mapped range of integers |
427 | 443 | */ |
428 | 444 | private void setMappings(Map<String, List<IntegerRange>> mappings) { |
429 | | - fMappings = mappings; |
| 445 | + fMappings.clear(); |
| 446 | + fMappings.putAll(mappings); |
| 447 | + buildIntervalTree(); |
| 448 | + } |
| 449 | + |
| 450 | + private void buildIntervalTree() { |
| 451 | + fIntervalTree.clear(); |
| 452 | + for (Map.Entry<String, List<IntegerRange>> entry : fMappings.entrySet()) { |
| 453 | + String name = entry.getKey(); |
| 454 | + for (IntegerRange range : entry.getValue()) { |
| 455 | + fIntervalTree.add(new IntervalNode(range.getStart(), range.getEnd(), name)); |
| 456 | + } |
| 457 | + } |
| 458 | + Collections.sort(fIntervalTree, Comparator.comparingLong(n -> n.start)); |
430 | 459 | } |
431 | 460 |
|
432 | 461 | /** |
@@ -517,11 +546,7 @@ public IntegerDefinition createDefinition(@Nullable IDefinitionScope definitionS |
517 | 546 | input.setByteOrder(fByteOrder); |
518 | 547 | long value = read(input); |
519 | 548 | input.setByteOrder(byteOrder); |
520 | | - if (fMappings.size() == 0) { |
521 | | - return new IntegerDefinition(this, definitionScope, fieldName, value); |
522 | | - } |
523 | | - String mappingName = getMappingForValue(value); |
524 | | - return new IntegerDefinition(this, definitionScope, fieldName, value, mappingName); |
| 549 | + return new IntegerDefinition(this, definitionScope, fieldName, value); |
525 | 550 | } |
526 | 551 |
|
527 | 552 | @Override |
@@ -682,25 +707,37 @@ private boolean isBinaryEquivalent(IntegerDeclaration other) { |
682 | 707 | return !((fLength != BYTE_ALIGN) && !fByteOrder.equals(other.fByteOrder)); |
683 | 708 | } |
684 | 709 |
|
685 | | - private String getMappingForValue(long value) { |
686 | | - String mapping = ""; //$NON-NLS-1$ |
687 | | - int count = 0; |
688 | | - for (Map.Entry<String, List<IntegerRange>> entry : fMappings.entrySet()) { |
689 | | - String mappingName = entry.getKey(); |
690 | | - List<IntegerRange> ranges = entry.getValue(); |
691 | | - |
692 | | - for (IntegerRange range : ranges) { |
693 | | - if (range.getStart() <= value && value <= range.getEnd()) { |
694 | | - if (count != 0) { |
695 | | - mapping += " " + mappingName; //$NON-NLS-1$ |
696 | | - } else { |
697 | | - mapping += mappingName; |
698 | | - } |
699 | | - count++; |
| 710 | + String getMappingForValue(long value) { |
| 711 | + if (fIntervalTree.isEmpty()) { |
| 712 | + return ""; //$NON-NLS-1$ |
| 713 | + } |
700 | 714 |
|
701 | | - } |
| 715 | + List<String> matches = new ArrayList<>(); |
| 716 | + |
| 717 | + // Binary search for rightmost node with start <= value |
| 718 | + int left = 0, right = fIntervalTree.size() - 1; |
| 719 | + int lastValid = -1; |
| 720 | + |
| 721 | + while (left <= right) { |
| 722 | + int mid = (left + right) / 2; |
| 723 | + if (fIntervalTree.get(mid).start <= value) { |
| 724 | + lastValid = mid; |
| 725 | + left = mid + 1; |
| 726 | + } else { |
| 727 | + right = mid - 1; |
702 | 728 | } |
703 | 729 | } |
704 | | - return mapping; |
| 730 | + |
| 731 | + // Check all nodes from lastValid backwards for overlaps |
| 732 | + for (int i = lastValid; i >= 0; i--) { |
| 733 | + IntervalNode node = fIntervalTree.get(i); |
| 734 | + if (node.end < value) { |
| 735 | + break; |
| 736 | + } |
| 737 | + matches.add(node.name); |
| 738 | + } |
| 739 | + |
| 740 | + return matches.isEmpty() ? "" : Objects.requireNonNull(String.join(" ", matches)); //$NON-NLS-1$ //$NON-NLS-2$ |
705 | 741 | } |
| 742 | + |
706 | 743 | } |
0 commit comments