GP-4949 Added Structure.setLength method and made structure editor performance improvements and various bug fixes.

This commit is contained in:
ghidra1 2024-09-25 13:41:13 -04:00
parent 2fe68de0e2
commit ef724708df
19 changed files with 341 additions and 270 deletions

View file

@ -236,9 +236,57 @@ class StructureDB extends CompositeDB implements StructureInternal {
}
}
@Override
public void setLength(int len) {
if (len < 0) {
throw new IllegalArgumentException("Invalid length: " + len);
}
if (len == structLength || isPackingEnabled()) {
return;
}
lock.acquire();
try {
checkDeleted();
if (len < structLength) {
// identify index of first defined-component to be removed
int index = Collections.binarySearch(components, Integer.valueOf(len),
OffsetComparator.INSTANCE);
if (index < 0) {
index = -index - 1;
}
else {
index = backupToFirstComponentContainingOffset(index, len);
}
int definedComponentCount = components.size();
if (index >= 0 && index < definedComponentCount) {
for (int i = index; i < definedComponentCount; i++) {
doDelete(components.get(i));
}
components = components.subList(0, index);
}
}
else {
numComponents += len - structLength;
}
structLength = len;
repack(false, false);
notifySizeChanged(false);
}
catch (IOException e) {
dataMgr.dbError(e);
}
finally {
lock.release();
}
}
@Override
public void growStructure(int amount) {
if (isPackingEnabled()) {
if (amount < 0) {
throw new IllegalArgumentException("Invalid growth amount: " + amount);
}
if (amount == 0 || isPackingEnabled()) {
return;
}
lock.acquire();

View file

@ -914,6 +914,7 @@ public class StandAloneDataTypeManager extends DataTypeManagerDB implements Clos
}
}
if (restored) {
invalidateCache();
notifyRestored();
}
}

View file

@ -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.
@ -430,13 +430,22 @@ public interface Structure extends Composite {
String comment) throws IllegalArgumentException;
/**
* Increases the size of the structure by the specified amount by adding undefined filler at the
* Increases the size of the structure by the specified positive amount by adding undefined filler at the
* end of the structure. NOTE: This method only has an affect on non-packed structures.
*
* @param amount the amount by which to grow the structure.
* @throws IllegalArgumentException if amount &lt; 1
* @throws IllegalArgumentException if amount &lt; 0
*/
public void growStructure(int amount);
/**
* Set the size of the structure to the specified byte-length. If the length is shortened defined
* components will be cleared and removed as required.
* NOTE: This method only has an affect on non-packed structures.
* @param length new structure length
* @throws IllegalArgumentException if length &lt; 0
*/
public void setLength(int length);
/**
* <code>BitOffsetComparator</code> provides ability to compare an normalized bit offset (see

View file

@ -624,9 +624,43 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
return dtc;
}
@Override
public void setLength(int len) {
if (len < 0) {
throw new IllegalArgumentException("Invalid length: " + len);
}
if (len == structLength || isPackingEnabled()) {
return;
}
if (len < structLength) {
// identify index of first defined-component to be removed
int index = Collections.binarySearch(components, Integer.valueOf(len),
OffsetComparator.INSTANCE);
if (index < 0) {
index = -index - 1;
}
else {
index = backupToFirstComponentContainingOffset(index, len);
}
int definedComponentCount = components.size();
if (index >= 0 && index < definedComponentCount) {
components = components.subList(0, index);
}
}
else {
numComponents += len - structLength;
}
structLength = len;
repack(false);
notifySizeChanged();
}
@Override
public void growStructure(int amount) {
if (isPackingEnabled()) {
if (amount < 0) {
throw new IllegalArgumentException("Invalid growth amount: " + amount);
}
if (amount == 0 || isPackingEnabled()) {
return;
}
doGrowStructure(amount);

View file

@ -1449,6 +1449,40 @@ public class StructureDBTest extends AbstractGenericTest {
assertEquals(dtc1, barStruct.getComponent(6));
}
@Test
public void testSetLength() {
assertEquals(8, struct.getLength());
assertEquals(4, struct.getNumComponents());
assertEquals(4, struct.getNumDefinedComponents());
struct.setLength(20);
assertEquals(20, struct.getLength());
assertEquals(16, struct.getNumComponents());
assertEquals(4, struct.getNumDefinedComponents());
// new length is offcut within 3rd component at offset 0x3 which should get cleared
struct.setLength(4);
assertEquals(4, struct.getLength());
assertEquals(3, struct.getNumComponents());
assertEquals(2, struct.getNumDefinedComponents());
// Maximum length supported by GUI editor is ~Integer.MAX_VALUE/10
int len = Integer.MAX_VALUE / 10;
struct.setLength(len);
assertEquals(len, struct.getLength());
assertEquals(len - 1, struct.getNumComponents());
assertEquals(2, struct.getNumDefinedComponents());
len /= 2;
struct.replaceAtOffset(len-2, WordDataType.dataType, -1, "x", null); // will be preserved below
struct.replaceAtOffset(len+2, WordDataType.dataType, -1, "y", null); // will be cleared below
struct.setLength(len);
assertEquals(len, struct.getLength());
assertEquals(len - 2, struct.getNumComponents());
assertEquals(3, struct.getNumDefinedComponents());
}
@Test
public void testDeleteMany() {