GP-1403 added suggested string setting support

This commit is contained in:
ghidra1 2022-03-23 09:52:38 -04:00
parent 3acd14c48a
commit 362bd6b5cb
11 changed files with 255 additions and 20 deletions

View file

@ -26,8 +26,7 @@ import db.*;
import db.util.ErrorHandler;
import generic.jar.ResourceFile;
import ghidra.app.plugin.core.datamgr.archive.BuiltInSourceArchive;
import ghidra.docking.settings.Settings;
import ghidra.docking.settings.SettingsDefinition;
import ghidra.docking.settings.*;
import ghidra.framework.store.db.PackedDBHandle;
import ghidra.framework.store.db.PackedDatabase;
import ghidra.graph.*;
@ -121,6 +120,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
private SettingsCache<Long> settingsCache = new SettingsCache<>(200);
private List<DataType> sortedDataTypes;
private Map<Long, Set<String>> enumValueMap;
private Map<String, Set<String>> suggestedSettingsValuesMap = new HashMap<>();
private List<InvalidatedListener> invalidatedListeners = new ArrayList<>();
protected DataTypeManagerChangeListenerHandler defaultListener =
@ -678,6 +678,13 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
if (rec != null) {
SettingDB setting = new SettingDB(rec, settingsAdapter.getSettingName(rec));
settingsCache.put(dataTypeId, name, setting);
if (strValue != null) {
Set<String> suggestions = suggestedSettingsValuesMap.get(name);
if (suggestions != null) {
// only cache suggestion if suggestions previously requested
suggestions.add(strValue);
}
}
return true;
}
return false;
@ -691,6 +698,39 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
return false;
}
private Set<String> generateSuggestions(StringSettingsDefinition settingsDefinition) {
Set<String> set = new TreeSet<>();
try {
settingsAdapter.addAllValues(settingsDefinition.getStorageKey(), set);
settingsDefinition.addPreferredValues(this, set);
}
catch (IOException e) {
errHandler.dbError(e);
}
return set;
}
/**
* Get suggested setting values for a specified settingsDefinition
* @param settingsDefinition string settings definition
* @return suggested values or empty array if none
*/
String[] getSuggestedValues(StringSettingsDefinition settingsDefinition) {
lock.acquire();
try {
Set<String> set = suggestedSettingsValuesMap
.computeIfAbsent(settingsDefinition.getStorageKey(),
n -> generateSuggestions(settingsDefinition));
if (set.isEmpty()) {
return Settings.EMPTY_STRING_ARRAY;
}
return set.toArray(new String[set.size()]);
}
finally {
lock.release();
}
}
/**
* Determine if transaction is active. With proper lock established
* this method may be useful for determining if a lazy record update
@ -3200,7 +3240,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
fireInvalidated();
updateFavorites();
idsToDataTypeMap.clear();
suggestedSettingsValuesMap.clear();
}
finally {
lock.release();

View file

@ -89,6 +89,11 @@ class DataTypeSettingsDB implements Settings {
return true;
}
@Override
public String[] getSuggestedValues(StringSettingsDefinition settingsDefinition) {
return dataMgr.getSuggestedValues(settingsDefinition);
}
/**
* Set predicate for settings modification
* @param allowedSettingPredicate callback for checking an allowed setting modification

View file

@ -16,6 +16,7 @@
package ghidra.program.database.data;
import java.io.IOException;
import java.util.Set;
import db.*;
import ghidra.program.database.map.AddressMap;
@ -289,6 +290,14 @@ abstract class SettingsDBAdapter {
*/
abstract String[] getSettingsNames(long associationId) throws IOException;
/**
* Add all values stored for the specified setting name to the specified set.
* @param name setting name
* @param set value set
* @throws IOException if there was a problem accessing the database
*/
abstract void addAllValues(String name, Set<String> set) throws IOException;
/**
* Get the setting name which corresponds to the specified record.
* @param record normalized settings record (name column is an integer index value)

View file

@ -16,8 +16,9 @@
package ghidra.program.database.data;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import db.*;
import ghidra.util.ReadOnlyException;
@ -110,6 +111,20 @@ class SettingsDBAdapterV0 extends SettingsDBAdapter {
return list.toArray(names);
}
@Override
void addAllValues(String name, Set<String> set) throws IOException {
RecordIterator recIter = settingsTable.iterator();
while (recIter.hasNext()) {
DBRecord rec = recIter.next();
if (name.equals(rec.getString(V0_SETTINGS_NAME_COL))) {
String s = rec.getString(V0_SETTINGS_STRING_VALUE_COL);
if (!StringUtils.isBlank(s)) {
set.add(s);
}
}
}
}
@Override
protected String getSettingName(DBRecord normalizedRecord) {
short nameIndex = normalizedRecord.getShortValue(SettingsDBAdapter.SETTINGS_NAME_INDEX_COL);

View file

@ -18,6 +18,8 @@ package ghidra.program.database.data;
import java.io.IOException;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import db.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
@ -148,6 +150,24 @@ class SettingsDBAdapterV1 extends SettingsDBAdapter {
return list.toArray(names);
}
@Override
void addAllValues(String name, Set<String> set) throws IOException {
short nameIndex = getNameIndex(name);
if (nameIndex < MIN_NAME_INDEX) {
return; // no such name defined
}
RecordIterator recIter = settingsTable.iterator();
while (recIter.hasNext()) {
DBRecord rec = recIter.next();
if (nameIndex == rec.getShortValue(V1_SETTINGS_NAME_INDEX_COL)) {
String s = rec.getString(V1_SETTINGS_STRING_VALUE_COL);
if (!StringUtils.isBlank(s)) {
set.add(s);
}
}
}
}
private void initNameMaps() throws IOException {
if (nameIndexMap != null) {
return;
@ -250,6 +270,8 @@ class SettingsDBAdapterV1 extends SettingsDBAdapter {
DBRecord updateSettingsRecord(long associationId, String name, String strValue, long longValue)
throws IOException {
strValue = StringUtils.isBlank(strValue) ? null : strValue.trim();
DBRecord record = getSettingsRecord(associationId, name);
if (record == null) {
return createSettingsRecord(associationId, name, strValue, longValue);

View file

@ -15,10 +15,14 @@
*/
package ghidra.program.model.data;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import ghidra.docking.settings.Settings;
import ghidra.docking.settings.StringSettingsDefinition;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.address.AddressSpace;
public class AddressSpaceSettingsDefinition
implements StringSettingsDefinition, TypeDefSettingsDefinition {
@ -101,4 +105,30 @@ public class AddressSpaceSettingsDefinition
}
return null;
}
@Override
public String[] getSuggestedValues(Settings settings) {
return settings.getSuggestedValues(this);
}
@Override
public boolean supportsSuggestedValues() {
return true;
}
@Override
public boolean addPreferredValues(Object settingsOwner, Set<String> set) {
if (settingsOwner instanceof ProgramBasedDataTypeManager) {
ProgramBasedDataTypeManager dtm = (ProgramBasedDataTypeManager) settingsOwner;
AddressFactory addressFactory = dtm.getProgram().getAddressFactory();
for (AddressSpace space : addressFactory.getAllAddressSpaces()) {
if (space.isLoadedMemorySpace()) {
set.add(space.getName());
}
}
return true;
}
return false;
}
}