diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/spatial/AbstractConstraintsTree.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/spatial/AbstractConstraintsTree.java index 2cb8dcc03e..5e2f5985a0 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/spatial/AbstractConstraintsTree.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/spatial/AbstractConstraintsTree.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.*; import java.util.Map.Entry; import java.util.function.Consumer; +import java.util.stream.Stream; import db.DBRecord; import generic.NestedIterator; @@ -557,17 +558,17 @@ public abstract class AbstractConstraintsTree< // node.setDataCount(node.getDataCount() - 1); } + protected NS unionStream(Stream shapes) { + return shapes.reduce(BoundingShape::unionBounds).orElse(null); + } + protected void doRecomputeBounds(NR node) { /* * TODO: There may be optimizations here, esp. if no bound of the removed node is on the * edge of the parent. Furthermore, since an implementation may index on those bounds, there * may be a fast way to discover the "next child in". */ - NS bounds = getChildrenOf(node).stream() - .map(DBTreeRecord::getBounds) - .reduce(BoundingShape::unionBounds) - .orElse(null); - node.setShape(bounds); + node.setShape(unionStream(getChildrenOf(node).stream().map(DBTreeRecord::getBounds))); } protected void doRemoveFromCachedChildren(long parentKey, R child, @@ -765,10 +766,7 @@ public abstract class AbstractConstraintsTree< // */ protected void checkNodeIntegrity(NR n) { // Check parent has exactly the minimum bounds of its children - NS expectedBounds = getChildrenOf(n).stream() - .map(DBTreeRecord::getBounds) - .reduce(BoundingShape::unionBounds) - .orElse(null); + NS expectedBounds = unionStream(getChildrenOf(n).stream().map(DBTreeRecord::getBounds)); if (expectedBounds == null && n != root) { throw new AssertionError("Non-root node cannot be empty"); } diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/spatial/AbstractRStarConstraintsTree.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/spatial/AbstractRStarConstraintsTree.java index 29e4420ed0..b924d05a9f 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/spatial/AbstractRStarConstraintsTree.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/spatial/AbstractRStarConstraintsTree.java @@ -280,18 +280,12 @@ public abstract class AbstractRStarConstraintsTree< // n2.setType(n.getType()); // Update existing node's metadata - n1.setShape(firstGroup.stream() - .map(DBTreeRecord::getBounds) - .reduce(BoundingShape::unionBounds) - .orElse(null)); + n1.setShape(unionStream(firstGroup.stream().map(DBTreeRecord::getBounds))); n1.setChildCount(index); n1.setDataCount(firstGroup.stream().mapToInt(DBTreeRecord::getDataCount).sum()); // Set new node's metadata - n2.setShape(secondGroup.stream() - .map(DBTreeRecord::getBounds) - .reduce(BoundingShape::unionBounds) - .orElse(null)); + n2.setShape(unionStream(secondGroup.stream().map(DBTreeRecord::getBounds))); n2.setChildCount(maxChildren + 1 - index); n2.setDataCount(secondGroup.stream().mapToInt(DBTreeRecord::getDataCount).sum()); @@ -329,17 +323,12 @@ public abstract class AbstractRStarConstraintsTree< // // ************X (M = 12) // mmm-------mmm (m = 3) // 8 distributions : 12 - 2*3 + 2 - NS boundsFirstKChildren = children.subList(0, minChildren) - .stream() - .map(DBTreeRecord::getBounds) - .reduce(BoundingShape::unionBounds) - .orElse(null); + NS boundsFirstKChildren = + unionStream(children.subList(0, minChildren).stream().map(DBTreeRecord::getBounds)); NS boundsLastKChildren = - children.subList(maxChildren + 1 - minChildren, maxChildren + 1) + unionStream(children.subList(maxChildren + 1 - minChildren, maxChildren + 1) .stream() - .map(DBTreeRecord::getBounds) - .reduce(BoundingShape::unionBounds) - .orElse(null); + .map(DBTreeRecord::getBounds)); int maxK = maxChildren + 1 - minChildren * 2; double marginValue = 0; @@ -376,16 +365,12 @@ public abstract class AbstractRStarConstraintsTree< // // mmm-------mmm (m = 3) // 8 distributions : 12 - 2*3 + 2 - NS boundsFirstKChildren = children.subList(0, minChildren) - .stream() - .map(DBTreeRecord::getBounds) - .reduce(BoundingShape::unionBounds) - .orElse(null); - NS boundsLastKChildren = children.subList(maxChildren + 1 - minChildren, maxChildren + 1) - .stream() - .map(DBTreeRecord::getBounds) - .reduce(BoundingShape::unionBounds) - .orElse(null); + NS boundsFirstKChildren = + unionStream(children.subList(0, minChildren).stream().map(DBTreeRecord::getBounds)); + NS boundsLastKChildren = + unionStream(children.subList(maxChildren + 1 - minChildren, maxChildren + 1) + .stream() + .map(DBTreeRecord::getBounds)); int maxK = maxChildren + 1 - minChildren * 2; Deque boundsFirsts = new ArrayDeque<>(); @@ -580,10 +565,7 @@ public abstract class AbstractRStarConstraintsTree< // p.setDataCount(newDataCount); // I can't think of a better way to re-compute the bounds in the path - p.setShape(getChildrenOf(p).stream() - .map(DBTreeRecord::getBounds) - .reduce(BoundingShape::unionBounds) - .orElse(null)); + p.setShape(unionStream(getChildrenOf(p).stream().map(DBTreeRecord::getBounds))); p = getParentOf(p); }