diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDB.java
index 8530215c53a..74eefed2e90 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDB.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDB.java
@@ -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.
@@ -345,6 +345,11 @@ protected void doSetNameRecord(String name) throws IOException {
compositeAdapter.updateRecord(record, true);
}
+ protected void removeComponentRecord(long compKey) throws IOException {
+ componentAdapter.removeRecord(compKey);
+ dataMgr.getSettingsAdapter().removeAllSettingsRecords(compKey);
+ }
+
/**
* This method throws an exception if the indicated data type is not a valid
* data type for a component of this composite data type. If the DEFAULT
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java
index 6b3f198815e..59ba1ec41e4 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java
@@ -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.
@@ -544,20 +544,29 @@ public void delete(int ordinal) {
}
/**
- * Removes a defined component at the specified index without any alteration to other components.
+ * 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.
* @param index defined component index
* @return the defined component which was removed.
* @throws IOException if an IO error occurs
*/
private DataTypeComponentDB doDelete(int index) throws IOException {
DataTypeComponentDB dtc = components.remove(index);
- dtc.getDataType().removeParent(this);
- long compKey = dtc.getKey();
- componentAdapter.removeRecord(compKey);
- dataMgr.getSettingsAdapter().removeAllSettingsRecords(compKey);
+ doDelete(dtc);
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.
*
@@ -587,38 +596,53 @@ private void doDeleteWithComponentShift(int index, boolean disableOffsetShift) {
@Override
public void delete(Set ordinals) {
+
+ if (ordinals.isEmpty()) {
+ return;
+ }
+
+ if (ordinals.size() == 1) {
+ ordinals.forEach(ordinal -> delete(ordinal));
+ return;
+ }
+
lock.acquire();
try {
checkDeleted();
- if (ordinals.isEmpty()) {
- return;
+ TreeSet sortedOrdinals = new TreeSet<>(ordinals);
+ int firstOrdinal = sortedOrdinals.first();
+ int lastOrdinal = sortedOrdinals.last();
+ if (firstOrdinal < 0 || lastOrdinal >= numComponents) {
+ throw new IndexOutOfBoundsException(ordinals.size() + " ordinals specified");
}
- boolean bitFieldRemoved = false;
-
- TreeSet treeSet = null;
- if (!isPackingEnabled()) {
- // treeSet only used to track undefined filler removal
- treeSet = new TreeSet<>(ordinals);
- }
+ Integer nextOrdinal = firstOrdinal;
- List newComponents = new ArrayList<>();
int ordinalAdjustment = 0;
int offsetAdjustment = 0;
int lastDefinedOrdinal = -1;
+
+ boolean isPacked = isPackingEnabled();
+
+ boolean bitFieldRemoved = false;
+
+ List newComponents = new ArrayList<>(components.size());
+
for (DataTypeComponentDB dtc : components) {
int ordinal = dtc.getOrdinal();
- if (treeSet != null && lastDefinedOrdinal < (ordinal - 1)) {
+ if (!isPacked && nextOrdinal != null && nextOrdinal < ordinal) {
// Identify removed filler since last defined component
- Set removedFillerSet = treeSet.subSet(lastDefinedOrdinal + 1, ordinal);
+ SortedSet removedFillerSet =
+ sortedOrdinals.subSet(lastDefinedOrdinal + 1, ordinal);
if (!removedFillerSet.isEmpty()) {
int undefinedRemoveCount = removedFillerSet.size();
ordinalAdjustment -= undefinedRemoveCount;
offsetAdjustment -= undefinedRemoveCount;
+ nextOrdinal = sortedOrdinals.higher(removedFillerSet.last());
}
}
- if (ordinals.contains(ordinal)) {
+ if (nextOrdinal != null && nextOrdinal == ordinal) {
// defined component removed
if (dtc.isBitFieldComponent()) {
// defer reconciling bitfield space to repack
@@ -627,8 +651,10 @@ public void delete(Set ordinals) {
else {
offsetAdjustment -= dtc.getLength();
}
+ doDelete(dtc); // delete defined component record
--ordinalAdjustment;
lastDefinedOrdinal = ordinal;
+ nextOrdinal = sortedOrdinals.higher(ordinal);
}
else {
if (ordinalAdjustment != 0) {
@@ -638,10 +664,10 @@ public void delete(Set ordinals) {
lastDefinedOrdinal = ordinal;
}
}
- if (treeSet != null) {
+ if (!isPacked) {
// Identify removed filler after last defined component
Set removedFillerSet =
- treeSet.subSet(lastDefinedOrdinal + 1, numComponents);
+ sortedOrdinals.subSet(lastDefinedOrdinal + 1, numComponents);
if (!removedFillerSet.isEmpty()) {
int undefinedRemoveCount = removedFillerSet.size();
ordinalAdjustment -= undefinedRemoveCount;
@@ -653,7 +679,7 @@ public void delete(Set ordinals) {
components = newComponents;
updateComposite(numComponents + ordinalAdjustment, -1, -1, true);
- if (isPackingEnabled()) {
+ if (isPacked) {
if (!repack(false, true)) {
dataMgr.dataTypeChanged(this, false);
}
@@ -667,6 +693,9 @@ public void delete(Set ordinals) {
notifySizeChanged(false);
}
}
+ catch (IOException e) {
+ dataMgr.dbError(e);
+ }
finally {
lock.release();
}
@@ -1684,9 +1713,9 @@ private void doReplaceWithPacked(Structure struct, DataType[] resolvedDts) {
private void doReplaceWithNonPacked(Structure struct, DataType[] resolvedDts)
throws IOException {
-
+
// caller responsible for record updates
-
+
// assumes components is clear and that alignment characteristics have been set.
if (struct.isNotYetDefined()) {
return;
@@ -2486,9 +2515,8 @@ private boolean updateComposite(int currentNumComponents, int currentLength,
record.setIntValue(CompositeDBAdapter.COMPOSITE_LENGTH_COL, structLength);
compositeChanged = true;
}
- if (currentAlignment >= 0 &&
- (currentAlignment != structAlignment || currentAlignment != record
- .getIntValue(CompositeDBAdapter.COMPOSITE_ALIGNMENT_COL))) {
+ if (currentAlignment >= 0 && (currentAlignment != structAlignment ||
+ currentAlignment != record.getIntValue(CompositeDBAdapter.COMPOSITE_ALIGNMENT_COL))) {
structAlignment = currentAlignment;
record.setIntValue(CompositeDBAdapter.COMPOSITE_ALIGNMENT_COL, structAlignment);
compositeChanged = true;
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/UnionDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/UnionDB.java
index eb989d4d09d..db0ffb23a2d 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/UnionDB.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/UnionDB.java
@@ -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.
@@ -159,16 +159,6 @@ private DataTypeComponentDB createComponent(long dtID, int length, int ordinal,
return null;
}
- private void removeComponent(long compKey) {
- try {
- componentAdapter.removeRecord(compKey);
- dataMgr.getSettingsAdapter().removeAllSettingsRecords(compKey);
- }
- catch (IOException e) {
- dataMgr.dbError(e);
- }
- }
-
@Override
public DataTypeComponent insert(int ordinal, DataType dataType, int length, String name,
String comment) throws IllegalArgumentException {
@@ -234,13 +224,16 @@ public void delete(int ordinal) {
DataTypeComponentDB dtc = components.remove(ordinal);
dtc.getDataType().removeParent(this);
- removeComponent(dtc.getKey());
+ removeComponentRecord(dtc.getKey());
shiftOrdinals(ordinal, -1);
if (!repack(false, true)) {
dataMgr.dataTypeChanged(this, false);
}
}
+ catch (IOException e) {
+ dataMgr.dbError(e);
+ }
finally {
lock.release();
}
@@ -248,10 +241,16 @@ public void delete(int ordinal) {
@Override
public void delete(Set ordinals) {
+
if (ordinals.isEmpty()) {
return;
}
+ if (ordinals.size() == 1) {
+ ordinals.forEach(ordinal -> delete(ordinal));
+ return;
+ }
+
lock.acquire();
try {
checkDeleted();
@@ -266,7 +265,9 @@ public void delete(Set ordinals) {
for (DataTypeComponentDB dtc : components) {
int ordinal = dtc.getOrdinal();
if (ordinals.contains(ordinal)) {
- // component removed
+ // component removed - delete record
+ dtc.getDataType().removeParent(this);
+ removeComponentRecord(dtc.getKey());
--ordinalAdjustment;
}
else {
@@ -285,10 +286,24 @@ public void delete(Set ordinals) {
}
}
else {
- unionLength = newLength;
- notifySizeChanged(false);
+ boolean sizeChanged = (unionLength != newLength);
+ if (sizeChanged) {
+ unionLength = newLength;
+ record.setIntValue(CompositeDBAdapter.COMPOSITE_LENGTH_COL, unionLength);
+ }
+ compositeAdapter.updateRecord(record, true);
+
+ if (sizeChanged) {
+ notifySizeChanged(false);
+ }
+ else {
+ dataMgr.dataTypeChanged(this, false);
+ }
}
}
+ catch (IOException e) {
+ dataMgr.dbError(e);
+ }
finally {
lock.release();
}
@@ -332,7 +347,7 @@ void doReplaceWith(UnionInternal union, boolean notify)
for (DataTypeComponentDB dtc : components) {
dtc.getDataType().removeParent(this);
- removeComponent(dtc.getKey());
+ removeComponentRecord(dtc.getKey());
}
components.clear();
unionAlignment = -1;
@@ -708,7 +723,7 @@ public void dataTypeDeleted(DataType dt) {
if (removeBitFieldComponent || dtc.getDataType() == dt) {
dt.removeParent(this);
components.remove(i);
- removeComponent(dtc.getKey());
+ removeComponentRecord(dtc.getKey());
shiftOrdinals(i, -1);
changed = true;
}
@@ -717,6 +732,9 @@ public void dataTypeDeleted(DataType dt) {
dataMgr.dataTypeChanged(this, false);
}
}
+ catch (IOException e) {
+ dataMgr.dbError(e);
+ }
finally {
lock.release();
}
@@ -853,7 +871,7 @@ else if (dtc.getDataType() == oldDt) {
if (remove) {
oldDt.removeParent(this);
components.remove(i);
- removeComponent(dtc.getKey());
+ removeComponentRecord(dtc.getKey());
shiftOrdinals(i, -1);
changed = true;
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureDataType.java
index 67202c20465..bc002ee434f 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureDataType.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureDataType.java
@@ -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.
@@ -348,30 +348,44 @@ public void delete(Set ordinals) {
return;
}
- boolean bitFieldRemoved = false;
+ if (ordinals.size() == 1) {
+ ordinals.forEach(ordinal -> delete(ordinal));
+ return;
+ }
- TreeSet treeSet = null;
- if (!isPackingEnabled()) {
- // treeSet only used to track undefined filler removal
- treeSet = new TreeSet<>(ordinals);
+ TreeSet sortedOrdinals = new TreeSet<>(ordinals);
+ int firstOrdinal = sortedOrdinals.first();
+ int lastOrdinal = sortedOrdinals.last();
+ if (firstOrdinal < 0 || lastOrdinal >= numComponents) {
+ throw new IndexOutOfBoundsException(ordinals.size() + " ordinals specified");
}
- List newComponents = new ArrayList<>();
+ Integer nextOrdinal = firstOrdinal;
+
int ordinalAdjustment = 0;
int offsetAdjustment = 0;
int lastDefinedOrdinal = -1;
+
+ boolean isPacked = isPackingEnabled();
+
+ boolean bitFieldRemoved = false;
+
+ List newComponents = new ArrayList<>(components.size());
+
for (DataTypeComponentImpl dtc : components) {
int ordinal = dtc.getOrdinal();
- if (treeSet != null && lastDefinedOrdinal < (ordinal - 1)) {
+ if (!isPacked && nextOrdinal != null && nextOrdinal < ordinal) {
// Identify removed filler since last defined component
- Set removedFillerSet = treeSet.subSet(lastDefinedOrdinal + 1, ordinal);
+ SortedSet removedFillerSet =
+ sortedOrdinals.subSet(lastDefinedOrdinal + 1, ordinal);
if (!removedFillerSet.isEmpty()) {
int undefinedRemoveCount = removedFillerSet.size();
ordinalAdjustment -= undefinedRemoveCount;
offsetAdjustment -= undefinedRemoveCount;
+ nextOrdinal = sortedOrdinals.higher(removedFillerSet.last());
}
}
- if (ordinals.contains(ordinal)) {
+ if (nextOrdinal != null && nextOrdinal == ordinal) {
// defined component removed
if (dtc.isBitFieldComponent()) {
// defer reconciling bitfield space to repack
@@ -382,6 +396,7 @@ public void delete(Set ordinals) {
}
--ordinalAdjustment;
lastDefinedOrdinal = ordinal;
+ nextOrdinal = sortedOrdinals.higher(ordinal);
}
else {
@@ -392,9 +407,10 @@ public void delete(Set ordinals) {
lastDefinedOrdinal = ordinal;
}
}
- if (treeSet != null) {
+ if (!isPacked) {
// Identify removed filler after last defined component
- Set removedFillerSet = treeSet.subSet(lastDefinedOrdinal + 1, numComponents);
+ Set removedFillerSet =
+ sortedOrdinals.subSet(lastDefinedOrdinal + 1, numComponents);
if (!removedFillerSet.isEmpty()) {
int undefinedRemoveCount = removedFillerSet.size();
ordinalAdjustment -= undefinedRemoveCount;
@@ -405,7 +421,7 @@ public void delete(Set ordinals) {
components = newComponents;
numComponents += ordinalAdjustment;
- if (isPackingEnabled()) {
+ if (isPacked) {
repack(true);
}
else {
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/UnionDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/UnionDataType.java
index af3f5d054ce..75f2a5419b5 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/UnionDataType.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/UnionDataType.java
@@ -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.
@@ -286,6 +286,11 @@ public void delete(Set ordinals) {
return;
}
+ if (ordinals.size() == 1) {
+ ordinals.forEach(ordinal -> delete(ordinal));
+ return;
+ }
+
int oldAlignment = getAlignment();
List newComponents = new ArrayList<>();
@@ -312,7 +317,7 @@ public void delete(Set ordinals) {
notifyAlignmentChanged();
}
}
- else {
+ else if (unionLength != newLength) {
unionLength = newLength;
notifySizeChanged();
}