Fix #1680 by adding a comment field in the enum editor

This commit is contained in:
Theofilos Pechlivanis 2020-10-23 18:16:08 +03:00 committed by dragonmacher
parent 156ce7ef80
commit 7398d26e84
10 changed files with 175 additions and 36 deletions

View file

@ -2506,7 +2506,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
long enumID = record.getKey();
String[] enumNames = enumm.getNames();
for (String enumName : enumNames) {
enumValueAdapter.createRecord(enumID, enumName, enumm.getValue(enumName));
enumValueAdapter.createRecord(enumID, enumName, enumm.getValue(enumName), enumm.getComment(enumName));
}
EnumDB enumDB = new EnumDB(this, dtCache, enumAdapter, enumValueAdapter, record);
return enumDB;

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.
@ -44,6 +44,7 @@ class EnumDB extends DataTypeDB implements Enum {
private EnumValueDBAdapter valueAdapter;
private Map<String, Long> nameMap; // name to value
private Map<Long, List<String>> valueMap; // value to names
private Map<String, String> commentMap; // name to comment
private List<BitGroup> bitGroups;
EnumDB(DataTypeManagerDB dataMgr, DBObjectCache<DataTypeDB> cache, EnumDBAdapter adapter,
@ -84,6 +85,7 @@ class EnumDB extends DataTypeDB implements Enum {
bitGroups = null;
nameMap = new HashMap<>();
valueMap = new HashMap<>();
commentMap = new HashMap<>();
Field[] ids = valueAdapter.getValueIdsInEnum(key);
@ -91,14 +93,16 @@ class EnumDB extends DataTypeDB implements Enum {
DBRecord rec = valueAdapter.getRecord(id.getLongValue());
String valueName = rec.getString(EnumValueDBAdapter.ENUMVAL_NAME_COL);
long value = rec.getLongValue(EnumValueDBAdapter.ENUMVAL_VALUE_COL);
addToCache(valueName, value);
String valueNameComment = rec.getString(EnumValueDBAdapter.ENUMVAL_COMMENT_COL);
addToCache(valueName, value, valueNameComment);
}
}
private void addToCache(String valueName, long value) {
private void addToCache(String valueName, long value, String valueNameComment) {
nameMap.put(valueName, value);
List<String> list = valueMap.computeIfAbsent(value, v -> new ArrayList<>());
list.add(valueName);
commentMap.put(valueName, valueNameComment);
}
private boolean removeFromCache(String valueName) {
@ -117,6 +121,10 @@ class EnumDB extends DataTypeDB implements Enum {
if (list.isEmpty()) {
valueMap.remove(value);
}
String comment = commentMap.remove(valueName);
if (comment == null) {
return false;
}
return true;
}
@ -159,6 +167,23 @@ class EnumDB extends DataTypeDB implements Enum {
return false;
}
@Override
public String getComment(String valueName) throws NoSuchElementException {
lock.acquire();
try {
checkIsValid();
initializeIfNeeded();
String comment = commentMap.get(valueName);
if (comment == null) {
comment = "";
}
return comment;
}
finally {
lock.release();
}
}
@Override
public long[] getValues() {
lock.acquire();
@ -189,6 +214,19 @@ class EnumDB extends DataTypeDB implements Enum {
}
}
@Override
public String[] getComments() {
lock.acquire();
try {
checkIsValid();
initializeIfNeeded();
return commentMap.keySet().toArray(new String[commentMap.size()]);
}
finally {
lock.release();
}
}
@Override
public int getCount() {
lock.acquire();
@ -204,6 +242,12 @@ class EnumDB extends DataTypeDB implements Enum {
@Override
public void add(String valueName, long value) {
String valueNameComment = "";
add(valueName, value, valueNameComment);
}
@Override
public void add(String valueName, long value, String valueNameComment) {
lock.acquire();
try {
checkDeleted();
@ -213,11 +257,10 @@ class EnumDB extends DataTypeDB implements Enum {
throw new IllegalArgumentException(valueName + " already exists in this enum");
}
bitGroups = null;
valueAdapter.createRecord(key, valueName, value);
valueAdapter.createRecord(key, valueName, value, valueNameComment);
adapter.updateRecord(record, true);
addToCache(valueName, value);
addToCache(valueName, value, valueNameComment);
dataMgr.dataTypeChanged(this, false);
}
catch (IOException e) {
dataMgr.dbError(e);
@ -286,6 +329,7 @@ class EnumDB extends DataTypeDB implements Enum {
bitGroups = null;
nameMap = new HashMap<>();
valueMap = new HashMap<>();
commentMap = new HashMap<>();
Field[] ids = valueAdapter.getValueIdsInEnum(key);
for (Field id : ids) {
@ -303,9 +347,10 @@ class EnumDB extends DataTypeDB implements Enum {
String[] names = enumm.getNames();
for (String name2 : names) {
long value = enumm.getValue(name2);
valueAdapter.createRecord(key, name2, value);
String comment = enumm.getComment(name2);
valueAdapter.createRecord(key, name2, value, comment);
adapter.updateRecord(record, true);
addToCache(name2, value);
addToCache(name2, value, comment);
}
if (oldLength != newLength) {

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.
@ -38,9 +38,10 @@ abstract class EnumValueDBAdapter {
static final int ENUMVAL_NAME_COL = EnumValueDBAdapterV0.V0_ENUMVAL_NAME_COL;
static final int ENUMVAL_VALUE_COL = EnumValueDBAdapterV0.V0_ENUMVAL_VALUE_COL;
static final int ENUMVAL_ID_COL = EnumValueDBAdapterV0.V0_ENUMVAL_ID_COL;
static final int ENUMVAL_COMMENT_COL = EnumValueDBAdapterV0.V0_ENUMVAL_COMMENT_COL;
/**
* Gets an adapter for working with the enumeration data type values database table. The adapter is based
* Gets an adapter for working with the enumeration data type values database table. The adapter is based
* on the version of the database associated with the specified database handle and the openMode.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
@ -87,10 +88,12 @@ abstract class EnumValueDBAdapter {
* Create new enum value record corresponding to specified enum datatype ID
* @param enumID enum datatype ID
* @param name value name
* @param value numeric value
* @param value numeric value
* @param comment the field comment
* @throws IOException if IO error occurs
*/
abstract void createRecord(long enumID, String name, long value) throws IOException;
abstract void createRecord(long enumID, String name, long value, String comment)
throws IOException;
/**
* Get enum value record which corresponds to specified value record ID

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.
@ -34,7 +34,8 @@ class EnumValueDBAdapterNoTable extends EnumValueDBAdapter {
}
@Override
public void createRecord(long enumID, String name, long value) throws IOException {
public void createRecord(long enumID, String name, long value, String comment)
throws IOException {
throw new UnsupportedOperationException();
}

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.
@ -18,11 +18,12 @@ package ghidra.program.database.data;
import java.io.IOException;
import db.*;
import ghidra.program.model.lang.ConstantPool.Record;
import ghidra.util.exception.VersionException;
/**
* Version 0 implementation for the enumeration tables adapter.
*
*
*/
class EnumValueDBAdapterV0 extends EnumValueDBAdapter {
static final int VERSION = 0;
@ -31,11 +32,16 @@ class EnumValueDBAdapterV0 extends EnumValueDBAdapter {
static final int V0_ENUMVAL_NAME_COL = 0;
static final int V0_ENUMVAL_VALUE_COL = 1;
static final int V0_ENUMVAL_ID_COL = 2;
static final int V0_ENUMVAL_COMMENT_COL = 3;
static final Schema V0_ENUM_VALUE_SCHEMA = new Schema(0, "Enum Value ID",
new Field[] { StringField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE },
new String[] { "Name", "Value", "Enum ID" });
// static final Schema V1_ENUM_VALUE_SCHEMA = new Schema(0, "Enum Value ID",
// new Class[] { StringField.class, LongField.class, LongField.class, StringField.class },
// new String[] { "Name", "Value", "Enum ID", "Comment" });
private Table valueTable;
/**
@ -71,11 +77,13 @@ class EnumValueDBAdapterV0 extends EnumValueDBAdapter {
}
@Override
public void createRecord(long enumID, String name, long value) throws IOException {
DBRecord record = V0_ENUM_VALUE_SCHEMA.createRecord(valueTable.getKey());
public void createRecord(long enumID, String name, long value, String comment)
throws IOException {
Record record = V0_ENUM_VALUE_SCHEMA.createRecord(valueTable.getKey());
record.setLongValue(V0_ENUMVAL_ID_COL, enumID);
record.setString(V0_ENUMVAL_NAME_COL, name);
record.setLongValue(V0_ENUMVAL_VALUE_COL, value);
record.setString(V0_ENUMVAL_COMMENT_COL, comment);
valueTable.putRecord(record);
}

View file

@ -37,6 +37,14 @@ public interface Enum extends DataType {
*/
public String getName(long value);
/**
* Get the comment for the given name.
* @param name name of the entry
* @return the comment
* @throws NoSuchElementException if the name does not exist in this Enum
*/
public String getComment(String name) throws NoSuchElementException;
/**
* Get the values of the enum entries.
* @return values sorted in ascending order
@ -48,6 +56,11 @@ public interface Enum extends DataType {
*/
public String[] getNames();
/**
* Get the comments of the enum entries.
*/
public String[] getComments();
/**
* Get the number of entries in this Enum.
*/
@ -60,6 +73,14 @@ public interface Enum extends DataType {
*/
public void add(String name, long value);
/**
* Add a enum entry.
* @param name name of the new entry
* @param value value of the new entry
* @param comment comment of the new entry
*/
public void add(String name, long value, String comment);
/**
* Remove the enum entry with the given name.
* @param name name of entry to remove.

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.
@ -33,6 +33,7 @@ public class EnumDataType extends GenericDataType implements Enum {
private Map<String, Long> nameMap; // name to value
private Map<Long, List<String>> valueMap; // value to names
private Map<String, String> commentMap; // name to comment
private int length;
private String description;
private List<BitGroup> bitGroups;
@ -52,6 +53,7 @@ public class EnumDataType extends GenericDataType implements Enum {
}
nameMap = new HashMap<>();
valueMap = new HashMap<>();
commentMap = new HashMap<>();
this.length = length;
}
@ -65,6 +67,7 @@ public class EnumDataType extends GenericDataType implements Enum {
}
nameMap = new HashMap<>();
valueMap = new HashMap<>();
commentMap = new HashMap<>();
this.length = length;
}
@ -91,6 +94,15 @@ public class EnumDataType extends GenericDataType implements Enum {
return list.get(0);
}
@Override
public String getComment(String valueName) throws NoSuchElementException {
String valueNameComment = commentMap.get(valueName);
if (valueNameComment == null) {
valueNameComment = "";
}
return valueNameComment;
}
@Override
public long[] getValues() {
long[] values = valueMap.keySet().stream().mapToLong(Long::longValue).toArray();
@ -105,6 +117,11 @@ public class EnumDataType extends GenericDataType implements Enum {
return names;
}
@Override
public String[] getComments() {
return commentMap.values().toArray(new String[commentMap.size()]);
}
@Override
public int getCount() {
return nameMap.size();
@ -112,6 +129,12 @@ public class EnumDataType extends GenericDataType implements Enum {
@Override
public void add(String valueName, long value) {
String valueNameComment = "";
add(valueName, value, valueNameComment);
}
@Override
public void add(String valueName, long value, String valueNameComment) {
bitGroups = null;
checkValue(value);
if (nameMap.containsKey(valueName)) {
@ -124,6 +147,10 @@ public class EnumDataType extends GenericDataType implements Enum {
valueMap.put(value, list);
}
list.add(valueName);
if (valueNameComment == null) {
valueNameComment = "";
}
commentMap.put(valueName, valueNameComment);
}
private void checkValue(long value) {
@ -166,6 +193,7 @@ public class EnumDataType extends GenericDataType implements Enum {
if (list.isEmpty()) {
valueMap.remove(value);
}
commentMap.remove(valueName);
}
}
@ -356,7 +384,10 @@ public class EnumDataType extends GenericDataType implements Enum {
for (int i = 0; i < names.length; i++) {
long value = getValue(names[i]);
long otherValue = enumm.getValue(names[i]);
if (!names[i].equals(otherNames[i]) || value != otherValue) {
String comment = getComment(names[i]);
String otherComment = enumm.getComment(names[i]);
if (!names[i].equals(otherNames[i]) || value != otherValue ||
!comment.equals(otherComment)) {
return false;
}
}
@ -376,10 +407,11 @@ public class EnumDataType extends GenericDataType implements Enum {
Enum enumm = (Enum) dataType;
nameMap = new HashMap<>();
valueMap = new HashMap<>();
commentMap = new HashMap<>();
setLength(enumm.getLength());
String[] names = enumm.getNames();
for (String name2 : names) {
add(name2, enumm.getValue(name2));
add(name2, enumm.getValue(name2), enumm.getComment(name2));
}
stateChanged(null);
}