mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Test fix; update Code Browser to have both setView() and updateView()
This commit is contained in:
parent
15203337f5
commit
dd15eca6b5
10 changed files with 297 additions and 61 deletions
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.gui.listing;
|
package ghidra.app.plugin.core.debug.gui.listing;
|
||||||
|
|
||||||
import static ghidra.app.plugin.core.debug.gui.DebuggerResources.GROUP_TRANSIENT_VIEWS;
|
import static ghidra.app.plugin.core.debug.gui.DebuggerResources.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -81,7 +81,8 @@ import ghidra.trace.model.program.TraceProgramView;
|
||||||
},
|
},
|
||||||
servicesProvided = {
|
servicesProvided = {
|
||||||
DebuggerListingService.class,
|
DebuggerListingService.class,
|
||||||
})
|
}
|
||||||
|
)
|
||||||
public class DebuggerListingPlugin extends AbstractCodeBrowserPlugin<DebuggerListingProvider>
|
public class DebuggerListingPlugin extends AbstractCodeBrowserPlugin<DebuggerListingProvider>
|
||||||
implements DebuggerListingService {
|
implements DebuggerListingService {
|
||||||
private static final String KEY_CONNECTED_PROVIDER = "connectedProvider";
|
private static final String KEY_CONNECTED_PROVIDER = "connectedProvider";
|
||||||
|
@ -180,13 +181,13 @@ public class DebuggerListingPlugin extends AbstractCodeBrowserPlugin<DebuggerLis
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void viewChanged(AddressSetView addrSet) {
|
protected void setView(AddressSetView addrSet) {
|
||||||
TraceProgramView view = current.getView();
|
TraceProgramView view = current.getView();
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
super.viewChanged(new AddressSet());
|
super.setView(new AddressSet());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
super.viewChanged(view.getMemory());
|
super.setView(view.getMemory());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ public abstract class AbstractCodeBrowserPlugin<P extends CodeViewerProvider> ex
|
||||||
protected FormatManager formatMgr;
|
protected FormatManager formatMgr;
|
||||||
protected ViewManagerService viewManager;
|
protected ViewManagerService viewManager;
|
||||||
private MarkerService markerService;
|
private MarkerService markerService;
|
||||||
protected AddressSetView currentView;
|
protected AddressSetView currentView = ImmutableAddressSet.EMPTY_SET;
|
||||||
protected Program currentProgram;
|
protected Program currentProgram;
|
||||||
private boolean selectionChanging;
|
private boolean selectionChanging;
|
||||||
private MarkerSet currentSelectionMarkers;
|
private MarkerSet currentSelectionMarkers;
|
||||||
|
@ -118,20 +118,26 @@ public abstract class AbstractCodeBrowserPlugin<P extends CodeViewerProvider> ex
|
||||||
|
|
||||||
protected abstract P createProvider(FormatManager formatManager, boolean isConnected);
|
protected abstract P createProvider(FormatManager formatManager, boolean isConnected);
|
||||||
|
|
||||||
protected void viewChanged(AddressSetView addrSet) {
|
protected void setView(AddressSetView newView) {
|
||||||
ProgramLocation currLoc = getCurrentLocation();
|
|
||||||
currentView = addrSet;
|
|
||||||
if (addrSet != null && !addrSet.isEmpty()) {
|
|
||||||
connectedProvider.setView(addrSet);
|
|
||||||
if (currLoc != null && addrSet.contains(currLoc.getAddress())) {
|
|
||||||
goTo(currLoc, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
connectedProvider.setView(new AddressSet());
|
|
||||||
}
|
|
||||||
updateBackgroundColorModel();
|
|
||||||
|
|
||||||
|
if (currentView.hasSameAddresses(newView)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramLocation location = getCurrentLocation();
|
||||||
|
currentView = ImmutableAddressSet.asImmutable(newView);
|
||||||
|
|
||||||
|
connectedProvider.setView(currentView);
|
||||||
|
|
||||||
|
if (location != null && currentView.contains(location.getAddress())) {
|
||||||
|
goTo(location, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
viewUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void viewUpdated() {
|
||||||
|
updateBackgroundColorModel();
|
||||||
setHighlight(connectedProvider.getHighlight());
|
setHighlight(connectedProvider.getHighlight());
|
||||||
setSelection(connectedProvider.getSelection());
|
setSelection(connectedProvider.getSelection());
|
||||||
}
|
}
|
||||||
|
@ -168,7 +174,7 @@ public abstract class AbstractCodeBrowserPlugin<P extends CodeViewerProvider> ex
|
||||||
listingPanel.setBackgroundColorModel(null);
|
listingPanel.setBackgroundColorModel(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: update all providers, not just the connected provider
|
// Note: this should update all providers, not just the connected provider
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -220,14 +226,14 @@ public abstract class AbstractCodeBrowserPlugin<P extends CodeViewerProvider> ex
|
||||||
public void serviceAdded(Class<?> interfaceClass, Object service) {
|
public void serviceAdded(Class<?> interfaceClass, Object service) {
|
||||||
if (interfaceClass == ViewManagerService.class && viewManager == null) {
|
if (interfaceClass == ViewManagerService.class && viewManager == null) {
|
||||||
viewManager = (ViewManagerService) service;
|
viewManager = (ViewManagerService) service;
|
||||||
viewChanged(viewManager.getCurrentView());
|
setView(viewManager.getCurrentView());
|
||||||
}
|
}
|
||||||
if (interfaceClass == MarkerService.class && markerService == null) {
|
if (interfaceClass == MarkerService.class && markerService == null) {
|
||||||
markerService = tool.getService(MarkerService.class);
|
markerService = tool.getService(MarkerService.class);
|
||||||
markerService.addChangeListener(markerChangeListener);
|
markerService.addChangeListener(markerChangeListener);
|
||||||
updateBackgroundColorModel();
|
updateBackgroundColorModel();
|
||||||
if (viewManager != null) {
|
if (viewManager != null) {
|
||||||
viewChanged(viewManager.getCurrentView());
|
viewUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (interfaceClass == ListingHoverService.class) {
|
if (interfaceClass == ListingHoverService.class) {
|
||||||
|
@ -247,7 +253,7 @@ public abstract class AbstractCodeBrowserPlugin<P extends CodeViewerProvider> ex
|
||||||
public void serviceRemoved(Class<?> interfaceClass, Object service) {
|
public void serviceRemoved(Class<?> interfaceClass, Object service) {
|
||||||
if ((service == viewManager) && (currentProgram != null)) {
|
if ((service == viewManager) && (currentProgram != null)) {
|
||||||
viewManager = null;
|
viewManager = null;
|
||||||
viewChanged(currentProgram.getMemory());
|
setView(currentProgram.getMemory());
|
||||||
}
|
}
|
||||||
if (service == markerService) {
|
if (service == markerService) {
|
||||||
markerService.removeChangeListener(markerChangeListener);
|
markerService.removeChangeListener(markerChangeListener);
|
||||||
|
@ -338,7 +344,7 @@ public abstract class AbstractCodeBrowserPlugin<P extends CodeViewerProvider> ex
|
||||||
@Override
|
@Override
|
||||||
public void setListingPanel(ListingPanel lp) {
|
public void setListingPanel(ListingPanel lp) {
|
||||||
connectedProvider.setOtherPanel(lp);
|
connectedProvider.setOtherPanel(lp);
|
||||||
viewChanged(currentView);
|
viewUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -363,7 +369,7 @@ public abstract class AbstractCodeBrowserPlugin<P extends CodeViewerProvider> ex
|
||||||
}
|
}
|
||||||
if (connectedProvider.getOtherPanel() == lp) {
|
if (connectedProvider.getOtherPanel() == lp) {
|
||||||
connectedProvider.clearPanel();
|
connectedProvider.clearPanel();
|
||||||
viewChanged(currentView);
|
viewUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -857,11 +863,11 @@ public abstract class AbstractCodeBrowserPlugin<P extends CodeViewerProvider> ex
|
||||||
connectedProvider.updateTitle();
|
connectedProvider.updateTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewManager != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ev.contains(DomainObjectEvent.RESTORED)) {
|
if (ev.contains(DomainObjectEvent.RESTORED)) {
|
||||||
viewChanged(currentProgram.getMemory());
|
if (viewManager == null) {
|
||||||
|
setView(currentProgram.getMemory());
|
||||||
|
viewUpdated();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,9 +113,6 @@ public class CodeBrowserPlugin extends AbstractCodeBrowserPlugin<CodeViewerProvi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface method called to process a plugin event.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void processEvent(PluginEvent event) {
|
public void processEvent(PluginEvent event) {
|
||||||
if (event instanceof ProgramClosedPluginEvent) {
|
if (event instanceof ProgramClosedPluginEvent) {
|
||||||
|
@ -150,7 +147,8 @@ public class CodeBrowserPlugin extends AbstractCodeBrowserPlugin<CodeViewerProvi
|
||||||
ProgramLocation location = evt.getLocation();
|
ProgramLocation location = evt.getLocation();
|
||||||
if (!connectedProvider.setLocation(location)) {
|
if (!connectedProvider.setLocation(location)) {
|
||||||
if (viewManager != null) {
|
if (viewManager != null) {
|
||||||
connectedProvider.setView(viewManager.addToView(location));
|
AddressSetView updatedView = viewManager.addToView(location);
|
||||||
|
setView(updatedView);
|
||||||
ListingPanel lp = connectedProvider.getListingPanel();
|
ListingPanel lp = connectedProvider.getListingPanel();
|
||||||
lp.goTo(location, true);
|
lp.goTo(location, true);
|
||||||
}
|
}
|
||||||
|
@ -168,7 +166,7 @@ public class CodeBrowserPlugin extends AbstractCodeBrowserPlugin<CodeViewerProvi
|
||||||
}
|
}
|
||||||
else if (event instanceof ViewChangedPluginEvent) {
|
else if (event instanceof ViewChangedPluginEvent) {
|
||||||
AddressSet view = ((ViewChangedPluginEvent) event).getView();
|
AddressSet view = ((ViewChangedPluginEvent) event).getView();
|
||||||
viewChanged(view);
|
setView(view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +201,7 @@ public class CodeBrowserPlugin extends AbstractCodeBrowserPlugin<CodeViewerProvi
|
||||||
ProgramSelection highlight = (ProgramSelection) state[2];
|
ProgramSelection highlight = (ProgramSelection) state[2];
|
||||||
ProgramSelection selection = (ProgramSelection) state[3];
|
ProgramSelection selection = (ProgramSelection) state[3];
|
||||||
|
|
||||||
viewChanged((AddressSetView) state[4]);
|
setView((AddressSetView) state[4]);
|
||||||
|
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
connectedProvider.setLocation(location);
|
connectedProvider.setLocation(location);
|
||||||
|
|
|
@ -60,6 +60,7 @@ import ghidra.framework.plugintool.NavigatableComponentProviderAdapter;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
import ghidra.program.model.mem.Memory;
|
||||||
import ghidra.program.util.*;
|
import ghidra.program.util.*;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.Swing;
|
import ghidra.util.Swing;
|
||||||
|
@ -958,25 +959,26 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
||||||
return fieldNavigator;
|
return fieldNavigator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setView(AddressSetView view) {
|
void setView(AddressSetView view) {
|
||||||
|
|
||||||
// If we are using a MultiListingLayoutModel then adjust the view address set.
|
// If we are using a MultiListingLayoutModel then adjust the view address set.
|
||||||
AddressSetView adjustedView = view;
|
AddressSetView adjustedView = view;
|
||||||
|
|
||||||
if (multiModel != null) {
|
if (multiModel != null) {
|
||||||
if ((program != null) && view.contains(new AddressSet(program.getMemory()))) {
|
|
||||||
Program otherProgram = otherPanel.getProgram();
|
Program otherProgram = otherPanel.getProgram();
|
||||||
|
Memory memory = program.getMemory();
|
||||||
|
if (view.contains(memory)) {
|
||||||
adjustedView = ProgramMemoryComparator.getCombinedAddresses(program, otherProgram);
|
adjustedView = ProgramMemoryComparator.getCombinedAddresses(program, otherProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
multiModel.setAddressSet(adjustedView);
|
multiModel.setAddressSet(adjustedView);
|
||||||
|
|
||||||
|
// convert the view addresses to ones compatible with the otherPanel's model
|
||||||
|
AddressSet diffAddrs = DiffUtility.getCompatibleAddressSet(adjustedView, otherProgram);
|
||||||
|
otherPanel.setView(diffAddrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
listingPanel.setView(adjustedView);
|
listingPanel.setView(adjustedView);
|
||||||
if (otherPanel != null) {
|
|
||||||
// Convert the view addresses to ones compatible with the otherPanel's model.
|
|
||||||
AddressSet compatibleAddressSet =
|
|
||||||
DiffUtility.getCompatibleAddressSet(adjustedView, otherPanel.getProgram());
|
|
||||||
otherPanel.setView(compatibleAddressSet);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -330,9 +330,7 @@ public class ListingModelAdapter implements LayoutModel, ListingModelListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProgramSelection getAllProgramSelection() {
|
public ProgramSelection getAllProgramSelection() {
|
||||||
Program program = model.getProgram();
|
return new ProgramSelection(model.getAddressSet());
|
||||||
AddressFactory factory = program == null ? null : program.getAddressFactory();
|
|
||||||
return new ProgramSelection(factory, model.getAddressSet());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method works for structures inside unions, but doesn't handle data
|
// This method works for structures inside unions, but doesn't handle data
|
||||||
|
@ -346,7 +344,7 @@ public class ListingModelAdapter implements LayoutModel, ListingModelListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addrSet = model.adjustAddressSetToCodeUnitBoundaries(addrSet);
|
addrSet = model.adjustAddressSetToCodeUnitBoundaries(addrSet);
|
||||||
return new ProgramSelection(null, addrSet);
|
return new ProgramSelection(addrSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this methods does NOT work for structures inside of unions, but handles structures
|
// this methods does NOT work for structures inside of unions, but handles structures
|
||||||
|
@ -519,9 +517,14 @@ public class ListingModelAdapter implements LayoutModel, ListingModelListener {
|
||||||
* associated with this model.
|
* associated with this model.
|
||||||
*/
|
*/
|
||||||
public void setAddressSet(AddressSetView view) {
|
public void setAddressSet(AddressSetView view) {
|
||||||
|
view = ImmutableAddressSet.asImmutable(view);
|
||||||
addressToIndexMap = new AddressIndexMap(view);
|
addressToIndexMap = new AddressIndexMap(view);
|
||||||
removeUnviewableAddressRanges();
|
removeUnviewableAddressRanges();
|
||||||
modelSizeChanged();
|
modelSizeChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void viewUpdated() {
|
||||||
|
removeUnviewableAddressRanges();
|
||||||
|
modelSizeChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import java.awt.event.*;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
|
@ -875,9 +874,11 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
||||||
*/
|
*/
|
||||||
public void setView(AddressSetView view) {
|
public void setView(AddressSetView view) {
|
||||||
|
|
||||||
|
view = ImmutableAddressSet.asImmutable(view);
|
||||||
|
|
||||||
AddressIndexMap currentMap = layoutModel.getAddressIndexMap();
|
AddressIndexMap currentMap = layoutModel.getAddressIndexMap();
|
||||||
AddressSetView originalView = currentMap.getOriginalAddressSet();
|
AddressSetView originalView = currentMap.getOriginalAddressSet();
|
||||||
if (Objects.equals(originalView, view)) {
|
if (view.hasSameAddresses(originalView)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -370,7 +370,7 @@ public class MultiListingLayoutModel implements ListingModelListener, FormatMode
|
||||||
* primary program and listingModel
|
* primary program and listingModel
|
||||||
*/
|
*/
|
||||||
public void setAddressSet(AddressSetView view) {
|
public void setAddressSet(AddressSetView view) {
|
||||||
primaryAddrSet = view;
|
primaryAddrSet = ImmutableAddressSet.asImmutable(view);
|
||||||
modelSizeChanged();
|
modelSizeChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,8 @@ import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.database.ProgramBuilder;
|
import ghidra.program.database.ProgramBuilder;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressSet;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.RefType;
|
import ghidra.program.model.symbol.RefType;
|
||||||
|
@ -56,7 +57,6 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
|
||||||
|
|
||||||
private static final String NESTED_STRUCT_ADDR = "0x1007000";
|
private static final String NESTED_STRUCT_ADDR = "0x1007000";
|
||||||
|
|
||||||
private AddressFactory addrFactory;
|
|
||||||
private FieldPanel fp;
|
private FieldPanel fp;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -629,7 +629,7 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
|
||||||
|
|
||||||
// now make a real program selection and verify the text selection goes away
|
// now make a real program selection and verify the text selection goes away
|
||||||
ProgramSelection programSelection =
|
ProgramSelection programSelection =
|
||||||
new ProgramSelection(addrFactory, addr("0x1003600"), addr("0x10036f0"));
|
new ProgramSelection(addr("0x1003600"), addr("0x10036f0"));
|
||||||
tool.firePluginEvent(
|
tool.firePluginEvent(
|
||||||
new ProgramSelectionPluginEvent(testName.getMethodName(), programSelection, program));
|
new ProgramSelectionPluginEvent(testName.getMethodName(), programSelection, program));
|
||||||
|
|
||||||
|
@ -705,8 +705,7 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setView(final AddressSet addrSet) {
|
private void setView(final AddressSet addrSet) {
|
||||||
runSwing(() -> codeBrowser.viewChanged(addrSet), true);
|
runSwing(() -> codeBrowser.setView(addrSet), true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void adjustFieldPanelSize(int numRows) {
|
private void adjustFieldPanelSize(int numRows) {
|
||||||
|
|
|
@ -664,7 +664,7 @@ public class CodeBrowserTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setView(AddressSet addrSet) {
|
private void setView(AddressSet addrSet) {
|
||||||
runSwing(() -> cb.viewChanged(addrSet), true);
|
runSwing(() -> cb.setView(addrSet), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSelection(final AddressSet addrSet) {
|
private void setSelection(final AddressSet addrSet) {
|
||||||
|
|
|
@ -0,0 +1,226 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.program.model.address;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immutable implementation of the {@link AddressSetView} interface;
|
||||||
|
*/
|
||||||
|
public class ImmutableAddressSet implements AddressSetView {
|
||||||
|
|
||||||
|
public static final ImmutableAddressSet EMPTY_SET = new ImmutableAddressSet(new AddressSet());
|
||||||
|
|
||||||
|
public static ImmutableAddressSet asImmutable(AddressSetView view) {
|
||||||
|
if (view == null) {
|
||||||
|
return EMPTY_SET;
|
||||||
|
}
|
||||||
|
if (view instanceof ImmutableAddressSet ias) {
|
||||||
|
return ias;
|
||||||
|
}
|
||||||
|
return new ImmutableAddressSet(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AddressSet set;
|
||||||
|
|
||||||
|
public ImmutableAddressSet(AddressSetView addresses) {
|
||||||
|
set = new AddressSet(addresses);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Address addr) {
|
||||||
|
return set.contains(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Address start, Address end) {
|
||||||
|
return set.contains(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(AddressSetView rangeSet) {
|
||||||
|
return set.contains(rangeSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return set.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Address getMinAddress() {
|
||||||
|
return set.getMinAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Address getMaxAddress() {
|
||||||
|
return set.getMaxAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumAddressRanges() {
|
||||||
|
return set.getNumAddressRanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressRangeIterator getAddressRanges() {
|
||||||
|
return set.getAddressRanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressRangeIterator getAddressRanges(boolean forward) {
|
||||||
|
return set.getAddressRanges(forward);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressRangeIterator getAddressRanges(Address start, boolean forward) {
|
||||||
|
return set.getAddressRanges(start, forward);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<AddressRange> iterator() {
|
||||||
|
return set.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<AddressRange> iterator(boolean forward) {
|
||||||
|
return set.iterator(forward);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<AddressRange> iterator(Address start, boolean forward) {
|
||||||
|
return set.iterator(start, forward);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getNumAddresses() {
|
||||||
|
return set.getNumAddresses();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressIterator getAddresses(boolean forward) {
|
||||||
|
return set.getAddresses(forward);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressIterator getAddresses(Address start, boolean forward) {
|
||||||
|
return set.getAddresses(start, forward);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean intersects(AddressSetView addrSet) {
|
||||||
|
return set.intersects(addrSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean intersects(Address start, Address end) {
|
||||||
|
return set.intersects(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressSet intersect(AddressSetView view) {
|
||||||
|
return set.intersect(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressSet intersectRange(Address start, Address end) {
|
||||||
|
return set.intersectRange(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressSet union(AddressSetView addrSet) {
|
||||||
|
return set.union(addrSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressSet subtract(AddressSetView addrSet) {
|
||||||
|
return set.subtract(addrSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressSet xor(AddressSetView addrSet) {
|
||||||
|
return set.xor(addrSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSameAddresses(AddressSetView view) {
|
||||||
|
return set.hasSameAddresses(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressRange getFirstRange() {
|
||||||
|
return set.getFirstRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressRange getLastRange() {
|
||||||
|
return set.getLastRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressRange getRangeContaining(Address address) {
|
||||||
|
return set.getRangeContaining(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Address findFirstAddressInCommon(AddressSetView addresses) {
|
||||||
|
return set.findFirstAddressInCommon(addresses);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean equals(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(obj instanceof ImmutableAddressSet)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableAddressSet otherSet = (ImmutableAddressSet) obj;
|
||||||
|
if (this.getNumAddresses() != otherSet.getNumAddresses()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if don't have same number of ranges, not equal
|
||||||
|
if (this.getNumAddressRanges() != otherSet.getNumAddressRanges()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressRangeIterator otherRanges = otherSet.getAddressRanges();
|
||||||
|
AddressRangeIterator myRanges = getAddressRanges();
|
||||||
|
while (myRanges.hasNext()) {
|
||||||
|
AddressRange myRange = myRanges.next();
|
||||||
|
AddressRange otherRange = otherRanges.next();
|
||||||
|
if (!myRange.equals(otherRange)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
if (isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return getMinAddress().hashCode() + getMaxAddress().hashCode();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue