mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-22 23:29:07 +08:00
GP-3564 Add composite get component by name and removed
DuplicateNameException when renaming components. Added GUI editor warning when duplicate naming is used.
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -15,13 +15,14 @@
|
||||
*/
|
||||
package ghidra.app.cmd.data;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import ghidra.framework.cmd.Command;
|
||||
import ghidra.program.model.data.DataTypeComponent;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* Command to rename a component in a data type.
|
||||
* Command to rename a component in a {@link Composite} data type.
|
||||
*
|
||||
*/
|
||||
public class RenameDataFieldCmd implements Command<Program> {
|
||||
@@ -47,20 +48,20 @@ public class RenameDataFieldCmd implements Command<Program> {
|
||||
statusMsg = "Null data type";
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
comp.setFieldName(newName);
|
||||
return true;
|
||||
|
||||
String name = InternalDataTypeComponent.cleanupFieldName(newName);
|
||||
|
||||
if (!Objects.equals(name, comp.getFieldName())) {
|
||||
comp = comp.setFieldName(newName);
|
||||
if (!Objects.equals(name, comp.getFieldName())) {
|
||||
statusMsg = "Unable to rename component";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
statusMsg = "Type name already exists: " + newName;
|
||||
}
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
||||
*/
|
||||
@Override
|
||||
public String getStatusMsg() {
|
||||
return statusMsg;
|
||||
|
||||
+21
-25
@@ -802,13 +802,9 @@ public abstract class CompEditorModel<T extends Composite> extends CompositeEdit
|
||||
DataTypeComponent dtc = getComponent(startRowIndex);
|
||||
|
||||
// Set the field name and comment the same as before
|
||||
try {
|
||||
dtc.setFieldName(oldDtc.getFieldName());
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Msg.showError(this, null, "Unexcected Exception", "Exception applying field name", e);
|
||||
}
|
||||
dtc.setFieldName(oldDtc.getFieldName());
|
||||
dtc.setComment(oldDtc.getComment());
|
||||
|
||||
fixSelection();
|
||||
selectionChanged();
|
||||
return dtc;
|
||||
@@ -1165,32 +1161,32 @@ public abstract class CompEditorModel<T extends Composite> extends CompositeEdit
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateComponentName(int rowIndex, String name) throws UsrException {
|
||||
if (nameExistsElsewhere(name, rowIndex)) {
|
||||
throw new InvalidNameException("Name \"" + name + "\" already exists.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComponentName(int rowIndex, String name) throws InvalidNameException {
|
||||
|
||||
String oldName = getComponent(rowIndex).getFieldName();
|
||||
if (Objects.equals(oldName, name)) {
|
||||
name = InternalDataTypeComponent.cleanupFieldName(name); // will trim name if needed
|
||||
DataTypeComponent component = getComponent(rowIndex);
|
||||
if (Objects.equals(name, component.getDefaultFieldName())) {
|
||||
name = null;
|
||||
}
|
||||
if (Objects.equals(name, component.getFieldName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nameExistsElsewhere(name, rowIndex)) {
|
||||
throw new InvalidNameException("Name \"" + name + "\" already exists.");
|
||||
if (viewComposite.findComponent(name) != null) {
|
||||
// Warn user and confirm rename when duplicate name is used
|
||||
if (OptionDialog.OPTION_ONE != OptionDialog.showOptionDialog(null,
|
||||
"Duplicate Field Name",
|
||||
"Duplicate field name. Proceed with rename?",
|
||||
"Rename!", OptionDialog.WARNING_MESSAGE)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return viewDTM.withTransaction("Set Component Name", () -> {
|
||||
try {
|
||||
getComponent(rowIndex).setFieldName(name); // setFieldName handles trimming
|
||||
return true;
|
||||
}
|
||||
catch (DuplicateNameException exc) {
|
||||
throw new InvalidNameException(exc.getMessage());
|
||||
}
|
||||
|
||||
String newName = name;
|
||||
return viewDTM.withTransaction("Set Field Name", () -> {
|
||||
getComponent(rowIndex).setFieldName(newName);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
-30
@@ -1097,36 +1097,6 @@ abstract public class CompositeEditorModel<T extends Composite> extends Composit
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for any data member in the composite with the specified name
|
||||
* other than the component at the specified index.
|
||||
*
|
||||
* @param name the component name to look for.
|
||||
* @param rowIndex index of the row (component).
|
||||
*
|
||||
* @return true if the name exists elsewhere.
|
||||
*/
|
||||
protected boolean nameExistsElsewhere(String name, int rowIndex) {
|
||||
if (name != null) {
|
||||
name = name.trim();
|
||||
if (name.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
int numComponents = getNumComponents();
|
||||
for (int i = 0; i < rowIndex && i < numComponents; i++) {
|
||||
if (name.equals(getComponent(i).getFieldName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int i = rowIndex + 1; i < numComponents; i++) {
|
||||
if (name.equals(getComponent(i).getFieldName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the data type is a valid one to place into the current structure being edited.
|
||||
* If invalid, an exception will be thrown.
|
||||
|
||||
+2
-2
@@ -1145,8 +1145,8 @@ public abstract class CompositeEditorPanel<T extends Composite, M extends Compos
|
||||
@Override
|
||||
public boolean stopCellEditing() {
|
||||
try {
|
||||
model.validateComponentName(table.getEditingRow(),
|
||||
((JTextComponent) getComponent()).getText());
|
||||
String newName = ((JTextComponent) getComponent()).getText();
|
||||
model.validateComponentName(table.getEditingRow(), newName);
|
||||
fireEditingStopped();
|
||||
return true;
|
||||
}
|
||||
|
||||
+3
-13
@@ -1009,12 +1009,7 @@ class StructureEditorModel extends CompEditorModel<Structure> {
|
||||
|
||||
DataTypeComponent comp = getComponent(startRowIndex);
|
||||
// Set the field name and comment the same as before
|
||||
try {
|
||||
comp.setFieldName(fieldName);
|
||||
}
|
||||
catch (DuplicateNameException exc) {
|
||||
Msg.showError(this, null, null, null);
|
||||
}
|
||||
comp.setFieldName(fieldName);
|
||||
comp.setComment(comment);
|
||||
|
||||
// Create any needed undefined data types.
|
||||
@@ -1377,13 +1372,8 @@ class StructureEditorModel extends CompEditorModel<Structure> {
|
||||
|
||||
DataTypeComponent comp = getComponent(rowIndex);
|
||||
// Set the field name and comment the same as before if unspecified
|
||||
try {
|
||||
if (comp.getFieldName() == null) {
|
||||
comp.setFieldName(fieldName);
|
||||
}
|
||||
}
|
||||
catch (DuplicateNameException exc) {
|
||||
Msg.showError(this, null, null, null);
|
||||
if (comp.getFieldName() == null) {
|
||||
comp.setFieldName(fieldName);
|
||||
}
|
||||
if (StringUtils.isBlank(comp.getComment())) {
|
||||
comp.setComment(comment);
|
||||
|
||||
+23
-10
@@ -19,12 +19,14 @@ import java.awt.BorderLayout;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import docking.DialogComponentProvider;
|
||||
import docking.widgets.OptionDialog;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.app.util.datatype.DataTypeSelectionEditor;
|
||||
import ghidra.framework.cmd.Command;
|
||||
@@ -439,9 +441,8 @@ public class EditDataFieldDialog extends DialogComponentProvider {
|
||||
// replace that default type with a type that will force a record to be get created.
|
||||
// We need a record to exist in order to set a comment or name.
|
||||
DataType newtype = new Undefined1DataType();
|
||||
DataTypeComponent newDtc =
|
||||
struct.replaceAtOffset(dtc.getOffset(), newtype, 1, "tempName",
|
||||
"Created by Edit Data Field action");
|
||||
DataTypeComponent newDtc = struct.replaceAtOffset(dtc.getOffset(), newtype, 1,
|
||||
"tempName", "Created by Edit Data Field action");
|
||||
|
||||
DataType oldDt = dtc.getDataType();
|
||||
DataType editorDt = dataTypeEditor.getCellEditorValueAsDataType();
|
||||
@@ -459,15 +460,28 @@ public class EditDataFieldDialog extends DialogComponentProvider {
|
||||
return true;
|
||||
}
|
||||
|
||||
String newName = InternalDataTypeComponent.cleanupFieldName(getNewFieldName());
|
||||
DataTypeComponent dtc = composite.getComponent(ordinal);
|
||||
try {
|
||||
dtc.setFieldName(getNewFieldName());
|
||||
if (Objects.equals(newName, dtc.getDefaultFieldName())) {
|
||||
newName = null;
|
||||
}
|
||||
if (Objects.equals(newName, dtc.getFieldName())) {
|
||||
return true;
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
statusMessage = "Duplicate field name";
|
||||
return false;
|
||||
|
||||
if (newName != null && composite.findComponent(newName) != null) {
|
||||
|
||||
// Warn user and confirm rename when duplicate name is used
|
||||
if (OptionDialog.OPTION_ONE != OptionDialog.showOptionDialog(getComponent(),
|
||||
"Duplicate Field Name",
|
||||
"Duplicate field name. Proceed with rename?",
|
||||
"Rename!", OptionDialog.WARNING_MESSAGE)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dtc.setFieldName(newName);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean updateComment() {
|
||||
@@ -512,8 +526,7 @@ public class EditDataFieldDialog extends DialogComponentProvider {
|
||||
return;
|
||||
}
|
||||
|
||||
DataTypeInstance dti =
|
||||
DataTypeInstance.getDataTypeInstance(resolvedDt, -1, false);
|
||||
DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(resolvedDt, -1, false);
|
||||
DataType dataType = dti.getDataType();
|
||||
int length = dti.getLength();
|
||||
String fieldName = dtc.getFieldName();
|
||||
|
||||
+1
-5
@@ -40,7 +40,6 @@ import ghidra.program.database.DatabaseObject;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.program.model.symbol.SymbolUtilities;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
@@ -707,10 +706,7 @@ public class StackEditorModel extends CompositeEditorModel<StackFrameDataType> {
|
||||
|
||||
@Override
|
||||
public void validateComponentName(int currentIndex, String name) throws UsrException {
|
||||
if (SymbolUtilities.containsInvalidChars(name)) {
|
||||
throw new InvalidInputException(
|
||||
"Symbol name \"" + name + "\"contains invalid characters.");
|
||||
}
|
||||
viewComposite.checkNameChange(currentIndex, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+70
-18
@@ -31,9 +31,11 @@ import ghidra.program.model.lang.ProgramArchitecture;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
import ghidra.program.model.symbol.SymbolTable;
|
||||
import ghidra.program.model.symbol.SymbolUtilities;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
|
||||
/**
|
||||
* {@link StackFrameDataType} provides a {@link Structure} representation of a {@link StackFrame}
|
||||
@@ -419,19 +421,15 @@ class StackFrameDataType implements Structure {
|
||||
* @param name the new name. Null indicates the default name.
|
||||
* @return true if name change was successful, else false
|
||||
* @throws IndexOutOfBoundsException if specified ordinal is out of range
|
||||
* @throws IllegalArgumentException if name is invalid
|
||||
* @throws InvalidNameException if an invalid or duplicate name is specified
|
||||
*/
|
||||
public boolean setName(int ordinal, String name) throws IndexOutOfBoundsException {
|
||||
public boolean setName(int ordinal, String name)
|
||||
throws IndexOutOfBoundsException, InvalidNameException {
|
||||
|
||||
StackComponentWrapper comp = getComponent(ordinal);
|
||||
String fieldName = comp.getFieldName();
|
||||
|
||||
if (name != null) {
|
||||
name = name.trim();
|
||||
if (name.length() == 0 || isDefaultName(name)) {
|
||||
name = null;
|
||||
}
|
||||
}
|
||||
name = checkNameChange(ordinal, name);
|
||||
|
||||
if (SystemUtilities.isEqual(name, fieldName)) {
|
||||
return false;
|
||||
@@ -445,17 +443,53 @@ class StackFrameDataType implements Structure {
|
||||
comp = replace(comp.getOrdinal(), DataType.DEFAULT, 1, name, null);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
comp.dtc.setFieldName(name);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
// FIXME: Inconsistent API / how should names be validated and on which methods?
|
||||
return false;
|
||||
}
|
||||
comp.dtc.setFieldName(name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preliminary check if a component may be renamed to the specified name.
|
||||
*
|
||||
* @param ordinal the ordinal
|
||||
* @param name the new name. Null indicates the default name.
|
||||
* @return name which will actually be applied after cleaning
|
||||
* @throws IndexOutOfBoundsException if specified ordinal is out of range
|
||||
* @throws InvalidNameException if an invalid or duplicate name is specified
|
||||
*/
|
||||
public String checkNameChange(int ordinal, String name) throws InvalidNameException {
|
||||
if (name != null) {
|
||||
name = name.trim();
|
||||
if (name.length() == 0 || isDefaultName(name)) {
|
||||
name = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
try {
|
||||
SymbolUtilities.validateName(name);
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
throw new InvalidNameException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
StackComponentWrapper comp = getComponent(ordinal);
|
||||
String oldFieldName = comp.getFieldName();
|
||||
if (SystemUtilities.isEqual(name, oldFieldName)) {
|
||||
return oldFieldName;
|
||||
}
|
||||
|
||||
SymbolTable symbolTable = function.getProgram().getSymbolTable();
|
||||
if (name != null && (wrappedStruct.findComponent(name) != null ||
|
||||
!symbolTable.getSymbols(name, function).isEmpty())) {
|
||||
// Stack or symbol table storage has a conflicting variable or symbol with the same name
|
||||
throw new InvalidNameException("Name conflicts with another variable: " + name);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the comment at the specified ordinal.
|
||||
*
|
||||
@@ -834,7 +868,7 @@ class StackFrameDataType implements Structure {
|
||||
* Unsupported method. Must use {@link StackFrameDataType#setComment(int, String)}.
|
||||
*/
|
||||
@Override
|
||||
public void setComment(String comment) {
|
||||
public DataTypeComponent setComment(String comment) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@@ -920,7 +954,7 @@ class StackFrameDataType implements Structure {
|
||||
* Unsupported method. Must use {@link StackFrameDataType#setName(int, String)}.
|
||||
*/
|
||||
@Override
|
||||
public void setFieldName(String fieldName) throws DuplicateNameException {
|
||||
public DataTypeComponent setFieldName(String fieldName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@@ -1070,6 +1104,11 @@ class StackFrameDataType implements Structure {
|
||||
return new StackComponentWrapper(dtc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent findComponent(String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearComponent(int ordinal) throws IndexOutOfBoundsException {
|
||||
wrappedStruct.clearComponent(ordinal);
|
||||
@@ -1193,6 +1232,19 @@ class StackFrameDataType implements Structure {
|
||||
name = null;
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
try {
|
||||
SymbolUtilities.validateName(name);
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
throw new IllegalArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: We don't check for duplicate name since this method is intended for stack
|
||||
// frame internal use only where any required conflict check should already have been
|
||||
// performed
|
||||
|
||||
DataTypeComponent dtc = wrappedStruct.replace(ordinal, dataType, length, name, comment);
|
||||
|
||||
checkForStackGrowth();
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -17,18 +17,18 @@ package ghidra.app.util;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import docking.DialogComponentProvider;
|
||||
import docking.widgets.OptionDialog;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeComponent;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class EditFieldNameDialog extends DialogComponentProvider {
|
||||
|
||||
@@ -77,36 +77,39 @@ public class EditFieldNameDialog extends DialogComponentProvider {
|
||||
@Override
|
||||
protected void okCallback() {
|
||||
|
||||
String newName = fieldName.getText().trim();
|
||||
|
||||
if (newName.equals(getCurrentFieldName())) {
|
||||
String newName = InternalDataTypeComponent.cleanupFieldName(fieldName.getText());
|
||||
if (Objects.equals(newName, dtComp.getDefaultFieldName())) {
|
||||
newName = null;
|
||||
}
|
||||
if (Objects.equals(newName, dtComp.getFieldName())) {
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
boolean success = false;
|
||||
DataType parent = dtComp.getParent();
|
||||
if (newName != null && parent instanceof Composite composite &&
|
||||
composite.findComponent(newName) != null) {
|
||||
|
||||
// Warn user and confirm rename when duplicate name is used
|
||||
if (OptionDialog.OPTION_ONE != OptionDialog.showOptionDialog(getComponent(),
|
||||
"Duplicate Field Name",
|
||||
"Duplicate field name. Proceed with rename?",
|
||||
"Rename!", OptionDialog.WARNING_MESSAGE)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int txId = program.startTransaction("Edit Field Name");
|
||||
try {
|
||||
dtComp.setFieldName(newName);
|
||||
DataType parent = dtComp.getParent();
|
||||
if (parent != null) {
|
||||
long timeNow = System.currentTimeMillis();
|
||||
parent.setLastChangeTime(timeNow);
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
setStatusText(e.getMessage());
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
dtComp = null;
|
||||
program = null;
|
||||
close();
|
||||
}
|
||||
dtComp = null;
|
||||
program = null;
|
||||
close();
|
||||
}
|
||||
|
||||
public void editField(DataTypeComponent dataTypeComponent, Program p) {
|
||||
|
||||
+3
-5
@@ -23,7 +23,6 @@ import ghidra.docking.settings.SettingsImpl;
|
||||
import ghidra.pcode.emu.PcodeThread;
|
||||
import ghidra.pcode.exec.PcodeArithmetic.Purpose;
|
||||
import ghidra.pcode.exec.PcodeExecutorState;
|
||||
import ghidra.pcode.memstate.MemoryState;
|
||||
import ghidra.pcode.utils.Utils;
|
||||
import ghidra.program.disassemble.Disassembler;
|
||||
import ghidra.program.model.address.*;
|
||||
@@ -296,10 +295,9 @@ public abstract class PCodeTestAbstractControlBlock {
|
||||
}
|
||||
|
||||
protected int getStructureComponent(Structure testInfoStruct, String fieldName) {
|
||||
for (DataTypeComponent component : testInfoStruct.getDefinedComponents()) {
|
||||
if (fieldName.equals(component.getFieldName())) {
|
||||
return component.getOffset();
|
||||
}
|
||||
DataTypeComponent component = testInfoStruct.findComponent(fieldName);
|
||||
if (component != null) {
|
||||
return component.getOffset();
|
||||
}
|
||||
throw new RuntimeException(fieldName + " field not found within " +
|
||||
testInfoStruct.getName() + " structure definition at " + infoStructAddr.toString(true));
|
||||
|
||||
+5
-15
@@ -932,13 +932,8 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
(Structure) dtm.getDataType(new CategoryPath("/Category1/Category2/Category3"),
|
||||
"IntStruct");
|
||||
|
||||
try {
|
||||
DataTypeComponent dtc = s.getComponent(0);
|
||||
dtc.setFieldName("Field One");
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Assert.fail("Got duplicate name exception!");
|
||||
}
|
||||
DataTypeComponent dtc = s.getComponent(0);
|
||||
dtc.setFieldName("Field One");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -950,14 +945,9 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
(Structure) dtm.getDataType(new CategoryPath("/Category1/Category2/Category3"),
|
||||
"IntStruct");
|
||||
|
||||
try {
|
||||
DataTypeComponent dtc = s.getComponent(2);
|
||||
dtc.setFieldName("My Field Three");
|
||||
dtc.setComment("my comments for Field 3");
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Assert.fail("Got duplicate name exception!");
|
||||
}
|
||||
DataTypeComponent dtc = s.getComponent(2);
|
||||
dtc.setFieldName("My Field Three");
|
||||
dtc.setComment("my comments for Field 3");
|
||||
}
|
||||
});
|
||||
executeMerge(DataTypeMergeManager.OPTION_MY);
|
||||
|
||||
+122
-195
@@ -23,7 +23,6 @@ import org.junit.Test;
|
||||
import ghidra.program.database.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.data.Enum;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* More data type merge tests.
|
||||
@@ -122,17 +121,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||
DataType dt =
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
|
||||
try {
|
||||
Union union = (Union) dt;
|
||||
DataTypeComponent dtc = union.add(new FloatDataType());
|
||||
dtc.setComment("my comments");
|
||||
dtc.setFieldName("Float Field");
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Assert.fail("Got Duplicate name exception!");
|
||||
}
|
||||
Union union = (Union) dt;
|
||||
union.add(new FloatDataType(), "Float Field", "my comments");
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
}
|
||||
});
|
||||
executeMerge();
|
||||
@@ -190,17 +182,11 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||
DataType dt =
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
|
||||
try {
|
||||
Union union = (Union) dt;
|
||||
DataTypeComponent dtc = union.add(new FloatDataType());
|
||||
dtc.setComment("my comments");
|
||||
dtc.setFieldName("Float Field");
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Assert.fail("Got Duplicate name exception!");
|
||||
}
|
||||
Union union = (Union) dt;
|
||||
union.add(new FloatDataType(), "Float Field", "my comments");
|
||||
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
}
|
||||
});
|
||||
executeMerge();
|
||||
@@ -1209,26 +1195,18 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||
DataType dt =
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
|
||||
try {
|
||||
Union union = (Union) dt;
|
||||
DataTypeComponent dtc = union.add(new FloatDataType());
|
||||
dtc.setComment("my comments");
|
||||
dtc.setFieldName("Float Field");
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
TypeDef td =
|
||||
new TypedefDataType(new CategoryPath("/Category1"), "TD_DLL_Table", s);
|
||||
Pointer p = PointerDataType.getPointer(td, 4);
|
||||
union =
|
||||
new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(p);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Assert.fail("Got Duplicate name exception!");
|
||||
}
|
||||
Union union = (Union) dt;
|
||||
union.add(new FloatDataType(), "Float Field", "my comments");
|
||||
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
TypeDef td = new TypedefDataType(new CategoryPath("/Category1"), "TD_DLL_Table", s);
|
||||
Pointer p = PointerDataType.getPointer(td, 4);
|
||||
union = new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(p);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
});
|
||||
executeMerge();
|
||||
@@ -1287,23 +1265,16 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||
DataType dt =
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
|
||||
try {
|
||||
Union union = (Union) dt;
|
||||
DataTypeComponent dtc = union.add(new FloatDataType());
|
||||
dtc.setComment("my comments");
|
||||
dtc.setFieldName("Float Field");
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
Union union = (Union) dt;
|
||||
union.add(new FloatDataType(), "Float Field", "my comments");
|
||||
|
||||
union =
|
||||
new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Assert.fail("Got Duplicate name exception!");
|
||||
}
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
|
||||
union = new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
});
|
||||
executeMerge();
|
||||
@@ -1375,28 +1346,20 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||
Union union =
|
||||
(Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
|
||||
try {
|
||||
DataTypeComponent dtc = union.add(new FloatDataType());
|
||||
dtc.setComment("my comments");
|
||||
dtc.setFieldName("Float Field");
|
||||
Enum enumm = new EnumDataType(new CategoryPath("/Category1"), "MyEnum", 1);
|
||||
enumm.add("one", 1);
|
||||
enumm.add("two", 2);
|
||||
enumm.add("three", 3);
|
||||
union.add(enumm);
|
||||
union.add(new FloatDataType(), "Float Field", "my comments");
|
||||
Enum enumm = new EnumDataType(new CategoryPath("/Category1"), "MyEnum", 1);
|
||||
enumm.add("one", 1);
|
||||
enumm.add("two", 2);
|
||||
enumm.add("three", 3);
|
||||
union.add(enumm);
|
||||
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
|
||||
union =
|
||||
new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Assert.fail("Got Duplicate name exception!");
|
||||
}
|
||||
union = new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
});
|
||||
executeMerge();
|
||||
@@ -1447,28 +1410,21 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||
Union union =
|
||||
(Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
|
||||
try {
|
||||
DataTypeComponent dtc = union.add(new FloatDataType());
|
||||
dtc.setComment("my comments");
|
||||
dtc.setFieldName("Float Field");
|
||||
Enum enumm = new EnumDataType(new CategoryPath("/Category1"), "MyEnum", 1);
|
||||
enumm.add("one", 1);
|
||||
enumm.add("two", 2);
|
||||
enumm.add("three", 3);
|
||||
union.add(enumm);
|
||||
union.add(new FloatDataType(), "Float Field", "my comments");
|
||||
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
Enum enumm = new EnumDataType(new CategoryPath("/Category1"), "MyEnum", 1);
|
||||
enumm.add("one", 1);
|
||||
enumm.add("two", 2);
|
||||
enumm.add("three", 3);
|
||||
union.add(enumm);
|
||||
|
||||
union =
|
||||
new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Assert.fail("Got Duplicate name exception!");
|
||||
}
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
|
||||
union = new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
});
|
||||
executeMerge();
|
||||
@@ -1529,28 +1485,21 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||
Union union =
|
||||
(Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
|
||||
try {
|
||||
DataTypeComponent dtc = union.add(new FloatDataType());
|
||||
dtc.setComment("my comments");
|
||||
dtc.setFieldName("Float Field");
|
||||
Enum enumm = new EnumDataType(new CategoryPath("/Category1"), "MyEnum", 1);
|
||||
enumm.add("one", 1);
|
||||
enumm.add("two", 2);
|
||||
enumm.add("three", 3);
|
||||
union.add(enumm);
|
||||
union.add(new FloatDataType(), "Float Field", "my comments");
|
||||
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
Enum enumm = new EnumDataType(new CategoryPath("/Category1"), "MyEnum", 1);
|
||||
enumm.add("one", 1);
|
||||
enumm.add("two", 2);
|
||||
enumm.add("three", 3);
|
||||
union.add(enumm);
|
||||
|
||||
union =
|
||||
new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Assert.fail("Got Duplicate name exception!");
|
||||
}
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
|
||||
union = new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
});
|
||||
executeMerge();
|
||||
@@ -1601,30 +1550,23 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||
Union union =
|
||||
(Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
|
||||
try {
|
||||
DataTypeComponent dtc = union.add(new FloatDataType());
|
||||
dtc.setComment("my comments");
|
||||
dtc.setFieldName("Float Field");
|
||||
Enum enumm = new EnumDataType(new CategoryPath("/Category1"), "MyEnum", 1);
|
||||
enumm.add("one", 1);
|
||||
enumm.add("two", 2);
|
||||
enumm.add("three", 3);
|
||||
TypeDef td =
|
||||
new TypedefDataType(new CategoryPath("/Category1"), "TD_MyEnum", enumm);
|
||||
union.add(td);
|
||||
union.add(new FloatDataType(), "Float Field", "my comments");
|
||||
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
Enum enumm = new EnumDataType(new CategoryPath("/Category1"), "MyEnum", 1);
|
||||
enumm.add("one", 1);
|
||||
enumm.add("two", 2);
|
||||
enumm.add("three", 3);
|
||||
TypeDef td =
|
||||
new TypedefDataType(new CategoryPath("/Category1"), "TD_MyEnum", enumm);
|
||||
union.add(td);
|
||||
|
||||
union =
|
||||
new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Assert.fail("Got Duplicate name exception!");
|
||||
}
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
|
||||
union = new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
});
|
||||
executeMerge();
|
||||
@@ -1704,33 +1646,26 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||
Union union =
|
||||
(Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
|
||||
try {
|
||||
DataTypeComponent dtc = union.add(new FloatDataType());
|
||||
dtc.setComment("my comments");
|
||||
dtc.setFieldName("Float Field");
|
||||
Enum enumm = new EnumDataType(new CategoryPath("/Category1"), "MyEnum", 1);
|
||||
enumm.add("one", 1);
|
||||
enumm.add("two", 2);
|
||||
enumm.add("three", 3);
|
||||
TypeDef td =
|
||||
new TypedefDataType(new CategoryPath("/Category1"), "TD_MyEnum", enumm);
|
||||
Pointer p = PointerDataType.getPointer(td, 4);// TD_MyEnum *
|
||||
p = PointerDataType.getPointer(p, 4);// TD_MyEnum * *
|
||||
p = PointerDataType.getPointer(p, 4);// TD_MyEnum * * *
|
||||
union.add(p);
|
||||
union.add(new FloatDataType(), "Float Field", "my comments");
|
||||
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
Enum enumm = new EnumDataType(new CategoryPath("/Category1"), "MyEnum", 1);
|
||||
enumm.add("one", 1);
|
||||
enumm.add("two", 2);
|
||||
enumm.add("three", 3);
|
||||
TypeDef td =
|
||||
new TypedefDataType(new CategoryPath("/Category1"), "TD_MyEnum", enumm);
|
||||
Pointer p = PointerDataType.getPointer(td, 4);// TD_MyEnum *
|
||||
p = PointerDataType.getPointer(p, 4);// TD_MyEnum * *
|
||||
p = PointerDataType.getPointer(p, 4);// TD_MyEnum * * *
|
||||
union.add(p);
|
||||
|
||||
union =
|
||||
new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Assert.fail("Got Duplicate name exception!");
|
||||
}
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
|
||||
union = new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
});
|
||||
executeMerge();
|
||||
@@ -1790,37 +1725,29 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||
Union union =
|
||||
(Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
|
||||
try {
|
||||
DataTypeComponent dtc = union.add(new FloatDataType());
|
||||
dtc.setComment("my comments");
|
||||
dtc.setFieldName("Float Field");
|
||||
Enum enumm = new EnumDataType(new CategoryPath("/Category1"), "MyEnum", 1);
|
||||
enumm.add("one", 1);
|
||||
enumm.add("two", 2);
|
||||
enumm.add("three", 3);
|
||||
TypeDef td =
|
||||
new TypedefDataType(new CategoryPath("/Category1"), "TD_MyEnum", enumm);
|
||||
Pointer p = PointerDataType.getPointer(td, 4);// TD_MyEnum *
|
||||
p = PointerDataType.getPointer(p, 4);// TD_MyEnum * *
|
||||
p = PointerDataType.getPointer(p, 4);// TD_MyEnum * * *
|
||||
union.add(new FloatDataType(), "Float Field", "my comments");
|
||||
|
||||
// create an array of TD_MyEnum * * *
|
||||
Array array = new ArrayDataType(p, 5, p.getLength());
|
||||
dtc = union.add(array);
|
||||
dtc.setComment("an array");
|
||||
dtc.setFieldName("array field name");
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
Enum enumm = new EnumDataType(new CategoryPath("/Category1"), "MyEnum", 1);
|
||||
enumm.add("one", 1);
|
||||
enumm.add("two", 2);
|
||||
enumm.add("three", 3);
|
||||
TypeDef td =
|
||||
new TypedefDataType(new CategoryPath("/Category1"), "TD_MyEnum", enumm);
|
||||
Pointer p = PointerDataType.getPointer(td, 4);// TD_MyEnum *
|
||||
p = PointerDataType.getPointer(p, 4);// TD_MyEnum * *
|
||||
p = PointerDataType.getPointer(p, 4);// TD_MyEnum * * *
|
||||
|
||||
union =
|
||||
new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Assert.fail("Got Duplicate name exception!");
|
||||
}
|
||||
// create an array of TD_MyEnum * * *
|
||||
Array array = new ArrayDataType(p, 5, p.getLength());
|
||||
union.add(array, "array field name", "an array");
|
||||
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
s.add(new WordDataType());
|
||||
|
||||
union = new UnionDataType(new CategoryPath("/Category1/Category2"), "AnotherUnion");
|
||||
union.add(s);
|
||||
union.add(new ByteDataType());
|
||||
dtm.addDataType(union, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
});
|
||||
executeMerge();
|
||||
|
||||
+255
-342
File diff suppressed because it is too large
Load Diff
-5
@@ -550,11 +550,6 @@ public class StackEditorCellEditTest extends AbstractStackEditorTest {
|
||||
triggerActionInCellEditor(KeyEvent.VK_UP);
|
||||
waitForSwing();
|
||||
rowNum--;
|
||||
// DataTypeComponent dtc = model.getComponent(rowNum);
|
||||
// if (dtc.getOffset() < ((StackEditorModel) model).getParameterOffset()) {
|
||||
// assertNotEditingField();
|
||||
// break;
|
||||
// }
|
||||
assertIsEditingField(rowNum, colNum);
|
||||
}
|
||||
while (rowNum > 0) {
|
||||
|
||||
+7
-17
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -47,7 +47,9 @@ public class HTMLDataTypeRepresentationTest extends AbstractGenericTest {
|
||||
DataType dataTypeCopy = composite.copy(null);
|
||||
Composite compositeCopy = (Composite) dataTypeCopy;
|
||||
int fieldIndex = 0;
|
||||
setName(compositeCopy, fieldIndex);
|
||||
|
||||
DataTypeComponent component = compositeCopy.getComponent(fieldIndex);
|
||||
component.setFieldName("newName");
|
||||
|
||||
HTMLDataTypeRepresentation representation = ToolTipUtils.getHTMLRepresentation(composite);
|
||||
HTMLDataTypeRepresentation otherRepresentation =
|
||||
@@ -789,8 +791,8 @@ public class HTMLDataTypeRepresentationTest extends AbstractGenericTest {
|
||||
assertEquals("ccc ddd", l3a.get(1));
|
||||
|
||||
//[a bbbbbbbb, bbbbbbbbbb, bbbbbbbbbb, bbbbbb c]
|
||||
List<String> l4 = HTMLDataTypeRepresentation.breakLongLineAtWordBoundaries(
|
||||
"a bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb c", 10);
|
||||
List<String> l4 = HTMLDataTypeRepresentation
|
||||
.breakLongLineAtWordBoundaries("a bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb c", 10);
|
||||
assertEquals(4, l4.size());
|
||||
assertEquals("a bbbbbbbb", l4.get(0));
|
||||
assertEquals("bbbbbbbbbb", l4.get(1));
|
||||
@@ -1219,18 +1221,6 @@ public class HTMLDataTypeRepresentationTest extends AbstractGenericTest {
|
||||
}
|
||||
}
|
||||
|
||||
private void setName(Composite c, int fieldIndex) {
|
||||
DataTypeComponent component = c.getComponent(fieldIndex);
|
||||
try {
|
||||
component.setFieldName("newName");
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
// shouldn't happen
|
||||
e.printStackTrace();
|
||||
Assert.fail("Unexpected duplicate name");
|
||||
}
|
||||
}
|
||||
|
||||
private void assertCompositeHeaderEquals(HTMLDataTypeRepresentation[] diffedRepresentations) {
|
||||
List<ValidatableLine> headerLines =
|
||||
((CompositeDataTypeHTMLRepresentation) diffedRepresentations[0]).headerContent;
|
||||
|
||||
+123
-10
@@ -116,6 +116,22 @@ public class StructureDataTypeTest extends AbstractGenericTest {
|
||||
assertEquals("Comment4", dtc.getComment());
|
||||
assertEquals(ByteDataType.class, dtc.getDataType().getClass());
|
||||
|
||||
dtc = struct.add(ByteDataType.dataType, "field3", "new comment");
|
||||
assertEquals(8, dtc.getOffset());
|
||||
assertEquals(4, dtc.getOrdinal());
|
||||
assertEquals("field3", dtc.getFieldName()); // non-duplicate name was imposed
|
||||
assertEquals("new comment", dtc.getComment());
|
||||
assertEquals(ByteDataType.class, dtc.getDataType().getClass());
|
||||
assertNotNull(struct.findComponent("field3")); // which one is returned is arbitrary
|
||||
|
||||
dtc = struct.add(ByteDataType.dataType, "field3 1", "new comment");
|
||||
assertEquals(9, dtc.getOffset());
|
||||
assertEquals(5, dtc.getOrdinal());
|
||||
assertEquals("field3_1", dtc.getFieldName()); // non-duplicate name was imposed
|
||||
assertEquals("new comment", dtc.getComment());
|
||||
assertEquals(ByteDataType.class, dtc.getDataType().getClass());
|
||||
assertEquals(dtc, struct.findComponent("field3_1"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1306,6 +1322,22 @@ public class StructureDataTypeTest extends AbstractGenericTest {
|
||||
assertEquals(8, comps[3].getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelete() {
|
||||
|
||||
assertNotNull(struct.findComponent("field1"));
|
||||
|
||||
struct.delete(0);
|
||||
|
||||
assertNull(struct.findComponent("field1"));
|
||||
|
||||
assertEquals(7, struct.getLength());
|
||||
assertEquals(3, struct.getNumComponents());
|
||||
DataTypeComponent[] comps = struct.getDefinedComponents();
|
||||
assertEquals(DWordDataType.class, comps[1].getDataType().getClass());
|
||||
assertEquals(2, comps[1].getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteManyBF() throws InvalidDataTypeException {
|
||||
|
||||
@@ -1356,16 +1388,6 @@ public class StructureDataTypeTest extends AbstractGenericTest {
|
||||
assertEquals(5, comps[1].getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelete() {
|
||||
struct.delete(1);
|
||||
assertEquals(6, struct.getLength());
|
||||
assertEquals(3, struct.getNumComponents());
|
||||
DataTypeComponent[] comps = struct.getDefinedComponents();
|
||||
assertEquals(DWordDataType.class, comps[1].getDataType().getClass());
|
||||
assertEquals(1, comps[1].getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteBF() throws InvalidDataTypeException {
|
||||
|
||||
@@ -1409,8 +1431,12 @@ public class StructureDataTypeTest extends AbstractGenericTest {
|
||||
"Length: 11 Alignment: 1", struct);
|
||||
//@formatter:on
|
||||
|
||||
assertNotNull(struct.findComponent("bf2"));
|
||||
|
||||
struct.delete(3);
|
||||
|
||||
assertNull(struct.findComponent("bf2"));
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"pack(disabled)\n" +
|
||||
@@ -1426,8 +1452,12 @@ public class StructureDataTypeTest extends AbstractGenericTest {
|
||||
"Length: 11 Alignment: 1", struct);
|
||||
//@formatter:on
|
||||
|
||||
assertNotNull(struct.findComponent("bf3"));
|
||||
|
||||
struct.delete(3);
|
||||
|
||||
assertNull(struct.findComponent("bf3"));
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"pack(disabled)\n" +
|
||||
@@ -1443,8 +1473,12 @@ public class StructureDataTypeTest extends AbstractGenericTest {
|
||||
"Length: 11 Alignment: 1", struct);
|
||||
//@formatter:on
|
||||
|
||||
assertNotNull(struct.findComponent("bf4"));
|
||||
|
||||
struct.delete(4);
|
||||
|
||||
assertNull(struct.findComponent("bf4"));
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"pack(disabled)\n" +
|
||||
@@ -1461,8 +1495,12 @@ public class StructureDataTypeTest extends AbstractGenericTest {
|
||||
"Length: 11 Alignment: 1", struct);
|
||||
//@formatter:on
|
||||
|
||||
assertNotNull(struct.findComponent("bf1"));
|
||||
|
||||
struct.delete(2);
|
||||
|
||||
assertNull(struct.findComponent("bf1"));
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"pack(disabled)\n" +
|
||||
@@ -1731,6 +1769,21 @@ public class StructureDataTypeTest extends AbstractGenericTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetComponentByName() {
|
||||
DataTypeComponent dtc = struct.findComponent("field1");
|
||||
assertNotNull(dtc);
|
||||
assertEquals("field1", dtc.getFieldName());
|
||||
|
||||
dtc = struct.findComponent("field3");
|
||||
assertNotNull(dtc);
|
||||
assertEquals("field3", dtc.getFieldName());
|
||||
|
||||
dtc = struct.findComponent("field4");
|
||||
assertNotNull(dtc);
|
||||
assertEquals("field4", dtc.getFieldName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetComponentAt() {
|
||||
/**
|
||||
@@ -2629,6 +2682,66 @@ public class StructureDataTypeTest extends AbstractGenericTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldNameWhitespaceConvertedToUnderscores() {
|
||||
StructureDataType newStruct = new StructureDataType("Test", 0);
|
||||
DataTypeComponent component = newStruct.add(new ByteDataType(), " name with spaces", null);
|
||||
assertEquals("name_with_spaces", component.getFieldName());
|
||||
|
||||
component = newStruct.getComponent(0);
|
||||
component.setFieldName(" name in db with spaces ");
|
||||
assertEquals("name_in_db_with_spaces", component.getFieldName());
|
||||
|
||||
component = newStruct.add(new ByteDataType(), " another test ", null);
|
||||
assertEquals("another_test", component.getFieldName());
|
||||
|
||||
newStruct.insert(0, new ByteDataType(), 1, " insert test ", "");
|
||||
component = newStruct.getComponent(0);
|
||||
assertEquals("insert_test", component.getFieldName());
|
||||
|
||||
newStruct.replace(0, new ByteDataType(), 1, " insert test ", "");
|
||||
component = newStruct.getComponent(0);
|
||||
assertEquals("insert_test", component.getFieldName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultFieldNames() {
|
||||
StructureDataType newStruct = new StructureDataType("Test", 0);
|
||||
DataTypeComponent component = newStruct.add(new ByteDataType(), " ", null);
|
||||
assertNull(component.getFieldName());
|
||||
|
||||
component = newStruct.add(new ByteDataType(), null, null);
|
||||
assertNull(component.getFieldName());
|
||||
|
||||
component = newStruct.getComponent(0);
|
||||
assertNull(component.getFieldName());
|
||||
|
||||
component.setFieldName(" ");
|
||||
assertNull(component.getFieldName());
|
||||
|
||||
component = newStruct.add(new ByteDataType(), null, null);
|
||||
assertNull(component.getFieldName());
|
||||
|
||||
component = newStruct.add(new ByteDataType(), " ", null);
|
||||
assertNull(component.getFieldName());
|
||||
|
||||
newStruct.insert(0, new ByteDataType(), 1, null, "");
|
||||
component = newStruct.getComponent(0);
|
||||
assertNull(component.getFieldName());
|
||||
|
||||
newStruct.insert(0, new ByteDataType(), 1, " ", "");
|
||||
component = newStruct.getComponent(0);
|
||||
assertNull(component.getFieldName());
|
||||
|
||||
newStruct.replace(0, new ByteDataType(), 1, null, "");
|
||||
component = newStruct.getComponent(0);
|
||||
assertNull(component.getFieldName());
|
||||
|
||||
newStruct.replace(0, new ByteDataType(), 1, " ", "");
|
||||
component = newStruct.getComponent(0);
|
||||
assertNull(component.getFieldName());
|
||||
}
|
||||
|
||||
protected DataTypeManager createBigEndianDataTypeManager() {
|
||||
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
|
||||
dataOrg.setBigEndian(true);
|
||||
|
||||
@@ -592,6 +592,61 @@ public class UnionDataTypeTest extends AbstractGenericTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldNameWhitespaceConvertedToUnderscores() {
|
||||
UnionDataType newUnion = new UnionDataType("Test");
|
||||
DataTypeComponent component = newUnion.add(new ByteDataType(), " name with spaces", null);
|
||||
assertEquals("name_with_spaces", component.getFieldName());
|
||||
|
||||
component = newUnion.getComponent(0);
|
||||
component.setFieldName(" name in db with spaces ");
|
||||
assertEquals("name_in_db_with_spaces", component.getFieldName());
|
||||
|
||||
component = newUnion.add(new ByteDataType(), " another test ", null);
|
||||
assertEquals("another_test", component.getFieldName());
|
||||
|
||||
newUnion.insert(0, new ByteDataType(), 1, " insert test ", "");
|
||||
component = newUnion.getComponent(0);
|
||||
assertEquals("insert_test", component.getFieldName());
|
||||
|
||||
newUnion.insert(1, new ByteDataType(), 1, " insert test ", "");
|
||||
component = newUnion.getComponent(1);
|
||||
assertEquals("insert_test", component.getFieldName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultFieldNames() {
|
||||
UnionDataType newUnion = new UnionDataType("Test");
|
||||
DataTypeComponent component = newUnion.add(new ByteDataType(), " ", null);
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field0", component.getDefaultFieldName());
|
||||
|
||||
component = newUnion.add(new ByteDataType(), null, null);
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field1", component.getDefaultFieldName());
|
||||
|
||||
component = newUnion.getComponent(0);
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field0", component.getDefaultFieldName());
|
||||
|
||||
component.setFieldName(" ");
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field0", component.getDefaultFieldName());
|
||||
|
||||
component = newUnion.add(new ByteDataType(), null, null);
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field2", component.getDefaultFieldName());
|
||||
|
||||
component = newUnion.add(new ByteDataType(), " ", null);
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field3", component.getDefaultFieldName());
|
||||
|
||||
newUnion.insert(0, new ByteDataType(), 1, null, "");
|
||||
component = newUnion.getComponent(0);
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field0", component.getDefaultFieldName());
|
||||
}
|
||||
|
||||
protected DataTypeManager createBigEndianDataTypeManager() {
|
||||
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
|
||||
dataOrg.setBigEndian(true);
|
||||
|
||||
+3
-10
@@ -1225,13 +1225,7 @@ public class DefaultCompositeMember extends CompositeMember {
|
||||
for (int i = 0; i < count; i++) {
|
||||
DataTypeComponent component = composite.getComponent(i);
|
||||
if (oldFieldName.equals(component.getFieldName())) {
|
||||
try {
|
||||
component.setFieldName(newFieldName);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Msg.error(this, "Failed to rename temporary component name: " +
|
||||
getDataTypeName() + "." + oldFieldName + " -> " + newFieldName);
|
||||
}
|
||||
component.setFieldName(newFieldName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1356,9 +1350,8 @@ public class DefaultCompositeMember extends CompositeMember {
|
||||
* @throws CancelledException if monitor is cancelled
|
||||
*/
|
||||
public static boolean applyDataTypeMembers(Composite composite, boolean packingDisabled,
|
||||
boolean isClass, int preferredCompositeSize,
|
||||
List<? extends PdbMember> members, Consumer<String> errorConsumer, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
boolean isClass, int preferredCompositeSize, List<? extends PdbMember> members,
|
||||
Consumer<String> errorConsumer, TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
Composite editComposite = composite;
|
||||
|
||||
|
||||
+8
-7
@@ -19,7 +19,7 @@ import java.io.IOException;
|
||||
|
||||
import db.*;
|
||||
import ghidra.framework.data.OpenMode;
|
||||
import ghidra.util.StringUtilities;
|
||||
import ghidra.program.model.data.InternalDataTypeComponent;
|
||||
import ghidra.util.exception.VersionException;
|
||||
|
||||
/**
|
||||
@@ -61,19 +61,20 @@ abstract class ComponentDBAdapter {
|
||||
* @param length the total length of this component.
|
||||
* @param ordinal the component's ordinal.
|
||||
* @param offset the component's offset.
|
||||
* @param name the component's name. This name will be subject to revision based upon
|
||||
* {@link #cleanUpFieldName(String)} method use.
|
||||
* @param fieldName the component's name (may be null). This method may sanitize the name
|
||||
* (see {@link InternalDataTypeComponent#cleanupFieldName(String)}) before storing.
|
||||
* {@link InternalDataTypeComponent#cleanupFieldName(String)} method use.
|
||||
* @param comment a comment about this component
|
||||
* @return the component data type record.
|
||||
* @throws IOException if there is a problem accessing the database.
|
||||
*/
|
||||
abstract DBRecord createRecord(long dataTypeID, long parentID, int length, int ordinal,
|
||||
int offset, String name, String comment) throws IOException;
|
||||
int offset, String fieldName, String comment) throws IOException;
|
||||
|
||||
/**
|
||||
* Gets the record for the indicated component data type.
|
||||
* @param componentID the ID of the component data type to retrieve.
|
||||
* @return the component record
|
||||
* @return the component record or null if not found
|
||||
* @throws IOException if there is a problem accessing the database.
|
||||
*/
|
||||
abstract DBRecord getRecord(long componentID) throws IOException;
|
||||
@@ -89,8 +90,8 @@ abstract class ComponentDBAdapter {
|
||||
/**
|
||||
* Updates the component data type table with the provided record.
|
||||
* <p>
|
||||
* IMPORTANT: Any modification of field name should be subject to {@link #cleanUpFieldName(String)}
|
||||
* use first.
|
||||
* IMPORTANT: Any modification of field name should be subject to
|
||||
* {@link InternalDataTypeComponent#cleanupFieldName(String)} use first.
|
||||
*
|
||||
* @param record the new record
|
||||
* @throws IOException if there is a problem accessing the database.
|
||||
|
||||
+9
-3
@@ -17,6 +17,8 @@ package ghidra.program.database.data;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import db.*;
|
||||
import ghidra.program.model.data.InternalDataTypeComponent;
|
||||
import ghidra.util.exception.VersionException;
|
||||
@@ -73,15 +75,19 @@ class ComponentDBAdapterV0 extends ComponentDBAdapter {
|
||||
|
||||
@Override
|
||||
DBRecord createRecord(long dataTypeID, long parentID, int length, int ordinal, int offset,
|
||||
String name, String comment) throws IOException {
|
||||
String fieldName, String comment) throws IOException {
|
||||
long key =
|
||||
DataTypeManagerDB.createKey(DataTypeManagerDB.COMPONENT, componentTable.getKey());
|
||||
if (StringUtils.isBlank(comment)) {
|
||||
comment = null;
|
||||
}
|
||||
fieldName = InternalDataTypeComponent.cleanupFieldName(fieldName);
|
||||
|
||||
DBRecord record = ComponentDBAdapter.COMPONENT_SCHEMA.createRecord(key);
|
||||
record.setLongValue(ComponentDBAdapter.COMPONENT_PARENT_ID_COL, parentID);
|
||||
record.setLongValue(ComponentDBAdapter.COMPONENT_OFFSET_COL, offset);
|
||||
record.setLongValue(ComponentDBAdapter.COMPONENT_DT_ID_COL, dataTypeID);
|
||||
record.setString(ComponentDBAdapter.COMPONENT_FIELD_NAME_COL,
|
||||
InternalDataTypeComponent.cleanupFieldName(name));
|
||||
record.setString(ComponentDBAdapter.COMPONENT_FIELD_NAME_COL, fieldName);
|
||||
record.setString(ComponentDBAdapter.COMPONENT_COMMENT_COL, comment);
|
||||
record.setIntValue(ComponentDBAdapter.COMPONENT_SIZE_COL, length);
|
||||
record.setIntValue(ComponentDBAdapter.COMPONENT_ORDINAL_COL, ordinal);
|
||||
|
||||
+122
-3
@@ -18,6 +18,7 @@ package ghidra.program.database.data;
|
||||
import java.io.IOException;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import db.DBRecord;
|
||||
import ghidra.docking.settings.Settings;
|
||||
@@ -62,6 +63,111 @@ abstract class CompositeDB extends DataTypeDB implements CompositeInternal {
|
||||
*/
|
||||
protected abstract void initialize();
|
||||
|
||||
protected DataTypeComponentDB createComponent(long dtID, int length, int ordinal, int offset,
|
||||
String componentName, String comment) {
|
||||
|
||||
DBRecord rec;
|
||||
try {
|
||||
rec = componentAdapter.createRecord(dtID, key, length, ordinal, offset, componentName,
|
||||
comment);
|
||||
return new DataTypeComponentDB(dataMgr, componentAdapter, this, rec);
|
||||
}
|
||||
catch (IOException e) {
|
||||
dataMgr.dbError(e); // throws RuntimeException
|
||||
}
|
||||
// Will never reach here
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract DataTypeComponentDB getComponent(int ordinal) throws IndexOutOfBoundsException;
|
||||
|
||||
private DataTypeComponentDB getValidatedComponent(DataTypeComponentDB component)
|
||||
throws IOException {
|
||||
// Verify that component is still valid for this composite
|
||||
DBRecord rec = componentAdapter.getRecord(component.getKey());
|
||||
if (rec == null || rec.getLongValue(ComponentDBAdapter.COMPONENT_PARENT_ID_COL) != key) {
|
||||
throw new ConcurrentModificationException("Component has been deleted.");
|
||||
}
|
||||
|
||||
// Verify specified component instance is
|
||||
DataTypeComponentDB myDtc = getComponent(component.getOrdinal());
|
||||
if (myDtc != component) {
|
||||
// supplied instance is stale - it should exist in our defined component list
|
||||
myDtc = getComponent(rec.getIntValue(ComponentDBAdapter.COMPONENT_ORDINAL_COL));
|
||||
}
|
||||
return myDtc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name on a possibly stale component in support of the
|
||||
* {@link DataTypeComponent#setFieldName(String)} method.
|
||||
* <p>
|
||||
* If the field name is empty it will be set to null,
|
||||
* which is the default field name. The field name may be sanitized to convert all whitespace
|
||||
* characters to an underscore. If a name conflict occurs with another component, a one-up
|
||||
* number suffix will be added to avoid duplication.
|
||||
*
|
||||
* @param component data type component which has this composite as its parent.
|
||||
* @param name new field name or null
|
||||
* @return updated component instance
|
||||
*/
|
||||
protected DataTypeComponentDB setFieldName(DataTypeComponentDB component, String name) {
|
||||
lock.acquire();
|
||||
try {
|
||||
checkDeleted();
|
||||
if (component.getRecord() == null) {
|
||||
return component; // unable to change undefined component
|
||||
}
|
||||
|
||||
// Verify specified component instance is
|
||||
DataTypeComponentDB myDtc = getValidatedComponent(component);
|
||||
if (myDtc.doSetFieldName(name)) {
|
||||
dataMgr.dataTypeChanged(this, false);
|
||||
}
|
||||
return myDtc; // return modified component instance
|
||||
}
|
||||
catch (IOException e) {
|
||||
dataMgr.dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return component; // unchanged
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the comment on a possibly stale component in support of the
|
||||
* {@link DataTypeComponent#setComment(String)} method.
|
||||
*
|
||||
* @param component data type component which has this composite as its parent.
|
||||
* @param comment comment string
|
||||
* @return updated component instance
|
||||
*/
|
||||
protected DataTypeComponentDB setComment(DataTypeComponentDB component, String comment) {
|
||||
lock.acquire();
|
||||
try {
|
||||
checkDeleted();
|
||||
if (component.getRecord() == null) {
|
||||
return component; // unable to change undefined component
|
||||
}
|
||||
|
||||
// Verify specified component instance is
|
||||
DataTypeComponentDB myDtc = getValidatedComponent(component);
|
||||
if (myDtc.doSetComment(comment)) {
|
||||
dataMgr.dataTypeChanged(this, false);
|
||||
}
|
||||
return myDtc; // return modified component instance
|
||||
}
|
||||
catch (IOException e) {
|
||||
dataMgr.dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return component; // unchanged
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getAlignedLength() {
|
||||
return getLength();
|
||||
@@ -329,9 +435,20 @@ abstract class CompositeDB extends DataTypeDB implements CompositeInternal {
|
||||
compositeAdapter.updateRecord(record, true);
|
||||
}
|
||||
|
||||
protected void removeComponentRecord(long compKey) throws IOException {
|
||||
componentAdapter.removeRecord(compKey);
|
||||
dataMgr.getSettingsAdapter().removeAllSettingsRecords(compKey);
|
||||
/**
|
||||
* Removes a defined component without any alteration to other components or the components
|
||||
* list, removes parent association for component datatype and remove name-map entry.
|
||||
* @param dtc datatype component
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
protected void doDelete(DataTypeComponentDB dtc) throws IOException {
|
||||
|
||||
dtc.getDataType().removeParent(this);
|
||||
|
||||
// Remove component record
|
||||
long dtcKey = dtc.getKey();
|
||||
componentAdapter.removeRecord(dtcKey);
|
||||
dataMgr.getSettingsAdapter().removeAllSettingsRecords(dtcKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -673,6 +790,8 @@ abstract class CompositeDB extends DataTypeDB implements CompositeInternal {
|
||||
@Override
|
||||
public abstract DataTypeComponentDB[] getDefinedComponents();
|
||||
|
||||
abstract void forEachDefinedComponent(Consumer<DataTypeComponentDB> dtcConsumer);
|
||||
|
||||
@Override
|
||||
protected void postPointerResolve(DataType definitionDt, DataTypeConflictHandler handler) {
|
||||
Composite composite = (Composite) definitionDt;
|
||||
|
||||
+55
-20
@@ -16,14 +16,13 @@
|
||||
package ghidra.program.database.data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import db.DBRecord;
|
||||
import ghidra.docking.settings.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* Database implementation for a DataTypeComponent. If this
|
||||
@@ -215,14 +214,26 @@ class DataTypeComponentDB implements InternalDataTypeComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComment(String comment) {
|
||||
public DataTypeComponentDB setComment(String comment) {
|
||||
if (record != null) {
|
||||
return parent.setComment(this, comment);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
boolean doSetComment(String comment) {
|
||||
if (record != null) {
|
||||
if (StringUtils.isBlank(comment)) {
|
||||
comment = null;
|
||||
}
|
||||
record.setString(ComponentDBAdapter.COMPONENT_COMMENT_COL, comment);
|
||||
updateRecord(true);
|
||||
if (!Objects.equals(comment,
|
||||
record.getString(ComponentDBAdapter.COMPONENT_COMMENT_COL))) {
|
||||
record.setString(ComponentDBAdapter.COMPONENT_COMMENT_COL, comment);
|
||||
updateRecord(true); // updates DB and timestamp without notification
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -236,12 +247,27 @@ class DataTypeComponentDB implements InternalDataTypeComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFieldName(String name) throws DuplicateNameException {
|
||||
public DataTypeComponentDB setFieldName(String name) {
|
||||
if (record != null) {
|
||||
String fieldName = InternalDataTypeComponent.cleanupFieldName(name);
|
||||
record.setString(ComponentDBAdapter.COMPONENT_FIELD_NAME_COL, fieldName);
|
||||
updateRecord(true);
|
||||
// Parent must first validate instance before setting field name
|
||||
return parent.setFieldName(this, name);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
boolean doSetFieldName(String name) {
|
||||
if (record != null) {
|
||||
String oldName = record.getString(ComponentDBAdapter.COMPONENT_FIELD_NAME_COL);
|
||||
|
||||
// Cleanup invalid names and make unique within this composite
|
||||
String fieldName = InternalDataTypeComponent.cleanupFieldName(name);
|
||||
if (!Objects.equals(oldName, fieldName)) {
|
||||
record.setString(ComponentDBAdapter.COMPONENT_FIELD_NAME_COL, fieldName);
|
||||
updateRecord(true); // updates DB and timestamp without notification
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -261,8 +287,8 @@ class DataTypeComponentDB implements InternalDataTypeComponent {
|
||||
|
||||
if (offset != dtc.getOffset() || getLength() != dtc.getLength() ||
|
||||
ordinal != dtc.getOrdinal() ||
|
||||
!SystemUtilities.isEqual(getFieldName(), dtc.getFieldName()) ||
|
||||
!SystemUtilities.isEqual(getComment(), dtc.getComment())) {
|
||||
!Objects.equals(getFieldName(), dtc.getFieldName()) ||
|
||||
!Objects.equals(getComment(), dtc.getComment())) {
|
||||
return false;
|
||||
}
|
||||
if (!(myDt instanceof Pointer) && !myDt.getPathName().equals(otherDt.getPathName())) {
|
||||
@@ -307,8 +333,8 @@ class DataTypeComponentDB implements InternalDataTypeComponent {
|
||||
(myParent instanceof Composite) ? ((Composite) myParent).isPackingEnabled() : false;
|
||||
// Components don't need to have matching offset when structure has packing enabled
|
||||
if ((!isPacked && (offset != dtc.getOffset())) ||
|
||||
!SystemUtilities.isEqual(getFieldName(), dtc.getFieldName()) ||
|
||||
!SystemUtilities.isEqual(getComment(), dtc.getComment())) {
|
||||
!Objects.equals(getFieldName(), dtc.getFieldName()) ||
|
||||
!Objects.equals(getComment(), dtc.getComment())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -407,27 +433,36 @@ class DataTypeComponentDB implements InternalDataTypeComponent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform special-case component update that does not result in size or alignment changes.
|
||||
* @param name new component name
|
||||
* Perform special-case component update that does not result in size or alignment changes
|
||||
* and does not modify last change time.
|
||||
* @param fieldName new component name or null. If not null a unique component name will be forced.
|
||||
* @param dt new resolved datatype
|
||||
* @param comment new comment
|
||||
*/
|
||||
void update(String name, DataType dt, String comment) {
|
||||
void update(String fieldName, DataType dt, String comment) {
|
||||
if (record != null) {
|
||||
|
||||
String oldName = record.getString(ComponentDBAdapter.COMPONENT_FIELD_NAME_COL);
|
||||
|
||||
fieldName = InternalDataTypeComponent.cleanupFieldName(fieldName);
|
||||
if (!Objects.equals(oldName, fieldName)) {
|
||||
record.setString(ComponentDBAdapter.COMPONENT_FIELD_NAME_COL, fieldName);
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(comment)) {
|
||||
comment = null;
|
||||
}
|
||||
String fieldName = InternalDataTypeComponent.cleanupFieldName(name);
|
||||
record.setString(ComponentDBAdapter.COMPONENT_FIELD_NAME_COL, fieldName);
|
||||
|
||||
record.setLongValue(ComponentDBAdapter.COMPONENT_DT_ID_COL, dataMgr.getResolvedID(dt));
|
||||
record.setString(ComponentDBAdapter.COMPONENT_COMMENT_COL, comment);
|
||||
record.setString(ComponentDBAdapter.COMPONENT_COMMENT_COL,
|
||||
StringUtils.isBlank(comment) ? null : comment);
|
||||
updateRecord(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDataType(DataType newDt) {
|
||||
// intended for internal use only - note exsiting settings should be preserved
|
||||
// Internal Interface use only - existing settings should be preserved
|
||||
if (record != null) {
|
||||
record.setLongValue(ComponentDBAdapter.COMPONENT_DT_ID_COL,
|
||||
dataMgr.getResolvedID(newDt));
|
||||
|
||||
+1
@@ -2646,6 +2646,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
||||
status = compositeAdapter.removeRecord(dataTypeID);
|
||||
break;
|
||||
case COMPONENT:
|
||||
// NOTE: This is only used when completely removing a composite datatype
|
||||
status = componentAdapter.removeRecord(dataTypeID);
|
||||
break;
|
||||
case TYPEDEF:
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package ghidra.program.database.data;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ghidra.docking.settings.*;
|
||||
import ghidra.program.model.data.*;
|
||||
@@ -88,7 +88,7 @@ class DataTypeSettingsDB implements Settings {
|
||||
return false;
|
||||
}
|
||||
if (allowedSettingPredicate != null &&
|
||||
!allowedSettingPredicate.apply(settingsDefinition.getStorageKey())) {
|
||||
!allowedSettingPredicate.test(settingsDefinition.getStorageKey())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -118,7 +118,7 @@ class DataTypeSettingsDB implements Settings {
|
||||
return false;
|
||||
}
|
||||
if (name != null && allowedSettingPredicate != null &&
|
||||
!allowedSettingPredicate.apply(name)) {
|
||||
!allowedSettingPredicate.test(name)) {
|
||||
Msg.warn(this, "Ignored disallowed setting '" + name + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
+42
-66
@@ -17,6 +17,7 @@ package ghidra.program.database.data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import db.DBRecord;
|
||||
import db.Field;
|
||||
@@ -182,8 +183,8 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
}
|
||||
}
|
||||
|
||||
private DataTypeComponent doAdd(DataType dataType, int length, String name, String comment,
|
||||
boolean validatePackAndNotify)
|
||||
private DataTypeComponent doAdd(DataType dataType, int length, String name,
|
||||
String comment, boolean validatePackAndNotify)
|
||||
throws DataTypeDependencyException, IllegalArgumentException {
|
||||
|
||||
lock.acquire();
|
||||
@@ -204,9 +205,10 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
}
|
||||
else {
|
||||
int componentLength = getPreferredComponentLength(dataType, length);
|
||||
DBRecord rec = componentAdapter.createRecord(dataMgr.getResolvedID(dataType),
|
||||
key, componentLength, numComponents, structLength, name, comment);
|
||||
dtc = new DataTypeComponentDB(dataMgr, componentAdapter, this, rec);
|
||||
|
||||
dtc = createComponent(dataMgr.getResolvedID(dataType), componentLength,
|
||||
numComponents, structLength, name, comment);
|
||||
|
||||
dataType.addParent(this);
|
||||
components.add(dtc);
|
||||
}
|
||||
@@ -261,6 +263,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
}
|
||||
else {
|
||||
index = backupToFirstComponentContainingOffset(index, len);
|
||||
index = afterNonZeroComponentsAtOffset(index, len);
|
||||
}
|
||||
int definedComponentCount = components.size();
|
||||
if (index >= 0 && index < definedComponentCount) {
|
||||
@@ -370,9 +373,10 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
length = getPreferredComponentLength(dataType, length);
|
||||
|
||||
int offset = getComponent(ordinal).getOffset();
|
||||
DBRecord rec = componentAdapter.createRecord(dataMgr.getResolvedID(dataType), key,
|
||||
length, ordinal, offset, name, comment);
|
||||
DataTypeComponentDB dtc = new DataTypeComponentDB(dataMgr, componentAdapter, this, rec);
|
||||
|
||||
DataTypeComponentDB dtc = createComponent(dataMgr.getResolvedID(dataType), length,
|
||||
ordinal, offset, name, comment);
|
||||
|
||||
dataType.addParent(this);
|
||||
shiftOffsets(idx, 1, dtc.getLength());
|
||||
components.add(idx, dtc);
|
||||
@@ -383,13 +387,9 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
catch (DataTypeDependencyException e) {
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
dataMgr.dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -544,9 +544,9 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
BitFieldDataType bitfieldDt =
|
||||
new BitFieldDBDataType(baseDataType, bitSize, storageBitOffset);
|
||||
|
||||
DBRecord rec = componentAdapter.createRecord(dataMgr.getResolvedID(bitfieldDt), key,
|
||||
DataTypeComponentDB dtc = createComponent(dataMgr.getResolvedID(bitfieldDt),
|
||||
bitfieldDt.getStorageSize(), ordinal, revisedOffset, componentName, comment);
|
||||
DataTypeComponentDB dtc = new DataTypeComponentDB(dataMgr, componentAdapter, this, rec);
|
||||
|
||||
bitfieldDt.addParent(this); // has no affect
|
||||
components.add(startIndex, dtc);
|
||||
|
||||
@@ -554,13 +554,9 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
notifySizeChanged(false);
|
||||
return dtc;
|
||||
}
|
||||
catch (IOException e) {
|
||||
dataMgr.dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -597,7 +593,8 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
|
||||
/**
|
||||
* Removes a defined component at the specified index from the components list without any
|
||||
* alteration to other components and removes parent association for component datatype.
|
||||
* alteration to other components, removes parent association for component datatype and
|
||||
* remove name-map entry.
|
||||
* @param index defined component index
|
||||
* @return the defined component which was removed.
|
||||
* @throws IOException if an IO error occurs
|
||||
@@ -608,17 +605,6 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
return dtc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a defined component without any alteration to other components or the components
|
||||
* list and removes parent association for component datatype.
|
||||
* @param dtc datatype component
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
private void doDelete(DataTypeComponentDB dtc) throws IOException {
|
||||
dtc.getDataType().removeParent(this);
|
||||
removeComponentRecord(dtc.getKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a defined component at the specified index.
|
||||
* <p>
|
||||
@@ -1301,6 +1287,11 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void forEachDefinedComponent(Consumer<DataTypeComponentDB> dtcConsumer) {
|
||||
components.forEach(dtcConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataTypeComponent insertAtOffset(int offset, DataType dataType, int length)
|
||||
throws IllegalArgumentException {
|
||||
@@ -1384,10 +1375,11 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
return new DataTypeComponentDB(dataMgr, this, ordinal, offset);
|
||||
}
|
||||
|
||||
DBRecord rec = componentAdapter.createRecord(dataMgr.getResolvedID(dataType), key,
|
||||
length, ordinal, offset, name, comment);
|
||||
length = getPreferredComponentLength(dataType, length);
|
||||
|
||||
DataTypeComponentDB dtc = createComponent(dataMgr.getResolvedID(dataType), length,
|
||||
ordinal, offset, name, comment);
|
||||
dataType.addParent(this);
|
||||
DataTypeComponentDB dtc = new DataTypeComponentDB(dataMgr, componentAdapter, this, rec);
|
||||
shiftOffsets(index, 1 + additionalShift, length + additionalShift);
|
||||
components.add(index, dtc);
|
||||
repack(false, false);
|
||||
@@ -1397,13 +1389,9 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
catch (DataTypeDependencyException e) {
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
dataMgr.dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1442,6 +1430,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
return oldComponent;
|
||||
}
|
||||
|
||||
// Note: a unique componentName will be imposed if not null
|
||||
DataTypeComponent replaceComponent =
|
||||
replaceComponents(replacedComponents, dataType, offset, length, componentName, comment);
|
||||
|
||||
@@ -1729,13 +1718,11 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
for (int i = 0; i < otherComponents.length; i++) {
|
||||
resolvedDts[i] = doCheckedResolve(otherComponents[i].getDataType());
|
||||
}
|
||||
for (DataTypeComponentDB dtc : components) {
|
||||
dtc.getDataType().removeParent(this);
|
||||
long compKey = dtc.getKey();
|
||||
componentAdapter.removeRecord(compKey);
|
||||
dataMgr.getSettingsAdapter().removeAllSettingsRecords(compKey);
|
||||
}
|
||||
|
||||
// Remove all existing components
|
||||
for (DataTypeComponentDB dtc : components) {
|
||||
doDelete(dtc);
|
||||
}
|
||||
components.clear();
|
||||
numComponents = 0;
|
||||
structLength = 0;
|
||||
@@ -1799,8 +1786,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
}
|
||||
}
|
||||
|
||||
private void doReplaceWithNonPacked(Structure struct, DataType[] resolvedDts)
|
||||
throws IOException {
|
||||
private void doReplaceWithNonPacked(Structure struct, DataType[] resolvedDts) {
|
||||
|
||||
// caller responsible for record updates
|
||||
|
||||
@@ -1836,17 +1822,16 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
length = getPreferredComponentLength(dt, -1, maxLength);
|
||||
}
|
||||
|
||||
DBRecord rec = componentAdapter.createRecord(dataMgr.getResolvedID(dt), key, length,
|
||||
DataTypeComponentDB newDtc = createComponent(dataMgr.getResolvedID(dt), length,
|
||||
dtc.getOrdinal(), dtc.getOffset(), dtc.getFieldName(), dtc.getComment());
|
||||
|
||||
dt.addParent(this);
|
||||
DataTypeComponentDB newDtc =
|
||||
new DataTypeComponentDB(dataMgr, componentAdapter, this, rec);
|
||||
components.add(newDtc);
|
||||
}
|
||||
}
|
||||
|
||||
private void doCopy(Structure struct, DataTypeComponent[] definedComponents,
|
||||
DataType[] resolvedDts) throws IOException {
|
||||
DataType[] resolvedDts) {
|
||||
|
||||
// simple replication of struct - caller must perform record updates
|
||||
structLength = struct.isZeroLength() ? 0 : struct.getLength();
|
||||
@@ -1857,12 +1842,11 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
for (int i = 0; i < otherComponents.length; i++) {
|
||||
DataTypeComponent dtc = otherComponents[i];
|
||||
DataType dt = resolvedDts[i]; // ancestry check already performed by caller
|
||||
DBRecord rec =
|
||||
componentAdapter.createRecord(dataMgr.getResolvedID(dt), key, dtc.getLength(),
|
||||
dtc.getOrdinal(), dtc.getOffset(), dtc.getFieldName(), dtc.getComment());
|
||||
|
||||
DataTypeComponentDB newDtc = createComponent(dataMgr.getResolvedID(dt), dtc.getLength(),
|
||||
dtc.getOrdinal(), dtc.getOffset(), dtc.getFieldName(), dtc.getComment());
|
||||
|
||||
dt.addParent(this);
|
||||
DataTypeComponentDB newDtc =
|
||||
new DataTypeComponentDB(dataMgr, componentAdapter, this, rec);
|
||||
components.add(newDtc);
|
||||
}
|
||||
}
|
||||
@@ -2345,10 +2329,10 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
DataTypeComponentDB newDtc = null;
|
||||
if (!clearOnly) {
|
||||
// insert new component
|
||||
DBRecord rec = componentAdapter.createRecord(dataMgr.getResolvedID(resolvedDataType),
|
||||
key, length, newOrdinal, newOffset, name, comment);
|
||||
newDtc = createComponent(dataMgr.getResolvedID(resolvedDataType), length, newOrdinal,
|
||||
newOffset, name, comment);
|
||||
|
||||
resolvedDataType.addParent(this);
|
||||
newDtc = new DataTypeComponentDB(dataMgr, componentAdapter, this, rec);
|
||||
components.add(index, newDtc);
|
||||
}
|
||||
|
||||
@@ -2477,15 +2461,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
try {
|
||||
checkDeleted();
|
||||
for (DataTypeComponentDB dtc : components) {
|
||||
dtc.getDataType().removeParent(this);
|
||||
try {
|
||||
long compKey = dtc.getKey();
|
||||
componentAdapter.removeRecord(compKey);
|
||||
dataMgr.getSettingsAdapter().removeAllSettingsRecords(compKey);
|
||||
}
|
||||
catch (IOException e) {
|
||||
dataMgr.dbError(e);
|
||||
}
|
||||
doDelete(dtc);
|
||||
}
|
||||
components.clear();
|
||||
structLength = 0;
|
||||
|
||||
+19
-24
@@ -17,6 +17,7 @@ package ghidra.program.database.data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import db.DBRecord;
|
||||
import db.Field;
|
||||
@@ -61,7 +62,9 @@ class UnionDB extends CompositeDB implements UnionInternal {
|
||||
Field[] ids = componentAdapter.getComponentIdsInComposite(key);
|
||||
for (Field id : ids) {
|
||||
DBRecord rec = componentAdapter.getRecord(id.getLongValue());
|
||||
components.add(new DataTypeComponentDB(dataMgr, componentAdapter, this, rec));
|
||||
DataTypeComponentDB component =
|
||||
new DataTypeComponentDB(dataMgr, componentAdapter, this, rec);
|
||||
components.add(component);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
@@ -122,8 +125,8 @@ class UnionDB extends CompositeDB implements UnionInternal {
|
||||
return length;
|
||||
}
|
||||
|
||||
private DataTypeComponent doAdd(DataType dataType, int length, String name, String comment,
|
||||
boolean validateAlignAndNotify) throws DataTypeDependencyException {
|
||||
private DataTypeComponent doAdd(DataType dataType, int length, String name,
|
||||
String comment, boolean validateAlignAndNotify) throws DataTypeDependencyException {
|
||||
|
||||
dataType = validateDataType(dataType);
|
||||
|
||||
@@ -145,19 +148,6 @@ class UnionDB extends CompositeDB implements UnionInternal {
|
||||
return dtc;
|
||||
}
|
||||
|
||||
private DataTypeComponentDB createComponent(long dtID, int length, int ordinal, int offset,
|
||||
String name, String comment) {
|
||||
DBRecord rec;
|
||||
try {
|
||||
rec = componentAdapter.createRecord(dtID, key, length, ordinal, offset, name, comment);
|
||||
return new DataTypeComponentDB(dataMgr, componentAdapter, this, rec);
|
||||
}
|
||||
catch (IOException e) {
|
||||
dataMgr.dbError(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent insert(int ordinal, DataType dataType, int length, String name,
|
||||
String comment) throws IllegalArgumentException {
|
||||
@@ -222,8 +212,8 @@ class UnionDB extends CompositeDB implements UnionInternal {
|
||||
getComputedAlignment(true); // ensure previous alignment has been stored
|
||||
|
||||
DataTypeComponentDB dtc = components.remove(ordinal);
|
||||
dtc.getDataType().removeParent(this);
|
||||
removeComponentRecord(dtc.getKey());
|
||||
doDelete(dtc);
|
||||
|
||||
shiftOrdinals(ordinal, -1);
|
||||
|
||||
if (!repack(false, true)) {
|
||||
@@ -265,8 +255,7 @@ class UnionDB extends CompositeDB implements UnionInternal {
|
||||
int ordinal = dtc.getOrdinal();
|
||||
if (ordinals.contains(ordinal)) {
|
||||
// component removed - delete record
|
||||
dtc.getDataType().removeParent(this);
|
||||
removeComponentRecord(dtc.getKey());
|
||||
doDelete(dtc);
|
||||
--ordinalAdjustment;
|
||||
}
|
||||
else {
|
||||
@@ -347,9 +336,9 @@ class UnionDB extends CompositeDB implements UnionInternal {
|
||||
}
|
||||
|
||||
for (DataTypeComponentDB dtc : components) {
|
||||
dtc.getDataType().removeParent(this);
|
||||
removeComponentRecord(dtc.getKey());
|
||||
doDelete(dtc);
|
||||
}
|
||||
|
||||
components.clear();
|
||||
unionAlignment = -1;
|
||||
computedAlignment = -1;
|
||||
@@ -358,7 +347,8 @@ class UnionDB extends CompositeDB implements UnionInternal {
|
||||
|
||||
for (int i = 0; i < otherComponents.length; i++) {
|
||||
DataTypeComponent dtc = otherComponents[i];
|
||||
doAdd(resolvedDts[i], dtc.getLength(), dtc.getFieldName(), dtc.getComment(), false);
|
||||
doAdd(resolvedDts[i], dtc.getLength(), dtc.getFieldName(), dtc.getComment(),
|
||||
false);
|
||||
}
|
||||
|
||||
repack(false, false);
|
||||
@@ -427,7 +417,7 @@ class UnionDB extends CompositeDB implements UnionInternal {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent getComponent(int ordinal) {
|
||||
public DataTypeComponentDB getComponent(int ordinal) {
|
||||
lock.acquire();
|
||||
try {
|
||||
checkIsValid();
|
||||
@@ -458,6 +448,11 @@ class UnionDB extends CompositeDB implements UnionInternal {
|
||||
return getComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
void forEachDefinedComponent(Consumer<DataTypeComponentDB> dtcConsumer) {
|
||||
components.forEach(dtcConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType copy(DataTypeManager dtm) {
|
||||
UnionDataType union = new UnionDataType(getCategoryPath(), getName(), dtm);
|
||||
|
||||
+1
-7
@@ -18,7 +18,6 @@ package ghidra.program.database.data.merge;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* DataType merger for structures.
|
||||
@@ -215,12 +214,7 @@ public class StructureMerger extends DataTypeMerger<Structure> {
|
||||
otherName));
|
||||
}
|
||||
if (workingName == null && otherName != null) {
|
||||
try {
|
||||
workingComp.setFieldName(otherName);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
// This exception is going away soon, so ignore it for now
|
||||
}
|
||||
workingComp.setFieldName(otherName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-8
@@ -16,7 +16,6 @@
|
||||
package ghidra.program.database.data.merge;
|
||||
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* Datatype merger for Unions
|
||||
@@ -77,13 +76,8 @@ public class UnionMerger extends DataTypeMerger<Union> {
|
||||
}
|
||||
|
||||
private void appySameTypeComponent(DataTypeComponent resultComp, DataTypeComponent component) {
|
||||
try {
|
||||
resultComp.setFieldName(component.getFieldName());
|
||||
resultComp.setComment(join(resultComp.getComment(), component.getComment()));
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
// can't happen, we already looked for a component with the same name
|
||||
}
|
||||
resultComp.setFieldName(component.getFieldName());
|
||||
resultComp.setComment(join(resultComp.getComment(), component.getComment()));
|
||||
}
|
||||
|
||||
private void applySameNamedComponent(DataTypeComponent comp1, DataTypeComponent comp2)
|
||||
|
||||
+2
-2
@@ -117,7 +117,7 @@ public class AlignedStructureInspector extends AlignedStructurePacker {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComment(String comment) {
|
||||
public DataTypeComponent setComment(String comment) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ public class AlignedStructureInspector extends AlignedStructurePacker {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFieldName(String fieldName) throws DuplicateNameException {
|
||||
public DataTypeComponent setFieldName(String fieldName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
+74
-14
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package ghidra.program.model.data;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Interface for common methods in Structure and Union
|
||||
@@ -55,6 +55,61 @@ public interface Composite extends DataType {
|
||||
*/
|
||||
public abstract DataTypeComponent getComponent(int ordinal) throws IndexOutOfBoundsException;
|
||||
|
||||
/**
|
||||
* Find the first component which has the specified case-sensitive field name.
|
||||
* Note that multiple components may be specified with the same name, if this is a possibility
|
||||
* the {@link #findComponents(String)} method should be used. Only components with an explicit
|
||||
* non-default field name will be considered. The name specified may be sanitized to be
|
||||
* consistent with those permitted by {@link Composite} data types.
|
||||
*
|
||||
* @param fieldName field name
|
||||
* @return first data type component whose field name matches or null if not found
|
||||
*/
|
||||
public default DataTypeComponent findComponent(String fieldName) {
|
||||
|
||||
if (getNumDefinedComponents() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
fieldName = InternalDataTypeComponent.cleanupFieldName(fieldName);
|
||||
if (fieldName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (DataTypeComponent dtc : getDefinedComponents()) {
|
||||
if (fieldName.equals(dtc.getFieldName())) {
|
||||
return dtc;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all components which have the specified case-sensitive field name.
|
||||
* Note that multiple components may be specified with the same name, if this is a possibility
|
||||
* the {@link #findComponents(String)} method should be used. Only components with an explicit
|
||||
* non-default field name will be considered. The name specified may be sanitized to be
|
||||
* consistent with those permitted by {@link Composite} data types.
|
||||
*
|
||||
* @param name field name
|
||||
* @return all data type components whose field name matches or empty list if not found
|
||||
*/
|
||||
public default List<DataTypeComponent> findComponents(String name) {
|
||||
|
||||
if (getNumDefinedComponents() == 0) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
List<DataTypeComponent> list = new ArrayList<>();
|
||||
for (DataTypeComponent dtc : getDefinedComponents()) {
|
||||
if (name.equals(dtc.getFieldName())) {
|
||||
list.add(dtc);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of Data Type Components that make up this composite including
|
||||
* undefined filler components which may be present within a Structure which has packing disabled.
|
||||
@@ -113,15 +168,16 @@ public interface Composite extends DataType {
|
||||
* automatically to provide the proper alignment.
|
||||
*
|
||||
* @param dataType the datatype to add.
|
||||
* @param name the field name to associate with this component.
|
||||
* @param comment the comment to associate with this component.
|
||||
* @param componentName the field name to associate with this component. (may be null)
|
||||
* The name may be sanitized to convert all whitespace characters to an underscore.
|
||||
* @param comment the comment to associate with this component. (may be null)
|
||||
* @return the componentDataType created.
|
||||
* @throws IllegalArgumentException if the specified data type is not
|
||||
* allowed to be added to this composite data type.
|
||||
* For example, suppose dt1 contains dt2. Therefore it is not valid
|
||||
* to add dt1 to dt2 since this would cause a cyclic dependency.
|
||||
*/
|
||||
public DataTypeComponent add(DataType dataType, String name, String comment)
|
||||
public DataTypeComponent add(DataType dataType, String componentName, String comment)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
@@ -132,8 +188,9 @@ public interface Composite extends DataType {
|
||||
*
|
||||
* @param baseDataType the bitfield base datatype (certain restrictions apply).
|
||||
* @param bitSize the bitfield size in bits
|
||||
* @param componentName the field name to associate with this component.
|
||||
* @param comment the comment to associate with this component.
|
||||
* @param componentName the field name to associate with this component. (may be null)
|
||||
* The name may be sanitized to convert all whitespace characters to an underscore.
|
||||
* @param comment the comment to associate with this component. (may be null)
|
||||
* @return the componentDataType created whose associated data type will
|
||||
* be BitFieldDataType.
|
||||
* @throws InvalidDataTypeException if the specified data type is
|
||||
@@ -151,16 +208,17 @@ public interface Composite extends DataType {
|
||||
* @param dataType the datatype to add.
|
||||
* @param length the length to associate with the datatype.
|
||||
* For fixed length types a length <= 0 will use the length of the resolved dataType.
|
||||
* @param name the field name to associate with this component.
|
||||
* @param comment the comment to associate with this component.
|
||||
* @param componentName the field name to associate with this component (may be null).
|
||||
* The name may be sanitized to convert all whitespace characters to an underscore.
|
||||
* @param comment the comment to associate with this component (may be null).
|
||||
* @return the componentDataType created.
|
||||
* @throws IllegalArgumentException if the specified data type is not
|
||||
* allowed to be added to this composite data type or an invalid length is specified.
|
||||
* For example, suppose dt1 contains dt2. Therefore it is not valid
|
||||
* to add dt1 to dt2 since this would cause a cyclic dependency.
|
||||
*/
|
||||
public DataTypeComponent add(DataType dataType, int length, String name, String comment)
|
||||
throws IllegalArgumentException;
|
||||
public DataTypeComponent add(DataType dataType, int length, String componentName,
|
||||
String comment) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Inserts a new datatype at the specified ordinal position in this composite.
|
||||
@@ -211,8 +269,9 @@ public interface Composite extends DataType {
|
||||
* @param dataType the datatype to insert.
|
||||
* @param length the length to associate with the datatype.
|
||||
* For fixed length types a length <= 0 will use the length of the resolved dataType.
|
||||
* @param name the field name to associate with this component.
|
||||
* @param comment the comment to associate with this component.
|
||||
* @param componentName the field name to associate with this component (may be null).
|
||||
* The name may be sanitized to convert all whitespace characters to an underscore.
|
||||
* @param comment the comment to associate with this component. (may be null)
|
||||
* @return the componentDataType created.
|
||||
* @throws IllegalArgumentException if the specified data type is not
|
||||
* allowed to be inserted into this composite data type or an invalid length
|
||||
@@ -221,8 +280,9 @@ public interface Composite extends DataType {
|
||||
* to insert dt1 to dt2 since this would cause a cyclic dependency.
|
||||
* @throws IndexOutOfBoundsException if component ordinal is out of bounds
|
||||
*/
|
||||
public DataTypeComponent insert(int ordinal, DataType dataType, int length, String name,
|
||||
String comment) throws IndexOutOfBoundsException, IllegalArgumentException;
|
||||
public DataTypeComponent insert(int ordinal, DataType dataType, int length,
|
||||
String componentName, String comment)
|
||||
throws IndexOutOfBoundsException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Deletes the component at the given ordinal position.
|
||||
|
||||
+11
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package ghidra.program.model.data;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.program.database.data.DataTypeUtilities;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
@@ -62,6 +64,13 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C
|
||||
description = "";
|
||||
}
|
||||
|
||||
protected DataTypeComponentImpl createComponent(DataType dataType, int length, int ordinal,
|
||||
int offset, String fieldName, String comment) {
|
||||
|
||||
return new DataTypeComponentImpl(dataType, this, length, ordinal,
|
||||
offset, fieldName, comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getAlignedLength() {
|
||||
return getLength();
|
||||
@@ -441,6 +450,8 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C
|
||||
@Override
|
||||
public abstract int getAlignment();
|
||||
|
||||
abstract void forEachDefinedComponent(Consumer<DataTypeComponentImpl> dtcConsumer);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return CompositeInternal.toString(this);
|
||||
|
||||
-1
@@ -260,5 +260,4 @@ public interface CompositeInternal extends Composite {
|
||||
buf.append(")");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-10
@@ -16,7 +16,6 @@
|
||||
package ghidra.program.model.data;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* DataTypeComponents are holders for the dataTypes that make up composite (Structures
|
||||
@@ -98,9 +97,14 @@ public interface DataTypeComponent {
|
||||
|
||||
/**
|
||||
* Sets the comment for the component.
|
||||
* <P>
|
||||
* NOTE: Since a datatype component instance is intended to be immutable a new component
|
||||
* instance is returned which will reflect the modified component.
|
||||
*
|
||||
* @param comment this components comment or null to clear comment.
|
||||
* @return a new component instance which will reflect the change.
|
||||
*/
|
||||
public void setComment(String comment);
|
||||
public DataTypeComponent setComment(String comment);
|
||||
|
||||
/**
|
||||
* Get this component's field name within its parent.
|
||||
@@ -112,17 +116,17 @@ public interface DataTypeComponent {
|
||||
|
||||
/**
|
||||
* Sets the field name. If the field name is empty it will be set to null,
|
||||
* which is the default field name. An exception is thrown if one of the
|
||||
* parent's other components already has the specified field name.
|
||||
* which is the default field name. The field name may be sanitized to convert all whitespace
|
||||
* characters to an underscore. If a name conflict occurs with another component, a one-up
|
||||
* number suffix will be added to avoid duplication.
|
||||
* <P>
|
||||
* NOTE: Since a datatype component instance is intended to be immutable a new component
|
||||
* instance is returned which will reflect the modified component.
|
||||
*
|
||||
* @param fieldName the new field name for this component.
|
||||
*
|
||||
* @throws DuplicateNameException This is actually never thrown anymore. All the other ways
|
||||
* of naming fields did not perform this check and it would cause quite a bit of churn to
|
||||
* add that exception to all the other methods that affect field names. So to be consistent,
|
||||
* we no longer do the check in this method.
|
||||
* @return a new component instance which will reflect the change.
|
||||
*/
|
||||
public void setFieldName(String fieldName) throws DuplicateNameException;
|
||||
public DataTypeComponent setFieldName(String fieldName);
|
||||
|
||||
/**
|
||||
* Returns a default field name for this component. Used only if a field name is not set.
|
||||
|
||||
+18
-16
@@ -16,13 +16,13 @@
|
||||
package ghidra.program.model.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.docking.settings.SettingsImpl;
|
||||
import ghidra.program.database.data.DataTypeUtilities;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
@@ -32,7 +32,7 @@ public class DataTypeComponentImpl implements InternalDataTypeComponent, Seriali
|
||||
private final static long serialVersionUID = 1;
|
||||
|
||||
private DataType dataType;
|
||||
private CompositeDataTypeImpl parent; // parent prototype containing us
|
||||
private CompositeDataTypeImpl parent; // composite containing us (may be null in certain use cases)
|
||||
private int offset; // offset in parent
|
||||
private int ordinal; // position in parent
|
||||
private SettingsImpl defaultSettings;
|
||||
@@ -48,12 +48,11 @@ public class DataTypeComponentImpl implements InternalDataTypeComponent, Seriali
|
||||
* @param length the length of the dataType in this component.
|
||||
* @param ordinal the index within its parent.
|
||||
* @param offset the byte offset within the parent
|
||||
* @param fieldName the name associated with this component
|
||||
* @param comment the comment associated with this component
|
||||
* @param fieldName the name associated with this component or null
|
||||
* @param comment the comment associated with this component or null
|
||||
*/
|
||||
public DataTypeComponentImpl(DataType dataType, CompositeDataTypeImpl parent, int length,
|
||||
int ordinal, int offset, String fieldName, String comment) {
|
||||
|
||||
this.parent = parent;
|
||||
this.ordinal = ordinal;
|
||||
this.offset = offset;
|
||||
@@ -67,7 +66,7 @@ public class DataTypeComponentImpl implements InternalDataTypeComponent, Seriali
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DataTypeComponent
|
||||
* Create a new DataTypeComponent without a name
|
||||
* @param dataType the dataType for this component
|
||||
* @param parent the dataType that this component belongs to
|
||||
* @param length the length of the dataType in this component.
|
||||
@@ -119,8 +118,9 @@ public class DataTypeComponentImpl implements InternalDataTypeComponent, Seriali
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComment(String comment) {
|
||||
public DataTypeComponentImpl setComment(String comment) {
|
||||
this.comment = StringUtils.isBlank(comment) ? null : comment;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,8 +132,10 @@ public class DataTypeComponentImpl implements InternalDataTypeComponent, Seriali
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFieldName(String name) throws DuplicateNameException {
|
||||
this.fieldName = InternalDataTypeComponent.cleanupFieldName(name);
|
||||
public DataTypeComponentImpl setFieldName(String name) {
|
||||
// Cleanup invalid names and make unique within its parent
|
||||
fieldName = InternalDataTypeComponent.cleanupFieldName(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static void checkDefaultFieldName(String fieldName) throws DuplicateNameException {
|
||||
@@ -174,9 +176,9 @@ public class DataTypeComponentImpl implements InternalDataTypeComponent, Seriali
|
||||
* @param newComment new comment
|
||||
*/
|
||||
void update(String name, DataType newDataType, String newComment) {
|
||||
this.fieldName = InternalDataTypeComponent.cleanupFieldName(name);
|
||||
this.dataType = newDataType;
|
||||
this.comment = StringUtils.isBlank(newComment) ? null : newComment;
|
||||
setFieldName(name);
|
||||
setComment(newComment);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -220,7 +222,7 @@ public class DataTypeComponentImpl implements InternalDataTypeComponent, Seriali
|
||||
|
||||
@Override
|
||||
public Settings getDefaultSettings() {
|
||||
if (defaultSettings == null) {
|
||||
if (defaultSettings == null && parent != null) {
|
||||
DataTypeManager dataMgr = parent.getDataTypeManager();
|
||||
boolean immutableSettings =
|
||||
dataMgr == null || !dataMgr.allowsDefaultComponentSettings();
|
||||
@@ -251,8 +253,8 @@ public class DataTypeComponentImpl implements InternalDataTypeComponent, Seriali
|
||||
|
||||
if (offset != dtc.getOffset() || getLength() != dtc.getLength() ||
|
||||
ordinal != dtc.getOrdinal() ||
|
||||
!SystemUtilities.isEqual(getFieldName(), dtc.getFieldName()) ||
|
||||
!SystemUtilities.isEqual(getComment(), dtc.getComment())) {
|
||||
!Objects.equals(getFieldName(), dtc.getFieldName()) ||
|
||||
!Objects.equals(getComment(), dtc.getComment())) {
|
||||
return false;
|
||||
}
|
||||
if (!(myDt instanceof Pointer)) {
|
||||
@@ -291,8 +293,8 @@ public class DataTypeComponentImpl implements InternalDataTypeComponent, Seriali
|
||||
(myParent instanceof Composite) ? ((Composite) myParent).isPackingEnabled() : false;
|
||||
// Components don't need to have matching offset when they are aligned
|
||||
if ((!aligned && (offset != dtc.getOffset())) ||
|
||||
!SystemUtilities.isEqual(getFieldName(), dtc.getFieldName()) ||
|
||||
!SystemUtilities.isEqual(getComment(), dtc.getComment())) {
|
||||
!Objects.equals(getFieldName(), dtc.getFieldName()) ||
|
||||
!Objects.equals(getComment(), dtc.getComment())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+75
-187
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -126,9 +126,8 @@ public class DialogResourceDataType extends DynamicDataType {
|
||||
private int addDlgTemplateStructure(MemBuffer memBuffer, List<DataTypeComponent> comps,
|
||||
int tempOffset, boolean ex) {
|
||||
|
||||
tempOffset =
|
||||
addComp(ex ? dlgTemplateExStructure() : dlgTemplateStructure(), ex ? 26 : 18,
|
||||
"Dialog Template Structure", memBuffer.getAddress(), comps, tempOffset);
|
||||
tempOffset = addComp(ex ? dlgTemplateExStructure() : dlgTemplateStructure(), ex ? 26 : 18,
|
||||
"Dialog Template Structure", memBuffer.getAddress(), comps, tempOffset);
|
||||
|
||||
return tempOffset;
|
||||
}
|
||||
@@ -139,15 +138,13 @@ public class DialogResourceDataType extends DynamicDataType {
|
||||
|
||||
short dialogMenuInfo = memBuffer.getShort(tempOffset);
|
||||
if (dialogMenuInfo == 0x0000) { //if 0x0000 - no menu
|
||||
tempOffset =
|
||||
addComp(createArrayOfShorts(1), 2, "Dialog Menu",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
tempOffset = addComp(createArrayOfShorts(1), 2, "Dialog Menu",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
}
|
||||
//if 0xFFFF - one more item that is resource number of the menu
|
||||
else if (dialogMenuInfo == 0xFFFF) {
|
||||
tempOffset =
|
||||
addComp(createArrayOfShorts(2), 4, "Dialog Menu",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
tempOffset = addComp(createArrayOfShorts(2), 4, "Dialog Menu",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
}
|
||||
//array is unicode name of menu in executable file
|
||||
else {
|
||||
@@ -164,15 +161,13 @@ public class DialogResourceDataType extends DynamicDataType {
|
||||
|
||||
//if 0x0000 - use predefined class
|
||||
if (dialogClassInfo == 0x0000) {
|
||||
tempOffset =
|
||||
addComp(createArrayOfShorts(1), 2, "Dialog Class",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
tempOffset = addComp(createArrayOfShorts(1), 2, "Dialog Class",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
}
|
||||
//if 0xFFFF - one more item that is ordinal value of system window class
|
||||
else if (dialogClassInfo == 0xFFFF) {
|
||||
tempOffset =
|
||||
addComp(createArrayOfShorts(2), 4, "Dialog Class",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
tempOffset = addComp(createArrayOfShorts(2), 4, "Dialog Class",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
}
|
||||
//array is unicode name of menu in executable file
|
||||
else {
|
||||
@@ -188,9 +183,8 @@ public class DialogResourceDataType extends DynamicDataType {
|
||||
short dialogTitleInfo = memBuffer.getShort(tempOffset);
|
||||
//if 0x0000 - Dialog has no title
|
||||
if (dialogTitleInfo == 0x0000) {
|
||||
tempOffset =
|
||||
addComp(createArrayOfShorts(1), 2, "Dialog Title",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
tempOffset = addComp(createArrayOfShorts(1), 2, "Dialog Title",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
}
|
||||
//array is unicode name of menu in executable file
|
||||
else {
|
||||
@@ -206,22 +200,21 @@ public class DialogResourceDataType extends DynamicDataType {
|
||||
private int addDialogFontComponents(MemBuffer memBuffer, List<DataTypeComponent> comps,
|
||||
int tempOffset, boolean ex) {
|
||||
//add Dialog Font size
|
||||
tempOffset =
|
||||
addComp(new ShortDataType(), 2, "Dialog Font Size",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
tempOffset = addComp(new ShortDataType(), 2, "Dialog Font Size",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
|
||||
if (ex) {
|
||||
//add Dialog Font weight
|
||||
tempOffset = addComp(new WordDataType(), 2, "Dialog Font Weight", memBuffer.getAddress().add(tempOffset),
|
||||
comps, tempOffset);
|
||||
tempOffset = addComp(new WordDataType(), 2, "Dialog Font Weight",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
|
||||
//add Dialog Font Italic
|
||||
tempOffset = addComp(new ByteDataType(), 1, "Dialog Font Italic", memBuffer.getAddress().add(tempOffset),
|
||||
comps, tempOffset);
|
||||
tempOffset = addComp(new ByteDataType(), 1, "Dialog Font Italic",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
|
||||
//add Dialog Font Charset
|
||||
tempOffset = addComp(new ByteDataType(), 1, "Dialog Font Charset", memBuffer.getAddress().add(tempOffset),
|
||||
comps, tempOffset);
|
||||
tempOffset = addComp(new ByteDataType(), 1, "Dialog Font Charset",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
}
|
||||
|
||||
//add Dialog Font Style array
|
||||
@@ -235,9 +228,8 @@ public class DialogResourceDataType extends DynamicDataType {
|
||||
int tempOffset, boolean ex) {
|
||||
|
||||
if ((memBuffer.getAddress().add(tempOffset).getOffset() % 4) != 0) {
|
||||
tempOffset =
|
||||
addComp(new AlignmentDataType(), 2, "Alignment",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
tempOffset = addComp(new AlignmentDataType(), 2, "Alignment",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
}
|
||||
tempOffset =
|
||||
addComp(ex ? dlgItemTemplateExStructure() : dlgItemTemplateStructure(), ex ? 24 : 18,
|
||||
@@ -247,16 +239,15 @@ public class DialogResourceDataType extends DynamicDataType {
|
||||
}
|
||||
|
||||
//adds Item class array - 1st after component after each DLGITEMTEMPLATE structure
|
||||
private int addItemClassArray(MemBuffer memBuffer, List<DataTypeComponent> comps, int tempOffset)
|
||||
throws MemoryAccessException {
|
||||
private int addItemClassArray(MemBuffer memBuffer, List<DataTypeComponent> comps,
|
||||
int tempOffset) throws MemoryAccessException {
|
||||
|
||||
short itemClassInfo = memBuffer.getShort(tempOffset);
|
||||
if ((itemClassInfo & 0xffff) == 0xffff) {
|
||||
short classType = memBuffer.getShort(tempOffset + 2);
|
||||
tempOffset =
|
||||
addComp(createArrayOfShorts(2), 4, "Item Class Type or Name" + "(" +
|
||||
getItemType(Integer.valueOf(classType)) + ")",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
tempOffset = addComp(createArrayOfShorts(2), 4,
|
||||
"Item Class Type or Name" + "(" + getItemType(Integer.valueOf(classType)) + ")",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
}
|
||||
else {
|
||||
tempOffset = addUnicodeString(memBuffer, comps, tempOffset, "Item Class Type or Name");
|
||||
@@ -265,14 +256,13 @@ public class DialogResourceDataType extends DynamicDataType {
|
||||
}
|
||||
|
||||
//adds Item title array - 2nd after each DLGITEMTEMPLATE structure
|
||||
private int addItemTitleArray(MemBuffer memBuffer, List<DataTypeComponent> comps, int tempOffset)
|
||||
throws MemoryAccessException {
|
||||
private int addItemTitleArray(MemBuffer memBuffer, List<DataTypeComponent> comps,
|
||||
int tempOffset) throws MemoryAccessException {
|
||||
|
||||
short itemTitleInfo = memBuffer.getShort(tempOffset);
|
||||
if ((itemTitleInfo & 0xffff) == 0xffff) {
|
||||
tempOffset =
|
||||
addComp(createArrayOfShorts(2), 4, "Item Title or Resource ID",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
tempOffset = addComp(createArrayOfShorts(2), 4, "Item Title or Resource ID",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
}
|
||||
else {
|
||||
tempOffset =
|
||||
@@ -287,15 +277,13 @@ public class DialogResourceDataType extends DynamicDataType {
|
||||
|
||||
short itemDataLength = memBuffer.getShort(tempOffset);
|
||||
if (itemDataLength == 0x0000) {
|
||||
tempOffset =
|
||||
addComp(createArrayOfShorts(1), 2, "Item Data",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
tempOffset = addComp(createArrayOfShorts(1), 2, "Item Data",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
}
|
||||
else {
|
||||
tempOffset =
|
||||
addComp(new ArrayDataType(ByteDataType.dataType, itemDataLength, 1),
|
||||
itemDataLength, "Item Data", memBuffer.getAddress().add(tempOffset), comps,
|
||||
tempOffset);
|
||||
addComp(new ArrayDataType(ByteDataType.dataType, itemDataLength, 1), itemDataLength,
|
||||
"Item Data", memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
}
|
||||
return tempOffset;
|
||||
}
|
||||
@@ -303,154 +291,56 @@ public class DialogResourceDataType extends DynamicDataType {
|
||||
//This is always the first structure in the dialog resource
|
||||
private StructureDataType dlgTemplateExStructure() {
|
||||
StructureDataType struct = new StructureDataType("DLGTEMPLATEEX", 0);
|
||||
|
||||
struct.add(WordDataType.dataType);
|
||||
struct.add(WordDataType.dataType);
|
||||
struct.add(DWordDataType.dataType);
|
||||
struct.add(DWordDataType.dataType);
|
||||
struct.add(DWordDataType.dataType);
|
||||
struct.add(WordDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
|
||||
try {
|
||||
struct.getComponent(0).setFieldName("dlgVer");
|
||||
struct.getComponent(1).setFieldName("signature");
|
||||
struct.getComponent(2).setFieldName("helpId");
|
||||
struct.getComponent(3).setFieldName("exStyle");
|
||||
struct.getComponent(4).setFieldName("style");
|
||||
struct.getComponent(5).setFieldName("cDlgItems");
|
||||
struct.getComponent(6).setFieldName("x");
|
||||
struct.getComponent(7).setFieldName("y");
|
||||
struct.getComponent(8).setFieldName("cx");
|
||||
struct.getComponent(9).setFieldName("cy");
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Msg.debug(this, "Unexpected exception building DLGTEMPLATEEX", e);
|
||||
}
|
||||
struct.getComponent(0).setComment("version (must be 1)");
|
||||
struct.getComponent(1).setComment("signature (must be 0xffff)");
|
||||
struct.getComponent(2).setComment("help context identifier");
|
||||
struct.getComponent(3).setComment("extended styles for a window");
|
||||
struct.getComponent(4).setComment("style of dialog box");
|
||||
struct.getComponent(5).setComment("number of items in dialog box");
|
||||
struct.getComponent(6).setComment("x-coordinate of upper-left corner of dialog");
|
||||
struct.getComponent(7).setComment("y-coordinate of upper-left corner of dialog");
|
||||
struct.getComponent(8).setComment("width of dialog box");
|
||||
struct.getComponent(9).setComment("height of dialog box");
|
||||
|
||||
struct.add(WordDataType.dataType, "dlgVer", "version (must be 1)");
|
||||
struct.add(WordDataType.dataType, "signature", "signature (must be 0xffff)");
|
||||
struct.add(DWordDataType.dataType, "helpId", "help context identifier");
|
||||
struct.add(DWordDataType.dataType, "exStyle", "extended styles for a window");
|
||||
struct.add(DWordDataType.dataType, "style", "style of dialog box");
|
||||
struct.add(WordDataType.dataType, "cDlgItems", "number of items in dialog box");
|
||||
struct.add(ShortDataType.dataType, "x", "x-coordinate of upper-left corner of dialog");
|
||||
struct.add(ShortDataType.dataType, "y", "y-coordinate of upper-left corner of dialog");
|
||||
struct.add(ShortDataType.dataType, "cx", "width of dialog box");
|
||||
struct.add(ShortDataType.dataType, "cy", "height of dialog box");
|
||||
return struct;
|
||||
}
|
||||
|
||||
//This is always the first structure in the dialog resource
|
||||
private StructureDataType dlgTemplateStructure() {
|
||||
StructureDataType struct = new StructureDataType("DLGTEMPLATE", 0);
|
||||
|
||||
struct.add(DWordDataType.dataType);
|
||||
struct.add(DWordDataType.dataType);
|
||||
struct.add(WordDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
|
||||
try {
|
||||
struct.getComponent(0).setFieldName("style");
|
||||
struct.getComponent(1).setFieldName("dwExtendedStyle");
|
||||
struct.getComponent(2).setFieldName("cdit");
|
||||
struct.getComponent(3).setFieldName("x");
|
||||
struct.getComponent(4).setFieldName("y");
|
||||
struct.getComponent(5).setFieldName("cx");
|
||||
struct.getComponent(6).setFieldName("cy");
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Msg.debug(this, "Unexpected exception building DLGTEMPLATE", e);
|
||||
}
|
||||
struct.getComponent(0).setComment("style of dialog box");
|
||||
struct.getComponent(1).setComment("extended styles for a window");
|
||||
struct.getComponent(2).setComment("number of items in dialog box");
|
||||
struct.getComponent(3).setComment("x-coordinate of upper-left corner of dialog");
|
||||
struct.getComponent(4).setComment("y-coordinate of upper-left corner of dialog");
|
||||
struct.getComponent(5).setComment("width of dialog box");
|
||||
struct.getComponent(6).setComment("height of dialog box");
|
||||
|
||||
struct.add(DWordDataType.dataType, "style", "style of dialog box");
|
||||
struct.add(DWordDataType.dataType, "dwExtendedStyle", "extended styles for a window");
|
||||
struct.add(WordDataType.dataType, "cdit", "number of items in dialog box");
|
||||
struct.add(ShortDataType.dataType, "x", "x-coordinate of upper-left corner of dialog");
|
||||
struct.add(ShortDataType.dataType, "y", "y-coordinate of upper-left corner of dialog");
|
||||
struct.add(ShortDataType.dataType, "cx", "width of dialog box");
|
||||
struct.add(ShortDataType.dataType, "cy", "height of dialog box");
|
||||
return struct;
|
||||
}
|
||||
|
||||
//Each control item has one of these structures
|
||||
private StructureDataType dlgItemTemplateExStructure() {
|
||||
StructureDataType struct = new StructureDataType("DLGITEMTEMPLATEEX", 0);
|
||||
|
||||
try {
|
||||
struct.add(DWordDataType.dataType);
|
||||
struct.add(DWordDataType.dataType);
|
||||
struct.add(DWordDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(DWordDataType.dataType);
|
||||
|
||||
struct.getComponent(0).setFieldName("helpID");
|
||||
struct.getComponent(1).setFieldName("exStyle");
|
||||
struct.getComponent(2).setFieldName("style");
|
||||
struct.getComponent(3).setFieldName("x");
|
||||
struct.getComponent(4).setFieldName("y");
|
||||
struct.getComponent(5).setFieldName("cx");
|
||||
struct.getComponent(6).setFieldName("cy");
|
||||
struct.getComponent(7).setFieldName("id");
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Msg.debug(this, "Unexpected exception building DLGITEMTEMPLATEEX", e);
|
||||
}
|
||||
|
||||
struct.getComponent(0).setComment("help context identifier");
|
||||
struct.getComponent(1).setComment("extended styles for a window");
|
||||
struct.getComponent(2).setComment("style of control");
|
||||
struct.getComponent(3).setComment("x-coordinate of upper-left corner of control");
|
||||
struct.getComponent(4).setComment("y-coordinate of upper-left corner of control");
|
||||
struct.getComponent(5).setComment("width of control");
|
||||
struct.getComponent(6).setComment("height of control");
|
||||
struct.getComponent(7).setComment("control identifier");
|
||||
|
||||
struct.add(DWordDataType.dataType, "helpID", "help context identifier");
|
||||
struct.add(DWordDataType.dataType, "exStyle", "extended styles for a window");
|
||||
struct.add(DWordDataType.dataType, "style", "style of control");
|
||||
struct.add(ShortDataType.dataType, "x", "x-coordinate of upper-left corner of control");
|
||||
struct.add(ShortDataType.dataType, "y", "y-coordinate of upper-left corner of control");
|
||||
struct.add(ShortDataType.dataType, "cx", "width of control");
|
||||
struct.add(ShortDataType.dataType, "cy", "height of control");
|
||||
struct.add(DWordDataType.dataType, "id", "control identifier");
|
||||
return struct;
|
||||
}
|
||||
|
||||
//Each control item has one of these structures
|
||||
private StructureDataType dlgItemTemplateStructure() {
|
||||
StructureDataType struct = new StructureDataType("DLGITEMTEMPLATE", 0);
|
||||
|
||||
try {
|
||||
struct.add(DWordDataType.dataType);
|
||||
struct.add(DWordDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(ShortDataType.dataType);
|
||||
struct.add(WordDataType.dataType);
|
||||
|
||||
struct.getComponent(0).setFieldName("style");
|
||||
struct.getComponent(1).setFieldName("dwExtendedStyle");
|
||||
struct.getComponent(2).setFieldName("x");
|
||||
struct.getComponent(3).setFieldName("y");
|
||||
struct.getComponent(4).setFieldName("cx");
|
||||
struct.getComponent(5).setFieldName("cy");
|
||||
struct.getComponent(6).setFieldName("id");
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Msg.debug(this, "Unexpected exception building DLGITEMTEMPLATE", e);
|
||||
}
|
||||
|
||||
struct.getComponent(0).setComment("style of control");
|
||||
struct.getComponent(1).setComment("extended styles for a window");
|
||||
struct.getComponent(2).setComment("x-coordinate of upper-left corner of control");
|
||||
struct.getComponent(3).setComment("y-coordinate of upper-left corner of control");
|
||||
struct.getComponent(4).setComment("width of control");
|
||||
struct.getComponent(5).setComment("height of control");
|
||||
struct.getComponent(6).setComment("control identifier");
|
||||
|
||||
struct.add(DWordDataType.dataType, "style", "style of dialog box");
|
||||
struct.add(DWordDataType.dataType, "dwExtendedStyle", "extended styles for a window");
|
||||
struct.add(ShortDataType.dataType, "x", "x-coordinate of upper-left corner of control");
|
||||
struct.add(ShortDataType.dataType, "y", "y-coordinate of upper-left corner of control");
|
||||
struct.add(ShortDataType.dataType, "cx", "width of control");
|
||||
struct.add(ShortDataType.dataType, "cy", "height of control");
|
||||
struct.add(DWordDataType.dataType, "id", "control identifier");
|
||||
return struct;
|
||||
}
|
||||
|
||||
@@ -459,16 +349,15 @@ public class DialogResourceDataType extends DynamicDataType {
|
||||
return itemTypeMap.get(value);
|
||||
}
|
||||
|
||||
private int addUnicodeString(MemBuffer memBuffer, List<DataTypeComponent> comps,
|
||||
int tempOffset, String title) {
|
||||
private int addUnicodeString(MemBuffer memBuffer, List<DataTypeComponent> comps, int tempOffset,
|
||||
String title) {
|
||||
|
||||
byte[] tempBytes = new byte[1024];
|
||||
memBuffer.getBytes(tempBytes, tempOffset);
|
||||
int strLength = findUnicodeLength(tempBytes);
|
||||
if (strLength >= 2) {
|
||||
tempOffset =
|
||||
addComp(UnicodeDataType.dataType, strLength, title,
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
tempOffset = addComp(UnicodeDataType.dataType, strLength, title,
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
}
|
||||
|
||||
return tempOffset;
|
||||
@@ -495,9 +384,8 @@ public class DialogResourceDataType extends DynamicDataType {
|
||||
private int addComp(DataType dataType, int len, String fieldName, Address address,
|
||||
List<DataTypeComponent> comps, int currentOffset) {
|
||||
if (len > 0) {
|
||||
ReadOnlyDataTypeComponent readOnlyDataTypeComponent =
|
||||
new ReadOnlyDataTypeComponent(dataType, this, len, comps.size(), currentOffset,
|
||||
fieldName, null);
|
||||
ReadOnlyDataTypeComponent readOnlyDataTypeComponent = new ReadOnlyDataTypeComponent(
|
||||
dataType, this, len, comps.size(), currentOffset, fieldName, null);
|
||||
comps.add(readOnlyDataTypeComponent);
|
||||
currentOffset += len;
|
||||
}
|
||||
|
||||
+18
-37
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -131,9 +131,8 @@ public class MenuResourceDataType extends DynamicDataType {
|
||||
}
|
||||
|
||||
//once verified as valid, lay down the initial structure
|
||||
tempOffset =
|
||||
addComp(menuItemTemplateHeaderStructure(), 4, "Menu Item Template Header Structure",
|
||||
memBuffer.getAddress(), comps, tempOffset);
|
||||
tempOffset = addComp(menuItemTemplateHeaderStructure(), 4,
|
||||
"Menu Item Template Header Structure", memBuffer.getAddress(), comps, tempOffset);
|
||||
|
||||
return tempOffset;
|
||||
}
|
||||
@@ -141,21 +140,8 @@ public class MenuResourceDataType extends DynamicDataType {
|
||||
//This is always the first structure in the menu resource
|
||||
private StructureDataType menuItemTemplateHeaderStructure() {
|
||||
StructureDataType struct = new StructureDataType("MENUITEM_TEMPLATE_HEADER", 0);
|
||||
|
||||
struct.add(WordDataType.dataType);
|
||||
struct.add(WordDataType.dataType);
|
||||
|
||||
try {
|
||||
struct.getComponent(0).setFieldName("versionNumber");
|
||||
struct.getComponent(1).setFieldName("offset");
|
||||
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Msg.debug(this, "Unexpected exception building MENUITEM_TEMPLATE_HEADER", e);
|
||||
}
|
||||
struct.getComponent(0).setComment("Version number of menu");
|
||||
struct.getComponent(1).setComment("Menu items offset.");
|
||||
|
||||
struct.add(WordDataType.dataType, "versionNumber", "Version number of menu");
|
||||
struct.add(WordDataType.dataType, "offset", "Menu items offset.");
|
||||
return struct;
|
||||
}
|
||||
|
||||
@@ -165,19 +151,16 @@ public class MenuResourceDataType extends DynamicDataType {
|
||||
|
||||
//If it is a popup there is only an option field, no ID field
|
||||
if ((mtOption & MF_POPUP) == MF_POPUP) {
|
||||
tempOffset =
|
||||
addComp(WordDataType.dataType, 2, "mtOption", memBuffer.getAddress(), comps,
|
||||
tempOffset);
|
||||
tempOffset = addComp(WordDataType.dataType, 2, "mtOption", memBuffer.getAddress(),
|
||||
comps, tempOffset);
|
||||
}
|
||||
//If it is anything else it has option and id fields
|
||||
else {
|
||||
tempOffset =
|
||||
addComp(WordDataType.dataType, 2, "mtOption", memBuffer.getAddress(), comps,
|
||||
tempOffset);
|
||||
tempOffset = addComp(WordDataType.dataType, 2, "mtOption", memBuffer.getAddress(),
|
||||
comps, tempOffset);
|
||||
|
||||
tempOffset =
|
||||
addComp(WordDataType.dataType, 2, "mtID", memBuffer.getAddress().add(tempOffset),
|
||||
comps, tempOffset);
|
||||
tempOffset = addComp(WordDataType.dataType, 2, "mtID",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
|
||||
}
|
||||
|
||||
@@ -189,25 +172,23 @@ public class MenuResourceDataType extends DynamicDataType {
|
||||
private int addComp(DataType dataType, int len, String fieldName, Address address,
|
||||
List<DataTypeComponent> comps, int currentOffset) {
|
||||
if (len > 0) {
|
||||
ReadOnlyDataTypeComponent readOnlyDataTypeComponent =
|
||||
new ReadOnlyDataTypeComponent(dataType, this, len, comps.size(), currentOffset,
|
||||
fieldName, null);
|
||||
ReadOnlyDataTypeComponent readOnlyDataTypeComponent = new ReadOnlyDataTypeComponent(
|
||||
dataType, this, len, comps.size(), currentOffset, fieldName, null);
|
||||
comps.add(readOnlyDataTypeComponent);
|
||||
currentOffset += len;
|
||||
}
|
||||
return currentOffset;
|
||||
}
|
||||
|
||||
private int addUnicodeString(MemBuffer memBuffer, List<DataTypeComponent> comps,
|
||||
int tempOffset, String title) {
|
||||
private int addUnicodeString(MemBuffer memBuffer, List<DataTypeComponent> comps, int tempOffset,
|
||||
String title) {
|
||||
|
||||
byte[] tempBytes = new byte[1024];
|
||||
memBuffer.getBytes(tempBytes, tempOffset);
|
||||
int strLength = findUnicodeLength(tempBytes);
|
||||
if (strLength >= 2) {
|
||||
tempOffset =
|
||||
addComp(UnicodeDataType.dataType, strLength, title,
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
tempOffset = addComp(UnicodeDataType.dataType, strLength, title,
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
return tempOffset;
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -101,8 +101,9 @@ public class ReadOnlyDataTypeComponent implements DataTypeComponent, Serializabl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComment(String comment) {
|
||||
public DataTypeComponent setComment(String comment) {
|
||||
// ignore - read-only
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -114,8 +115,9 @@ public class ReadOnlyDataTypeComponent implements DataTypeComponent, Serializabl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFieldName(String fieldName) throws DuplicateNameException {
|
||||
public DataTypeComponent setFieldName(String fieldName) {
|
||||
// ignore - read-only
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+16
-8
@@ -162,7 +162,8 @@ public interface Structure extends Composite {
|
||||
* @param baseDataType the bitfield base datatype (certain restrictions apply).
|
||||
* @param bitSize the declared bitfield size in bits. The effective bit size may be adjusted
|
||||
* based upon the specified baseDataType.
|
||||
* @param componentName the field name to associate with this component.
|
||||
* @param componentName the field name to associate with this component. (may be null)
|
||||
* The name may be sanitized to convert all whitespace characters to an underscore.
|
||||
* @param comment the comment to associate with this component.
|
||||
* @return the bitfield component created whose associated data type will be BitFieldDataType.
|
||||
* @throws InvalidDataTypeException if the specified baseDataType is not a valid base type for
|
||||
@@ -206,7 +207,8 @@ public interface Structure extends Composite {
|
||||
* viewed as big-endian. The final offset may be reduced based upon the minimal
|
||||
* storage size determined during insertion.
|
||||
* @param baseDataType the bitfield base datatype (certain restrictions apply).
|
||||
* @param componentName the field name to associate with this component.
|
||||
* @param componentName the field name to associate with this component. (may be null)
|
||||
* The name may be sanitized to convert all whitespace characters to an underscore.
|
||||
* @param bitSize the bitfield size in bits. A bitSize of 0 may be specified although its name
|
||||
* will be ignored.
|
||||
* @param comment the comment to associate with this component.
|
||||
@@ -257,7 +259,8 @@ public interface Structure extends Composite {
|
||||
* structure an {@link Undefined1DataType} will be used in its place.
|
||||
* @param length the length to associate with the dataType. For fixed length types a length
|
||||
* <= 0 will use the length of the resolved dataType.
|
||||
* @param name the field name to associate with this component.
|
||||
* @param componentName the field name to associate with this component. (may be null)
|
||||
* The name may be sanitized to convert all whitespace characters to an underscore.
|
||||
* @param comment the comment to associate with this component.
|
||||
* @return the componentDataType created.
|
||||
* @throws IllegalArgumentException if the specified data type is not allowed to be inserted
|
||||
@@ -265,7 +268,8 @@ public interface Structure extends Composite {
|
||||
* suppose dt1 contains dt2. Therefore it is not valid to insert dt1 to dt2 since
|
||||
* this would cause a cyclic dependency.
|
||||
*/
|
||||
public DataTypeComponent insertAtOffset(int offset, DataType dataType, int length, String name,
|
||||
public DataTypeComponent insertAtOffset(int offset, DataType dataType, int length,
|
||||
String componentName,
|
||||
String comment) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
@@ -383,14 +387,16 @@ public interface Structure extends Composite {
|
||||
* @param length component length for containing the specified dataType. A positive length is required
|
||||
* for sizable {@link Dynamic} datatypes and should be specified as -1 for fixed-length
|
||||
* datatypes to rely on their resolved size.
|
||||
* @param name the field name to associate with this component or null.
|
||||
* @param componentName the field name to associate with this component. (may be null)
|
||||
* The name may be sanitized to convert all whitespace characters to an underscore.
|
||||
* @param comment the comment to associate with this component or null.
|
||||
* @return the new component.
|
||||
* @throws IllegalArgumentException may be caused by: 1) invalid offset specified, 2) invalid datatype or
|
||||
* associated length specified, or 3) insufficient space for replacement.
|
||||
* @throws IndexOutOfBoundsException if component ordinal is out of bounds
|
||||
*/
|
||||
public DataTypeComponent replace(int ordinal, DataType dataType, int length, String name,
|
||||
public DataTypeComponent replace(int ordinal, DataType dataType, int length,
|
||||
String componentName,
|
||||
String comment) throws IndexOutOfBoundsException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
@@ -428,13 +434,15 @@ public interface Structure extends Composite {
|
||||
* @param length component length for containing the specified dataType. A positive length is required
|
||||
* for sizable {@link Dynamic} datatypes and should be specified as -1 for fixed-length
|
||||
* datatypes to rely on their resolved size.
|
||||
* @param name the field name to associate with this component or null.
|
||||
* @param componentName the field name to associate with this component. (may be null)
|
||||
* The name may be sanitized to convert all whitespace characters to an underscore.
|
||||
* @param comment the comment to associate with this component or null.
|
||||
* @return the new component.
|
||||
* @throws IllegalArgumentException may be caused by: 1) invalid offset specified, 2) invalid datatype or
|
||||
* associated length specified, or 3) insufficient space for replacement.
|
||||
*/
|
||||
public DataTypeComponent replaceAtOffset(int offset, DataType dataType, int length, String name,
|
||||
public DataTypeComponent replaceAtOffset(int offset, DataType dataType, int length,
|
||||
String componentName,
|
||||
String comment) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
|
||||
+46
-20
@@ -16,6 +16,7 @@
|
||||
package ghidra.program.model.data;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.program.database.data.DataTypeUtilities;
|
||||
@@ -26,13 +27,8 @@ import ghidra.util.exception.AssertException;
|
||||
|
||||
/**
|
||||
* Basic implementation of the structure data type.
|
||||
* NOTES:
|
||||
* <ul>
|
||||
* <li>Implementation is not thread safe when being modified.</li>
|
||||
* <li>For a structure to treated as having a zero-length (see {@link #isZeroLength()}) it </li>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* NOTE: Implementation is not thread safe.
|
||||
*/
|
||||
public class StructureDataType extends CompositeDataTypeImpl implements StructureInternal {
|
||||
|
||||
@@ -386,6 +382,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
}
|
||||
}
|
||||
if (nextOrdinal != null && nextOrdinal == ordinal) {
|
||||
|
||||
// defined component removed
|
||||
if (dtc.isBitFieldComponent()) {
|
||||
// defer reconciling bitfield space to repack
|
||||
@@ -394,12 +391,13 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
else {
|
||||
offsetAdjustment -= dtc.getLength();
|
||||
}
|
||||
dtc.getDataType().removeParent(this);
|
||||
|
||||
--ordinalAdjustment;
|
||||
lastDefinedOrdinal = ordinal;
|
||||
nextOrdinal = sortedOrdinals.higher(ordinal);
|
||||
}
|
||||
else {
|
||||
|
||||
if (ordinalAdjustment != 0) {
|
||||
shiftOffset(dtc, ordinalAdjustment, offsetAdjustment);
|
||||
}
|
||||
@@ -565,11 +563,14 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
return new DataTypeComponentImpl(DataType.DEFAULT, this, 1, ordinal, offset);
|
||||
}
|
||||
|
||||
DataTypeComponentImpl dtc = new DataTypeComponentImpl(dataType, this, length, ordinal,
|
||||
length = getPreferredComponentLength(dataType, length);
|
||||
|
||||
DataTypeComponentImpl dtc = createComponent(dataType, length, ordinal,
|
||||
offset, componentName, comment);
|
||||
dataType.addParent(this);
|
||||
shiftOffsets(index, 1 + additionalShift, length + additionalShift);
|
||||
components.add(index, dtc);
|
||||
|
||||
repack(false);
|
||||
notifySizeChanged();
|
||||
return dtc;
|
||||
@@ -622,12 +623,12 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
|
||||
DataTypeComponentImpl dtc;
|
||||
if (dataType == DataType.DEFAULT) {
|
||||
// assume non-packed structure - structre will grow by 1-byte below
|
||||
// assume non-packed structure - will grow by 1-byte below
|
||||
dtc = new DataTypeComponentImpl(DataType.DEFAULT, this, 1, numComponents, structLength);
|
||||
}
|
||||
else {
|
||||
int componentLength = getPreferredComponentLength(dataType, length);
|
||||
dtc = new DataTypeComponentImpl(dataType, this, componentLength, numComponents,
|
||||
dtc = createComponent(dataType, componentLength, numComponents,
|
||||
structLength, componentName, comment);
|
||||
dataType.addParent(this);
|
||||
components.add(dtc);
|
||||
@@ -667,9 +668,14 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
}
|
||||
else {
|
||||
index = backupToFirstComponentContainingOffset(index, len);
|
||||
index = afterNonZeroComponentsAtOffset(index, len);
|
||||
}
|
||||
int definedComponentCount = components.size();
|
||||
if (index >= 0 && index < definedComponentCount) {
|
||||
// Process deleted components
|
||||
components.subList(index, components.size()).forEach(dtc -> {
|
||||
dtc.getDataType().removeParent(this);
|
||||
});
|
||||
components = components.subList(0, index);
|
||||
}
|
||||
}
|
||||
@@ -743,11 +749,12 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
length = getPreferredComponentLength(dataType, length);
|
||||
|
||||
int offset = (getComponent(ordinal)).getOffset();
|
||||
DataTypeComponentImpl dtc = new DataTypeComponentImpl(dataType, this, length, ordinal,
|
||||
DataTypeComponentImpl dtc = createComponent(dataType, length, ordinal,
|
||||
offset, componentName, comment);
|
||||
dataType.addParent(this);
|
||||
shiftOffsets(idx, 1, dtc.getLength());
|
||||
components.add(idx, dtc);
|
||||
|
||||
repack(false);
|
||||
notifySizeChanged();
|
||||
return dtc;
|
||||
@@ -901,11 +908,11 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
|
||||
BitFieldDataType bitfieldDt = new BitFieldDataType(baseDataType, bitSize, storageBitOffset);
|
||||
|
||||
DataTypeComponentImpl dtc = new DataTypeComponentImpl(bitfieldDt, this,
|
||||
DataTypeComponentImpl dtc = createComponent(bitfieldDt,
|
||||
bitfieldDt.getStorageSize(), ordinal, revisedOffset, componentName, comment);
|
||||
bitfieldDt.addParent(this); // currently has no affect
|
||||
|
||||
components.add(startIndex, dtc);
|
||||
|
||||
adjustNonPackedComponents();
|
||||
notifySizeChanged();
|
||||
return dtc;
|
||||
@@ -1259,6 +1266,9 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
/**
|
||||
* Replaces the internal components of this structure with components of the given structure
|
||||
* including packing and alignment settings.
|
||||
* <p>
|
||||
* NOTE: unlike adding new components which will guarantee component name uniqueness, this
|
||||
* method will preserve component names.
|
||||
*
|
||||
* @param dataType the structure to get the component information from.
|
||||
* @throws IllegalArgumentException if any of the component data types are not allowed to
|
||||
@@ -1274,6 +1284,12 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// Remove all existing components
|
||||
for (DataTypeComponentImpl dtc : components) {
|
||||
dtc.getDataType().removeParent(this);
|
||||
}
|
||||
|
||||
components.clear();
|
||||
numComponents = 0;
|
||||
structLength = 0;
|
||||
@@ -1341,8 +1357,11 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
length = getPreferredComponentLength(dt, -1, maxLength);
|
||||
}
|
||||
|
||||
components.add(new DataTypeComponentImpl(dt, this, length, dtc.getOrdinal(),
|
||||
dtc.getOffset(), dtc.getFieldName(), dtc.getComment()));
|
||||
// Note: original component name is preserved
|
||||
DataTypeComponentImpl newDtc = createComponent(dt, length, dtc.getOrdinal(),
|
||||
dtc.getOffset(), dtc.getFieldName(), dtc.getComment());
|
||||
dt.addParent(this);
|
||||
components.add(newDtc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1431,7 +1450,12 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
|
||||
@Override
|
||||
public DataTypeComponent[] getDefinedComponents() {
|
||||
return components.toArray(new DataTypeComponent[components.size()]);
|
||||
return components.toArray(new DataTypeComponentImpl[components.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
void forEachDefinedComponent(Consumer<DataTypeComponentImpl> dtcConsumer) {
|
||||
components.forEach(dtcConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1481,7 +1505,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataTypeComponent replace(int index, DataType dataType, int length) {
|
||||
public final DataTypeComponent replace(int index, DataType dataType, int length)
|
||||
throws IndexOutOfBoundsException, IllegalArgumentException {
|
||||
return replace(index, dataType, length, null, null);
|
||||
}
|
||||
|
||||
@@ -1792,9 +1817,10 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
DataTypeComponentImpl newDtc = null;
|
||||
if (!clearOnly) {
|
||||
// insert new component
|
||||
newDtc = new DataTypeComponentImpl(dataType, this, length, newOrdinal, newOffset,
|
||||
fieldName, comment);
|
||||
newDtc =
|
||||
createComponent(dataType, length, newOrdinal, newOffset, fieldName, comment);
|
||||
components.add(index, newDtc);
|
||||
dataType.addParent(this);
|
||||
}
|
||||
|
||||
// adjust ordinals of trailing components - defer if packing is enabled
|
||||
|
||||
+4
-3
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -37,7 +37,8 @@ public interface Union extends Composite {
|
||||
* @param baseDataType the bitfield base datatype (certain restrictions apply).
|
||||
* @param bitSize the declared bitfield size in bits. The effective bit size may be
|
||||
* adjusted based upon the specified baseDataType.
|
||||
* @param componentName the field name to associate with this component.
|
||||
* @param componentName the field name to associate with this component. (may be null)
|
||||
* The name may be sanitized to convert all whitespace characters to an underscore.
|
||||
* @param comment the comment to associate with this component.
|
||||
* @return the bitfield component created whose associated data type will
|
||||
* be BitFieldDataType.
|
||||
|
||||
+15
-5
@@ -16,6 +16,7 @@
|
||||
package ghidra.program.model.data;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.program.database.data.DataTypeUtilities;
|
||||
@@ -24,7 +25,8 @@ import ghidra.util.UniversalID;
|
||||
|
||||
/**
|
||||
* Basic implementation of the union data type.
|
||||
* NOTE: Implementation is not thread safe when being modified.
|
||||
* <p>
|
||||
* NOTE: Implementation is not thread safe.
|
||||
*/
|
||||
public class UnionDataType extends CompositeDataTypeImpl implements UnionInternal {
|
||||
|
||||
@@ -116,6 +118,11 @@ public class UnionDataType extends CompositeDataTypeImpl implements UnionInterna
|
||||
return getComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
void forEachDefinedComponent(Consumer<DataTypeComponentImpl> dtcConsumer) {
|
||||
components.forEach(dtcConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumComponents() {
|
||||
return components.size();
|
||||
@@ -134,6 +141,7 @@ public class UnionDataType extends CompositeDataTypeImpl implements UnionInterna
|
||||
int oldAlignment = getAlignment();
|
||||
|
||||
DataTypeComponent dtc = doAdd(dataType, length, componentName, comment);
|
||||
|
||||
if (!repack(true) && isPackingEnabled() && oldAlignment != getAlignment()) {
|
||||
notifyAlignmentChanged();
|
||||
}
|
||||
@@ -163,8 +171,8 @@ public class UnionDataType extends CompositeDataTypeImpl implements UnionInterna
|
||||
return length;
|
||||
}
|
||||
|
||||
DataTypeComponentImpl doAdd(DataType dataType, int length, String componentName, String comment)
|
||||
throws DataTypeDependencyException {
|
||||
DataTypeComponentImpl doAdd(DataType dataType, int length, String componentName,
|
||||
String comment) throws DataTypeDependencyException {
|
||||
|
||||
dataType = validateDataType(dataType);
|
||||
|
||||
@@ -175,8 +183,9 @@ public class UnionDataType extends CompositeDataTypeImpl implements UnionInterna
|
||||
|
||||
length = getPreferredComponentLength(dataType, length);
|
||||
|
||||
DataTypeComponentImpl dtc = new DataTypeComponentImpl(dataType, this, length,
|
||||
DataTypeComponentImpl dtc = createComponent(dataType, length,
|
||||
components.size(), 0, componentName, comment);
|
||||
|
||||
dataType.addParent(this);
|
||||
components.add(dtc);
|
||||
|
||||
@@ -198,7 +207,7 @@ public class UnionDataType extends CompositeDataTypeImpl implements UnionInterna
|
||||
|
||||
length = getPreferredComponentLength(dataType, length);
|
||||
|
||||
DataTypeComponentImpl dtc = new DataTypeComponentImpl(dataType, this, length, ordinal,
|
||||
DataTypeComponentImpl dtc = createComponent(dataType, length, ordinal,
|
||||
0, componentName, comment);
|
||||
dataType.addParent(this);
|
||||
shiftOrdinals(ordinal, 1);
|
||||
@@ -311,6 +320,7 @@ public class UnionDataType extends CompositeDataTypeImpl implements UnionInterna
|
||||
if (ordinals.contains(ordinal)) {
|
||||
// component removed
|
||||
--ordinalAdjustment;
|
||||
dtc.getDataType().removeParent(this);
|
||||
}
|
||||
else {
|
||||
if (ordinalAdjustment != 0) {
|
||||
|
||||
+51
-2
@@ -134,6 +134,7 @@ public class StructureDBTest extends AbstractGenericTest {
|
||||
assertEquals("field1", dtc.getFieldName());
|
||||
assertEquals("Comment1", dtc.getComment());
|
||||
assertEquals(ByteDataType.class, dtc.getDataType().getClass());
|
||||
assertEquals(dtc, struct.findComponent("field1"));
|
||||
|
||||
dtc = struct.getComponent(1);
|
||||
assertEquals(1, dtc.getOffset());
|
||||
@@ -148,6 +149,7 @@ public class StructureDBTest extends AbstractGenericTest {
|
||||
assertEquals("field3", dtc.getFieldName());
|
||||
assertEquals(null, dtc.getComment());
|
||||
assertEquals(DWordDataType.class, dtc.getDataType().getClass());
|
||||
assertEquals(dtc, struct.findComponent("field3"));
|
||||
|
||||
dtc = struct.getComponent(3);
|
||||
assertEquals(7, dtc.getOffset());
|
||||
@@ -155,7 +157,23 @@ public class StructureDBTest extends AbstractGenericTest {
|
||||
assertEquals("field4", dtc.getFieldName());
|
||||
assertEquals("Comment4", dtc.getComment());
|
||||
assertEquals(ByteDataType.class, dtc.getDataType().getClass());
|
||||
assertEquals(dtc, struct.findComponent("field4"));
|
||||
|
||||
dtc = struct.add(ByteDataType.dataType, "field3", "new comment");
|
||||
assertEquals(8, dtc.getOffset());
|
||||
assertEquals(4, dtc.getOrdinal());
|
||||
assertEquals("field3", dtc.getFieldName());
|
||||
assertEquals("new comment", dtc.getComment());
|
||||
assertEquals(ByteDataType.class, dtc.getDataType().getClass());
|
||||
assertNotNull(struct.findComponent("field3")); // which one is returned is arbitrary
|
||||
|
||||
dtc = struct.add(ByteDataType.dataType, "field3 1", "new comment"); // cleanup required
|
||||
assertEquals(9, dtc.getOffset());
|
||||
assertEquals(5, dtc.getOrdinal());
|
||||
assertEquals("field3_1", dtc.getFieldName());
|
||||
assertEquals("new comment", dtc.getComment());
|
||||
assertEquals(ByteDataType.class, dtc.getDataType().getClass());
|
||||
assertEquals(dtc, struct.findComponent("field3_1")); // name gets modified
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1869,7 +1887,7 @@ public class StructureDBTest extends AbstractGenericTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelete() throws InvalidDataTypeException {
|
||||
public void testDeleteBF() throws InvalidDataTypeException {
|
||||
|
||||
struct.insertBitFieldAt(2, 4, 0, IntegerDataType.dataType, 3, "bf1", "bf1Comment");
|
||||
struct.insertBitFieldAt(2, 4, 3, IntegerDataType.dataType, 3, "bf2", "bf2Comment");
|
||||
@@ -1911,8 +1929,12 @@ public class StructureDBTest extends AbstractGenericTest {
|
||||
"Length: 11 Alignment: 1", struct);
|
||||
//@formatter:on
|
||||
|
||||
assertNotNull(struct.findComponent("bf2"));
|
||||
|
||||
struct.delete(3);
|
||||
|
||||
assertNull(struct.findComponent("bf2"));
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Test\n" +
|
||||
"pack(disabled)\n" +
|
||||
@@ -1928,8 +1950,12 @@ public class StructureDBTest extends AbstractGenericTest {
|
||||
"Length: 11 Alignment: 1", struct);
|
||||
//@formatter:on
|
||||
|
||||
assertNotNull(struct.findComponent("bf3"));
|
||||
|
||||
struct.delete(3);
|
||||
|
||||
assertNull(struct.findComponent("bf3"));
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Test\n" +
|
||||
"pack(disabled)\n" +
|
||||
@@ -1945,8 +1971,12 @@ public class StructureDBTest extends AbstractGenericTest {
|
||||
"Length: 11 Alignment: 1", struct);
|
||||
//@formatter:on
|
||||
|
||||
assertNotNull(struct.findComponent("bf4"));
|
||||
|
||||
struct.delete(4);
|
||||
|
||||
assertNull(struct.findComponent("bf4"));
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Test\n" +
|
||||
"pack(disabled)\n" +
|
||||
@@ -1963,8 +1993,12 @@ public class StructureDBTest extends AbstractGenericTest {
|
||||
"Length: 11 Alignment: 1", struct);
|
||||
//@formatter:on
|
||||
|
||||
assertNotNull(struct.findComponent("bf1"));
|
||||
|
||||
struct.delete(2);
|
||||
|
||||
assertNull(struct.findComponent("bf1"));
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Test\n" +
|
||||
"pack(disabled)\n" +
|
||||
@@ -2092,7 +2126,7 @@ public class StructureDBTest extends AbstractGenericTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteComponent() {
|
||||
public void testDataTypeDeleted() {
|
||||
Structure s = new StructureDataType("test1", 0);
|
||||
s.add(new ByteDataType());
|
||||
s.add(new FloatDataType());
|
||||
@@ -2149,6 +2183,21 @@ public class StructureDBTest extends AbstractGenericTest {
|
||||
assertEquals(0, s.getNumComponents());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetComponentByName() {
|
||||
DataTypeComponent dtc = struct.findComponent("field1");
|
||||
assertNotNull(dtc);
|
||||
assertEquals("field1", dtc.getFieldName());
|
||||
|
||||
dtc = struct.findComponent("field3");
|
||||
assertNotNull(dtc);
|
||||
assertEquals("field3", dtc.getFieldName());
|
||||
|
||||
dtc = struct.findComponent("field4");
|
||||
assertNotNull(dtc);
|
||||
assertEquals("field4", dtc.getFieldName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetComponentAt() {
|
||||
/**
|
||||
|
||||
+59
@@ -745,4 +745,63 @@ public class UnionDBTest extends AbstractGenericTest {
|
||||
"Should be able to insert a union typedef array pointer into the pointer's union.");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldNameWhitespaceConvertedToUnderscores() {
|
||||
UnionDataType newUnion = new UnionDataType("Test");
|
||||
DataTypeComponent component = newUnion.add(new ByteDataType(), " name with spaces", null);
|
||||
assertEquals("name_with_spaces", component.getFieldName());
|
||||
|
||||
union = (UnionDB) dataMgr.resolve(newUnion, null);
|
||||
|
||||
component = union.getComponent(0);
|
||||
component.setFieldName(" name in db with spaces ");
|
||||
assertEquals("name_in_db_with_spaces", component.getFieldName());
|
||||
|
||||
component = union.add(new ByteDataType(), " another test ", null);
|
||||
assertEquals("another_test", component.getFieldName());
|
||||
|
||||
union.insert(0, new ByteDataType(), 1, " insert test ", "");
|
||||
component = union.getComponent(0);
|
||||
assertEquals("insert_test", component.getFieldName());
|
||||
|
||||
union.insert(1, new ByteDataType(), 1, " insert test ", "");
|
||||
component = union.getComponent(1);
|
||||
assertEquals("insert_test", component.getFieldName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultFieldNames() {
|
||||
UnionDataType newUnion = new UnionDataType("Test");
|
||||
DataTypeComponent component = newUnion.add(new ByteDataType(), " ", null);
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field0", component.getDefaultFieldName());
|
||||
|
||||
union = (UnionDB) dataMgr.resolve(newUnion, null);
|
||||
|
||||
component = union.add(new ByteDataType(), null, null);
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field1", component.getDefaultFieldName());
|
||||
|
||||
component = union.getComponent(0);
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field0", component.getDefaultFieldName());
|
||||
|
||||
component.setFieldName(" ");
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field0", component.getDefaultFieldName());
|
||||
|
||||
component = union.add(new ByteDataType(), null, null);
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field2", component.getDefaultFieldName());
|
||||
|
||||
component = union.add(new ByteDataType(), " ", null);
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field3", component.getDefaultFieldName());
|
||||
|
||||
union.insert(0, new ByteDataType(), 1, null, "");
|
||||
component = union.getComponent(0);
|
||||
assertNull(component.getFieldName());
|
||||
assertEquals("field0", component.getDefaultFieldName());
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -77,7 +77,7 @@ public class CompositeTestUtils {
|
||||
if (mismatch) {
|
||||
Msg.error(test, "Expected composite:\n" + expectedDump);
|
||||
Msg.error(test, "Result composite:\n" + result);
|
||||
fail("Failed to parse expected composite (see log)");
|
||||
fail("Composite mismatch (see log)");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user