mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 12:00:04 +02:00
GP-1316 - Enums - Updates for PR to add comments to enum values
This commit is contained in:
parent
7398d26e84
commit
e80dedcbdf
25 changed files with 715 additions and 1219 deletions
|
@ -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.
|
||||
|
@ -19,6 +19,8 @@ import java.io.IOException;
|
|||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import db.DBRecord;
|
||||
import db.Field;
|
||||
import ghidra.docking.settings.Settings;
|
||||
|
@ -33,7 +35,6 @@ import ghidra.util.UniversalID;
|
|||
|
||||
/**
|
||||
* Database implementation for the enumerated data type.
|
||||
*
|
||||
*/
|
||||
class EnumDB extends DataTypeDB implements Enum {
|
||||
|
||||
|
@ -42,6 +43,7 @@ class EnumDB extends DataTypeDB implements Enum {
|
|||
|
||||
private EnumDBAdapter adapter;
|
||||
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
|
||||
|
@ -88,21 +90,22 @@ class EnumDB extends DataTypeDB implements Enum {
|
|||
commentMap = new HashMap<>();
|
||||
|
||||
Field[] ids = valueAdapter.getValueIdsInEnum(key);
|
||||
|
||||
for (Field id : ids) {
|
||||
DBRecord rec = valueAdapter.getRecord(id.getLongValue());
|
||||
String valueName = rec.getString(EnumValueDBAdapter.ENUMVAL_NAME_COL);
|
||||
long value = rec.getLongValue(EnumValueDBAdapter.ENUMVAL_VALUE_COL);
|
||||
String valueNameComment = rec.getString(EnumValueDBAdapter.ENUMVAL_COMMENT_COL);
|
||||
addToCache(valueName, value, valueNameComment);
|
||||
String comment = rec.getString(EnumValueDBAdapter.ENUMVAL_COMMENT_COL);
|
||||
addToCache(valueName, value, comment);
|
||||
}
|
||||
}
|
||||
|
||||
private void addToCache(String valueName, long value, String valueNameComment) {
|
||||
private void addToCache(String valueName, long value, String comment) {
|
||||
nameMap.put(valueName, value);
|
||||
List<String> list = valueMap.computeIfAbsent(value, v -> new ArrayList<>());
|
||||
list.add(valueName);
|
||||
commentMap.put(valueName, valueNameComment);
|
||||
if (!StringUtils.isBlank(comment)) {
|
||||
commentMap.put(valueName, comment);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean removeFromCache(String valueName) {
|
||||
|
@ -121,10 +124,7 @@ class EnumDB extends DataTypeDB implements Enum {
|
|||
if (list.isEmpty()) {
|
||||
valueMap.remove(value);
|
||||
}
|
||||
String comment = commentMap.remove(valueName);
|
||||
if (comment == null) {
|
||||
return false;
|
||||
}
|
||||
commentMap.remove(valueName);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -168,7 +168,7 @@ class EnumDB extends DataTypeDB implements Enum {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getComment(String valueName) throws NoSuchElementException {
|
||||
public String getComment(String valueName) {
|
||||
lock.acquire();
|
||||
try {
|
||||
checkIsValid();
|
||||
|
@ -214,19 +214,6 @@ 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();
|
||||
|
@ -242,12 +229,11 @@ class EnumDB extends DataTypeDB implements Enum {
|
|||
|
||||
@Override
|
||||
public void add(String valueName, long value) {
|
||||
String valueNameComment = "";
|
||||
add(valueName, value, valueNameComment);
|
||||
add(valueName, value, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(String valueName, long value, String valueNameComment) {
|
||||
public void add(String valueName, long value, String comment) {
|
||||
lock.acquire();
|
||||
try {
|
||||
checkDeleted();
|
||||
|
@ -256,10 +242,15 @@ class EnumDB extends DataTypeDB implements Enum {
|
|||
if (nameMap.containsKey(valueName)) {
|
||||
throw new IllegalArgumentException(valueName + " already exists in this enum");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(comment)) {
|
||||
comment = null; // use null values in the db to save space
|
||||
}
|
||||
|
||||
bitGroups = null;
|
||||
valueAdapter.createRecord(key, valueName, value, valueNameComment);
|
||||
valueAdapter.createRecord(key, valueName, value, comment);
|
||||
adapter.updateRecord(record, true);
|
||||
addToCache(valueName, value, valueNameComment);
|
||||
addToCache(valueName, value, comment);
|
||||
dataMgr.dataTypeChanged(this, false);
|
||||
}
|
||||
catch (IOException e) {
|
||||
|
@ -294,10 +285,9 @@ class EnumDB extends DataTypeDB implements Enum {
|
|||
if (!removeFromCache(valueName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bitGroups = null;
|
||||
|
||||
Field[] ids = valueAdapter.getValueIdsInEnum(key);
|
||||
|
||||
for (Field id : ids) {
|
||||
DBRecord rec = valueAdapter.getRecord(id.getLongValue());
|
||||
if (valueName.equals(rec.getString(EnumValueDBAdapter.ENUMVAL_NAME_COL))) {
|
||||
|
@ -321,6 +311,7 @@ class EnumDB extends DataTypeDB implements Enum {
|
|||
if (!(dataType instanceof Enum)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
Enum enumm = (Enum) dataType;
|
||||
lock.acquire();
|
||||
try {
|
||||
|
@ -338,19 +329,21 @@ class EnumDB extends DataTypeDB implements Enum {
|
|||
|
||||
int oldLength = getLength();
|
||||
int newLength = enumm.getLength();
|
||||
|
||||
if (oldLength != newLength) {
|
||||
record.setByteValue(EnumDBAdapter.ENUM_SIZE_COL, (byte) newLength);
|
||||
adapter.updateRecord(record, true);
|
||||
}
|
||||
|
||||
String[] names = enumm.getNames();
|
||||
for (String name2 : names) {
|
||||
long value = enumm.getValue(name2);
|
||||
String comment = enumm.getComment(name2);
|
||||
valueAdapter.createRecord(key, name2, value, comment);
|
||||
for (String valueName : names) {
|
||||
long value = enumm.getValue(valueName);
|
||||
String comment = enumm.getComment(valueName);
|
||||
if (StringUtils.isBlank(comment)) {
|
||||
comment = null; // use null values in the db to save space
|
||||
}
|
||||
valueAdapter.createRecord(key, valueName, value, comment);
|
||||
adapter.updateRecord(record, true);
|
||||
addToCache(name2, value, comment);
|
||||
addToCache(valueName, value, comment);
|
||||
}
|
||||
|
||||
if (oldLength != newLength) {
|
||||
|
@ -525,7 +518,7 @@ class EnumDB extends DataTypeDB implements Enum {
|
|||
return "0";
|
||||
}
|
||||
List<BitGroup> list = getBitGroups();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (BitGroup bitGroup : list) {
|
||||
long subValue = bitGroup.getMask() & value;
|
||||
if (subValue != 0) {
|
||||
|
@ -576,21 +569,39 @@ class EnumDB extends DataTypeDB implements Enum {
|
|||
getLength() != enumm.getLength() || getCount() != enumm.getCount()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isEachValueEquivalent(enumm)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isEachValueEquivalent(Enum enumm) {
|
||||
String[] names = getNames();
|
||||
String[] otherNames = enumm.getNames();
|
||||
try {
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (!names[i].equals(otherNames[i])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long value = getValue(names[i]);
|
||||
long otherValue = enumm.getValue(names[i]);
|
||||
if (!names[i].equals(otherNames[i]) || value != otherValue) {
|
||||
if (value != otherValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String comment = getComment(names[i]);
|
||||
String otherComment = enumm.getComment(names[i]);
|
||||
if (!comment.equals(otherComment)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (NoSuchElementException e) {
|
||||
return false; // named element not found
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -598,6 +609,7 @@ class EnumDB extends DataTypeDB implements Enum {
|
|||
try {
|
||||
nameMap = null;
|
||||
valueMap = null;
|
||||
commentMap = null;
|
||||
bitGroups = null;
|
||||
DBRecord rec = adapter.getRecord(key);
|
||||
if (rec != null) {
|
||||
|
@ -731,5 +743,4 @@ class EnumDB extends DataTypeDB implements Enum {
|
|||
lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -30,15 +30,16 @@ import ghidra.util.task.TaskMonitor;
|
|||
/**
|
||||
* Adapter to access the Enumeration data type values tables.
|
||||
*/
|
||||
abstract class EnumValueDBAdapter {
|
||||
abstract class EnumValueDBAdapter implements RecordTranslator {
|
||||
|
||||
static final String ENUM_VALUE_TABLE_NAME = "Enumeration Values";
|
||||
static final Schema ENUM_VALUE_SCHEMA = EnumValueDBAdapterV0.V0_ENUM_VALUE_SCHEMA;
|
||||
static final Schema ENUM_VALUE_SCHEMA = EnumValueDBAdapterV1.SCHEMA;
|
||||
|
||||
// Enum Value Columns
|
||||
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;
|
||||
static final int ENUMVAL_NAME_COL = 0;
|
||||
static final int ENUMVAL_VALUE_COL = 1;
|
||||
static final int ENUMVAL_ID_COL = 2;
|
||||
static final int ENUMVAL_COMMENT_COL = 3;
|
||||
|
||||
/**
|
||||
* Gets an adapter for working with the enumeration data type values database table. The adapter is based
|
||||
|
@ -53,16 +54,16 @@ abstract class EnumValueDBAdapter {
|
|||
static EnumValueDBAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
|
||||
throws VersionException, IOException {
|
||||
if (openMode == DBConstants.CREATE) {
|
||||
return new EnumValueDBAdapterV0(handle, true);
|
||||
return new EnumValueDBAdapterV1(handle, true);
|
||||
}
|
||||
try {
|
||||
return new EnumValueDBAdapterV0(handle, false);
|
||||
return new EnumValueDBAdapterV1(handle, false);
|
||||
}
|
||||
catch (VersionException e) {
|
||||
if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
|
||||
throw e;
|
||||
}
|
||||
EnumValueDBAdapter adapter = new EnumValueDBAdapterNoTable(handle);
|
||||
EnumValueDBAdapter adapter = findReadOnlyAdapter(handle);
|
||||
if (openMode == DBConstants.UPGRADE) {
|
||||
adapter = upgrade(handle, adapter);
|
||||
}
|
||||
|
@ -70,8 +71,18 @@ abstract class EnumValueDBAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
static EnumValueDBAdapter findReadOnlyAdapter(DBHandle handle) {
|
||||
try {
|
||||
return new EnumValueDBAdapterV0(handle);
|
||||
}
|
||||
catch (VersionException e) {
|
||||
return new EnumValueDBAdapterNoTable(handle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrades the Enumeration Data Type Values table from the oldAdapter's version to the current version.
|
||||
* Upgrades the Enumeration Data Type Values table from the oldAdapter's version to the current
|
||||
* version.
|
||||
* @param handle handle to the database whose table is to be upgraded to a newer version.
|
||||
* @param oldAdapter the adapter for the existing table to be upgraded.
|
||||
* @return the adapter for the new upgraded version of the table.
|
||||
|
@ -81,7 +92,30 @@ abstract class EnumValueDBAdapter {
|
|||
*/
|
||||
static EnumValueDBAdapter upgrade(DBHandle handle, EnumValueDBAdapter oldAdapter)
|
||||
throws VersionException, IOException {
|
||||
return new EnumValueDBAdapterV0(handle, true);
|
||||
|
||||
DBHandle tmpHandle = new DBHandle();
|
||||
long id = tmpHandle.startTransaction();
|
||||
EnumValueDBAdapter tmpAdapter = null;
|
||||
try {
|
||||
tmpAdapter = new EnumValueDBAdapterV1(tmpHandle, true);
|
||||
RecordIterator it = oldAdapter.getRecords();
|
||||
while (it.hasNext()) {
|
||||
DBRecord rec = it.next();
|
||||
tmpAdapter.updateRecord(rec);
|
||||
}
|
||||
oldAdapter.deleteTable(handle);
|
||||
EnumValueDBAdapter newAdapter = new EnumValueDBAdapterV1(handle, true);
|
||||
it = tmpAdapter.getRecords();
|
||||
while (it.hasNext()) {
|
||||
DBRecord rec = it.next();
|
||||
newAdapter.updateRecord(rec);
|
||||
}
|
||||
return newAdapter;
|
||||
}
|
||||
finally {
|
||||
tmpHandle.endTransaction(id, true);
|
||||
tmpHandle.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,7 +124,7 @@ abstract class EnumValueDBAdapter {
|
|||
* @param name value name
|
||||
* @param value numeric value
|
||||
* @param comment the field comment
|
||||
* @throws IOException if IO error occurs
|
||||
* @throws IOException if there was a problem accessing the database
|
||||
*/
|
||||
abstract void createRecord(long enumID, String name, long value, String comment)
|
||||
throws IOException;
|
||||
|
@ -99,10 +133,26 @@ abstract class EnumValueDBAdapter {
|
|||
* Get enum value record which corresponds to specified value record ID
|
||||
* @param valueID value record ID
|
||||
* @return value record or null
|
||||
* @throws IOException if IO error occurs
|
||||
* @throws IOException if there was a problem accessing the database
|
||||
*/
|
||||
abstract DBRecord getRecord(long valueID) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns an iterator over the value records inside of this Enum
|
||||
* @return the iterator
|
||||
* @throws IOException if there was a problem accessing the database
|
||||
*/
|
||||
abstract RecordIterator getRecords() throws IOException;
|
||||
|
||||
/**
|
||||
* Deletes the table; used when upgrading
|
||||
* @param handle the handle used to delete the table
|
||||
* @throws IOException if there was a problem accessing the database
|
||||
*/
|
||||
void deleteTable(DBHandle handle) throws IOException {
|
||||
handle.deleteTable(ENUM_VALUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the record for the given enum Value ID.
|
||||
* @param valueID ID of the value record to delete
|
||||
|
@ -113,7 +163,7 @@ abstract class EnumValueDBAdapter {
|
|||
/**
|
||||
* Updates the enum data type values table with the provided record.
|
||||
* @param record the new record
|
||||
* @throws IOException if the database can't be accessed.
|
||||
* @throws IOException if there was a problem accessing the database
|
||||
*/
|
||||
abstract void updateRecord(DBRecord record) throws IOException;
|
||||
|
||||
|
@ -121,8 +171,7 @@ abstract class EnumValueDBAdapter {
|
|||
* Get enum value record IDs which correspond to specified enum datatype ID
|
||||
* @param enumID enum datatype ID
|
||||
* @return enum value record IDs as LongField values within Field array
|
||||
* @throws IOException if IO error occurs
|
||||
* @throws IOException if there was a problem accessing the database
|
||||
*/
|
||||
abstract Field[] getValueIdsInEnum(long enumID) throws IOException;
|
||||
|
||||
}
|
||||
|
|
|
@ -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,7 +17,10 @@ package ghidra.program.database.data;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.help.UnsupportedOperationException;
|
||||
|
||||
import db.*;
|
||||
import ghidra.program.database.util.EmptyRecordIterator;
|
||||
|
||||
/**
|
||||
* Adapter needed for a read-only version of data type manager that is not going
|
||||
|
@ -59,4 +62,18 @@ class EnumValueDBAdapterNoTable extends EnumValueDBAdapter {
|
|||
return Field.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator getRecords() throws IOException {
|
||||
return new EmptyRecordIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deleteTable(DBHandle handle) throws IOException {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBRecord translateRecord(DBRecord rec) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,92 +18,84 @@ 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;
|
||||
|
||||
// Enum Value Columns
|
||||
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;
|
||||
// Keep for reference
|
||||
// static final Schema SCHEMA = new Schema(0, "Enum Value ID",
|
||||
// new Field[] { StringField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE },
|
||||
// new String[] { "Name", "Value", "Enum ID" });
|
||||
|
||||
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;
|
||||
private Table table;
|
||||
|
||||
/**
|
||||
* Gets a version 0 adapter for the Enumeration Data Type Values database table.
|
||||
* @param handle handle to the database containing the table.
|
||||
* @param create true if this constructor should create the table.
|
||||
* @throws VersionException if the the table's version does not match the expected version
|
||||
* for this adapter.
|
||||
* @throws IOException if IO error occurs
|
||||
*/
|
||||
public EnumValueDBAdapterV0(DBHandle handle, boolean create)
|
||||
throws VersionException, IOException {
|
||||
public EnumValueDBAdapterV0(DBHandle handle) throws VersionException {
|
||||
|
||||
if (create) {
|
||||
valueTable = handle.createTable(ENUM_VALUE_TABLE_NAME, V0_ENUM_VALUE_SCHEMA,
|
||||
new int[] { V0_ENUMVAL_ID_COL });
|
||||
table = handle.getTable(ENUM_VALUE_TABLE_NAME);
|
||||
if (table == null) {
|
||||
throw new VersionException("Missing Table: " + ENUM_VALUE_TABLE_NAME);
|
||||
}
|
||||
else {
|
||||
valueTable = handle.getTable(ENUM_VALUE_TABLE_NAME);
|
||||
if (valueTable == null) {
|
||||
throw new VersionException("Missing Table: " + ENUM_VALUE_TABLE_NAME);
|
||||
}
|
||||
int version = valueTable.getSchema().getVersion();
|
||||
if (version != VERSION) {
|
||||
String msg = "Expected version " + VERSION + " for table " + ENUM_VALUE_TABLE_NAME +
|
||||
" but got " + valueTable.getSchema().getVersion();
|
||||
if (version < VERSION) {
|
||||
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
|
||||
}
|
||||
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
|
||||
}
|
||||
|
||||
int version = table.getSchema().getVersion();
|
||||
if (version != VERSION) {
|
||||
String msg = "Expected version " + VERSION + " for table " + ENUM_VALUE_TABLE_NAME +
|
||||
" but got " + table.getSchema().getVersion();
|
||||
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
throw new UnsupportedOperationException("Cannot update Version 0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBRecord getRecord(long valueID) throws IOException {
|
||||
return valueTable.getRecord(valueID);
|
||||
return translateRecord(table.getRecord(valueID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRecord(long valueID) throws IOException {
|
||||
valueTable.deleteRecord(valueID);
|
||||
throw new UnsupportedOperationException("Cannot remove Version 0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRecord(DBRecord record) throws IOException {
|
||||
valueTable.putRecord(record);
|
||||
throw new UnsupportedOperationException("Cannot update Version 0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Field[] getValueIdsInEnum(long enumID) throws IOException {
|
||||
return valueTable.findRecords(new LongField(enumID), V0_ENUMVAL_ID_COL);
|
||||
return table.findRecords(new LongField(enumID), ENUMVAL_ID_COL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBRecord translateRecord(DBRecord oldRec) {
|
||||
if (oldRec == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DBRecord record = EnumValueDBAdapter.ENUM_VALUE_SCHEMA.createRecord(oldRec.getKey());
|
||||
record.setLongValue(ENUMVAL_ID_COL, oldRec.getLongValue(ENUMVAL_ID_COL));
|
||||
record.setString(ENUMVAL_NAME_COL, oldRec.getString(ENUMVAL_NAME_COL));
|
||||
record.setLongValue(ENUMVAL_VALUE_COL, oldRec.getLongValue(ENUMVAL_VALUE_COL));
|
||||
record.setString(ENUMVAL_COMMENT_COL, null);
|
||||
return record;
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator getRecords() throws IOException {
|
||||
return new TranslatedRecordIterator(table.iterator(), this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.program.database.data;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import db.*;
|
||||
import ghidra.util.exception.VersionException;
|
||||
|
||||
/**
|
||||
* Version 1 implementation for the enumeration tables adapter.
|
||||
*/
|
||||
class EnumValueDBAdapterV1 extends EnumValueDBAdapter {
|
||||
|
||||
static final int VERSION = 1;
|
||||
|
||||
static final Schema SCHEMA = new Schema(VERSION, "Enum Value ID",
|
||||
new Class[] { StringField.class, LongField.class, LongField.class, StringField.class },
|
||||
new String[] { "Name", "Value", "Enum ID", "Comment" });
|
||||
|
||||
private Table table;
|
||||
|
||||
/**
|
||||
* Gets a version 1 adapter for the Enumeration Data Type Values database table.
|
||||
* @param handle handle to the database containing the table.
|
||||
* @param create true if this constructor should create the table.
|
||||
* @throws VersionException if the the table's version does not match the expected version
|
||||
* for this adapter.
|
||||
* @throws IOException if IO error occurs
|
||||
*/
|
||||
public EnumValueDBAdapterV1(DBHandle handle, boolean create)
|
||||
throws VersionException, IOException {
|
||||
|
||||
if (create) {
|
||||
table = handle.createTable(ENUM_VALUE_TABLE_NAME, SCHEMA, new int[] { ENUMVAL_ID_COL });
|
||||
}
|
||||
else {
|
||||
table = handle.getTable(ENUM_VALUE_TABLE_NAME);
|
||||
if (table == null) {
|
||||
throw new VersionException(true);
|
||||
}
|
||||
int version = table.getSchema().getVersion();
|
||||
if (version != VERSION) {
|
||||
String msg = "Expected version " + VERSION + " for table " + ENUM_VALUE_TABLE_NAME +
|
||||
" but got " + table.getSchema().getVersion();
|
||||
if (version < VERSION) {
|
||||
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
|
||||
}
|
||||
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createRecord(long enumID, String name, long value, String comment)
|
||||
throws IOException {
|
||||
DBRecord record = SCHEMA.createRecord(table.getKey());
|
||||
record.setLongValue(ENUMVAL_ID_COL, enumID);
|
||||
record.setString(ENUMVAL_NAME_COL, name);
|
||||
record.setLongValue(ENUMVAL_VALUE_COL, value);
|
||||
record.setString(ENUMVAL_COMMENT_COL, comment);
|
||||
table.putRecord(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBRecord getRecord(long valueID) throws IOException {
|
||||
return table.getRecord(valueID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRecord(long valueID) throws IOException {
|
||||
table.deleteRecord(valueID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRecord(DBRecord record) throws IOException {
|
||||
table.putRecord(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Field[] getValueIdsInEnum(long enumID) throws IOException {
|
||||
return table.findRecords(new LongField(enumID), ENUMVAL_ID_COL);
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator getRecords() throws IOException {
|
||||
return table.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBRecord translateRecord(DBRecord r) {
|
||||
return r;
|
||||
}
|
||||
}
|
|
@ -24,9 +24,9 @@ import ghidra.util.task.TaskMonitor;
|
|||
|
||||
/**
|
||||
* Adapter to access the Pointer database table for Pointer data types.
|
||||
*
|
||||
*
|
||||
*/
|
||||
abstract class PointerDBAdapter {
|
||||
abstract class PointerDBAdapter implements RecordTranslator {
|
||||
static final String POINTER_TABLE_NAME = "Pointers";
|
||||
|
||||
static final Schema SCHEMA = new Schema(PointerDBAdapterV2.VERSION, "Pointer ID",
|
||||
|
@ -96,7 +96,7 @@ abstract class PointerDBAdapter {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
abstract void deleteTable(DBHandle handle) throws IOException;
|
||||
|
||||
|
@ -105,6 +105,7 @@ abstract class PointerDBAdapter {
|
|||
* @param dataTypeID data type ID of the date type being pointed to
|
||||
* @param categoryID the category ID of the datatype
|
||||
* @param length pointer size in bytes
|
||||
* @return the record
|
||||
* @throws IOException if there was a problem accessing the database
|
||||
*/
|
||||
abstract DBRecord createRecord(long dataTypeID, long categoryID, int length) throws IOException;
|
||||
|
@ -117,6 +118,11 @@ abstract class PointerDBAdapter {
|
|||
*/
|
||||
abstract DBRecord getRecord(long pointerID) throws IOException;
|
||||
|
||||
/**
|
||||
* An iterator over the records of this adapter
|
||||
* @return the iterator
|
||||
* @throws IOException if there was a problem accessing the database
|
||||
*/
|
||||
abstract RecordIterator getRecords() throws IOException;
|
||||
|
||||
/**
|
||||
|
@ -135,51 +141,11 @@ abstract class PointerDBAdapter {
|
|||
abstract void updateRecord(DBRecord record) throws IOException;
|
||||
|
||||
/**
|
||||
* Gets all the pointer data types that are contained in the category that
|
||||
* Gets all the pointer data types that are contained in the category that
|
||||
* have the indicated ID.
|
||||
* @param categoryID the category whose pointer data types are wanted.
|
||||
* @return an array of IDs for the pointer data types in the category.
|
||||
* @throws IOException if the database can't be accessed.
|
||||
*/
|
||||
abstract Field[] getRecordIdsInCategory(long categoryID) throws IOException;
|
||||
|
||||
DBRecord translateRecord(DBRecord rec) {
|
||||
return rec;
|
||||
}
|
||||
|
||||
class TranslatedRecordIterator implements RecordIterator {
|
||||
private RecordIterator it;
|
||||
|
||||
TranslatedRecordIterator(RecordIterator it) {
|
||||
this.it = it;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() throws IOException {
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() throws IOException {
|
||||
return it.hasPrevious();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBRecord next() throws IOException {
|
||||
DBRecord rec = it.next();
|
||||
return translateRecord(rec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBRecord previous() throws IOException {
|
||||
DBRecord rec = it.previous();
|
||||
return translateRecord(rec);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,14 +22,15 @@ import ghidra.util.exception.VersionException;
|
|||
|
||||
/**
|
||||
* Version 0 implementation for the accessing the pointer database table.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class PointerDBAdapterV0 extends PointerDBAdapter {
|
||||
final static int VERSION = 0;
|
||||
|
||||
static final int OLD_PTR_DTD_COL = 0;
|
||||
static final int OLD_PTR_SIZE_COL = 1;
|
||||
static final int V0_PTR_DTD_COL_ = 0;
|
||||
static final int V0_PTR_SIZE_COL = 1;
|
||||
|
||||
// Keep for reference
|
||||
// static final Schema SCHEMA = new Schema(VERSION, "Pointer ID",
|
||||
// new Class[] {LongField.class, IntField.class},
|
||||
// new String[] {"Data Type ID", "Size"});
|
||||
|
@ -60,7 +61,7 @@ class PointerDBAdapterV0 extends PointerDBAdapter {
|
|||
|
||||
@Override
|
||||
RecordIterator getRecords() throws IOException {
|
||||
return new TranslatedRecordIterator(table.iterator());
|
||||
return new TranslatedRecordIterator(table.iterator(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -79,13 +80,14 @@ class PointerDBAdapterV0 extends PointerDBAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
DBRecord translateRecord(DBRecord oldRec) {
|
||||
public DBRecord translateRecord(DBRecord oldRec) {
|
||||
if (oldRec == null) {
|
||||
return null;
|
||||
}
|
||||
DBRecord rec = PointerDBAdapter.SCHEMA.createRecord(oldRec.getKey());
|
||||
rec.setLongValue(PTR_DT_ID_COL, oldRec.getLongValue(OLD_PTR_DTD_COL));
|
||||
rec.setLongValue(PTR_DT_ID_COL, oldRec.getLongValue(V0_PTR_DTD_COL_));
|
||||
rec.setLongValue(PTR_CATEGORY_COL, 0);
|
||||
rec.setByteValue(PTR_LENGTH_COL, (byte) -1);
|
||||
return rec;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,11 +26,13 @@ import ghidra.util.exception.VersionException;
|
|||
class PointerDBAdapterV1 extends PointerDBAdapter {
|
||||
final static int VERSION = 1;
|
||||
|
||||
static final int OLD_PTR_DT_ID_COL = 0;
|
||||
static final int OLD_PTR_CATEGORY_COL = 1;
|
||||
static final Schema V1_SCHEMA =
|
||||
new Schema(VERSION, "Pointer ID", new Field[] { LongField.INSTANCE, LongField.INSTANCE },
|
||||
new String[] { "Data Type ID", "Category ID" });
|
||||
static final int V1_PTR_DT_ID_COL = 0;
|
||||
static final int V1_PTR_CATEGORY_COL = 1;
|
||||
|
||||
// Keep for reference
|
||||
// static final Schema V1_SCHEMA =
|
||||
// new Schema(VERSION, "Pointer ID", new Field[] { LongField.INSTANCE, LongField.INSTANCE },
|
||||
// new String[] { "Data Type ID", "Category ID" });
|
||||
|
||||
private Table table;
|
||||
|
||||
|
@ -49,13 +51,13 @@ class PointerDBAdapterV1 extends PointerDBAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
DBRecord translateRecord(DBRecord oldRec) {
|
||||
public DBRecord translateRecord(DBRecord oldRec) {
|
||||
if (oldRec == null) {
|
||||
return null;
|
||||
}
|
||||
DBRecord rec = PointerDBAdapter.SCHEMA.createRecord(oldRec.getKey());
|
||||
rec.setLongValue(PTR_DT_ID_COL, oldRec.getLongValue(OLD_PTR_DT_ID_COL));
|
||||
rec.setLongValue(PTR_CATEGORY_COL, oldRec.getLongValue(OLD_PTR_CATEGORY_COL));
|
||||
rec.setLongValue(PTR_DT_ID_COL, oldRec.getLongValue(V1_PTR_DT_ID_COL));
|
||||
rec.setLongValue(PTR_CATEGORY_COL, oldRec.getLongValue(V1_PTR_CATEGORY_COL));
|
||||
rec.setByteValue(PTR_LENGTH_COL, (byte) -1);
|
||||
return rec;
|
||||
}
|
||||
|
@ -72,7 +74,7 @@ class PointerDBAdapterV1 extends PointerDBAdapter {
|
|||
|
||||
@Override
|
||||
RecordIterator getRecords() throws IOException {
|
||||
return new TranslatedRecordIterator(table.iterator());
|
||||
return new TranslatedRecordIterator(table.iterator(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -87,7 +89,7 @@ class PointerDBAdapterV1 extends PointerDBAdapter {
|
|||
|
||||
@Override
|
||||
Field[] getRecordIdsInCategory(long categoryID) throws IOException {
|
||||
return table.findRecords(new LongField(categoryID), OLD_PTR_CATEGORY_COL);
|
||||
return table.findRecords(new LongField(categoryID), V1_PTR_CATEGORY_COL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -86,7 +86,10 @@ class PointerDBAdapterV2 extends PointerDBAdapter {
|
|||
@Override
|
||||
void deleteTable(DBHandle handle) throws IOException {
|
||||
handle.deleteTable(POINTER_TABLE_NAME);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBRecord translateRecord(DBRecord rec) {
|
||||
return rec;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,16 +15,15 @@
|
|||
*/
|
||||
package ghidra.program.database.map;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import db.DBConstants;
|
||||
import db.DBHandle;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* Database adapter for address map
|
||||
|
|
|
@ -24,9 +24,9 @@ public interface Enum extends DataType {
|
|||
|
||||
/**
|
||||
* Get the value for the given name.
|
||||
* @param name name of the entry
|
||||
* @return the value
|
||||
* @throws NoSuchElementException if the name does not exist in this Enum
|
||||
* @param name name of the entry.
|
||||
* @return the value.
|
||||
* @throws NoSuchElementException if the name does not exist in this Enum.
|
||||
*/
|
||||
public long getValue(String name) throws NoSuchElementException;
|
||||
|
||||
|
@ -39,11 +39,11 @@ public interface Enum extends DataType {
|
|||
|
||||
/**
|
||||
* 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
|
||||
* @param name name of the entry.
|
||||
* @return the comment or the empty string if the name does not exist in this enum or if no
|
||||
* comment is set.
|
||||
*/
|
||||
public String getComment(String name) throws NoSuchElementException;
|
||||
public String getComment(String name);
|
||||
|
||||
/**
|
||||
* Get the values of the enum entries.
|
||||
|
@ -52,17 +52,15 @@ public interface Enum extends DataType {
|
|||
public long[] getValues();
|
||||
|
||||
/**
|
||||
* Get the names of the enum entries.
|
||||
* Get the names of the enum entries. The returned names are sorted using String's natural
|
||||
* sort order.
|
||||
* @return the names of the enum entries.
|
||||
*/
|
||||
public String[] getNames();
|
||||
|
||||
/**
|
||||
* Get the comments of the enum entries.
|
||||
*/
|
||||
public String[] getComments();
|
||||
|
||||
/**
|
||||
* Get the number of entries in this Enum.
|
||||
* Get the number of entries in this Enum.
|
||||
* @return the number of entries in this Enum.
|
||||
*/
|
||||
public int getCount();
|
||||
|
||||
|
@ -82,14 +80,14 @@ public interface Enum extends DataType {
|
|||
public void add(String name, long value, String comment);
|
||||
|
||||
/**
|
||||
* Remove the enum entry with the given name.
|
||||
* Remove the enum entry with the given name.
|
||||
* @param name name of entry to remove.
|
||||
*/
|
||||
public void remove(String name);
|
||||
|
||||
/**
|
||||
* Set the description for this Enum.
|
||||
* @param description
|
||||
* @param description the description
|
||||
*/
|
||||
@Override
|
||||
public void setDescription(String description);
|
||||
|
@ -98,6 +96,7 @@ public interface Enum extends DataType {
|
|||
* Get enum representation of the big-endian value.
|
||||
* @param bigInt BigInteger value with the appropriate sign
|
||||
* @param settings integer format settings (PADDING, FORMAT, etc.)
|
||||
* @param bitLength the bit length
|
||||
* @return formatted integer string
|
||||
*/
|
||||
public String getRepresentation(BigInteger bigInt, Settings settings, int bitLength);
|
||||
|
|
|
@ -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,6 +18,8 @@ package ghidra.program.model.data;
|
|||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.docking.settings.SettingsDefinition;
|
||||
import ghidra.program.database.data.DataTypeUtilities;
|
||||
|
@ -95,12 +97,12 @@ public class EnumDataType extends GenericDataType implements Enum {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getComment(String valueName) throws NoSuchElementException {
|
||||
String valueNameComment = commentMap.get(valueName);
|
||||
if (valueNameComment == null) {
|
||||
valueNameComment = "";
|
||||
public String getComment(String valueName) {
|
||||
String comment = commentMap.get(valueName);
|
||||
if (comment == null) {
|
||||
comment = "";
|
||||
}
|
||||
return valueNameComment;
|
||||
return comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -117,11 +119,6 @@ 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();
|
||||
|
@ -129,28 +126,25 @@ public class EnumDataType extends GenericDataType implements Enum {
|
|||
|
||||
@Override
|
||||
public void add(String valueName, long value) {
|
||||
String valueNameComment = "";
|
||||
add(valueName, value, valueNameComment);
|
||||
add(valueName, value, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(String valueName, long value, String valueNameComment) {
|
||||
public void add(String valueName, long value, String comment) {
|
||||
bitGroups = null;
|
||||
checkValue(value);
|
||||
if (nameMap.containsKey(valueName)) {
|
||||
throw new IllegalArgumentException(valueName + " already exists in this enum");
|
||||
}
|
||||
|
||||
nameMap.put(valueName, value);
|
||||
List<String> list = valueMap.get(value);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
valueMap.put(value, list);
|
||||
}
|
||||
List<String> list = valueMap.computeIfAbsent(value, v -> new ArrayList<>());
|
||||
list.add(valueName);
|
||||
if (valueNameComment == null) {
|
||||
valueNameComment = "";
|
||||
|
||||
if (!StringUtils.isBlank(comment)) {
|
||||
commentMap.put(valueName, comment);
|
||||
}
|
||||
commentMap.put(valueName, valueNameComment);
|
||||
|
||||
}
|
||||
|
||||
private void checkValue(long value) {
|
||||
|
@ -180,21 +174,24 @@ public class EnumDataType extends GenericDataType implements Enum {
|
|||
public void remove(String valueName) {
|
||||
bitGroups = null;
|
||||
Long value = nameMap.get(valueName);
|
||||
if (value != null) {
|
||||
nameMap.remove(valueName);
|
||||
List<String> list = valueMap.get(value);
|
||||
Iterator<String> iter = list.iterator();
|
||||
while (iter.hasNext()) {
|
||||
if (valueName.equals(iter.next())) {
|
||||
iter.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (list.isEmpty()) {
|
||||
valueMap.remove(value);
|
||||
}
|
||||
commentMap.remove(valueName);
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
nameMap.remove(valueName);
|
||||
List<String> list = valueMap.get(value);
|
||||
Iterator<String> iter = list.iterator();
|
||||
while (iter.hasNext()) {
|
||||
if (valueName.equals(iter.next())) {
|
||||
iter.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (list.isEmpty()) {
|
||||
valueMap.remove(value);
|
||||
}
|
||||
|
||||
commentMap.remove(valueName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -231,11 +228,11 @@ public class EnumDataType extends GenericDataType implements Enum {
|
|||
|
||||
public void setLength(int length) {
|
||||
String[] names = getNames();
|
||||
for (String enumName : names) {
|
||||
long value = getValue(enumName);
|
||||
for (String valueName : names) {
|
||||
long value = getValue(valueName);
|
||||
if (isTooBig(length, value)) {
|
||||
throw new IllegalArgumentException("Setting the length of this Enum to a size " +
|
||||
"that cannot contain the current value for \"" + enumName + "\" of " +
|
||||
"that cannot contain the current value for \"" + valueName + "\" of " +
|
||||
Long.toHexString(value));
|
||||
}
|
||||
}
|
||||
|
@ -327,7 +324,7 @@ public class EnumDataType extends GenericDataType implements Enum {
|
|||
return "0";
|
||||
}
|
||||
List<BitGroup> list = getBitGroups();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (BitGroup bitGroup : list) {
|
||||
long subValue = bitGroup.getMask() & value;
|
||||
if (subValue != 0) {
|
||||
|
@ -372,30 +369,45 @@ public class EnumDataType extends GenericDataType implements Enum {
|
|||
if (dt == null || !(dt instanceof Enum)) {
|
||||
return false;
|
||||
}
|
||||
Enum enumm = (Enum) dt;
|
||||
|
||||
Enum enumm = (Enum) dt;
|
||||
if (!DataTypeUtilities.equalsIgnoreConflict(name, enumm.getName()) ||
|
||||
length != enumm.getLength() || getCount() != enumm.getCount()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isEachValueEquivalent(enumm)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isEachValueEquivalent(Enum enumm) {
|
||||
String[] names = getNames();
|
||||
String[] otherNames = enumm.getNames();
|
||||
try {
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (!names[i].equals(otherNames[i])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long value = getValue(names[i]);
|
||||
long otherValue = enumm.getValue(names[i]);
|
||||
if (value != otherValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String comment = getComment(names[i]);
|
||||
String otherComment = enumm.getComment(names[i]);
|
||||
if (!names[i].equals(otherNames[i]) || value != otherValue ||
|
||||
!comment.equals(otherComment)) {
|
||||
if (!comment.equals(otherComment)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (NoSuchElementException e) {
|
||||
return false; // named element not found
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -410,14 +422,14 @@ public class EnumDataType extends GenericDataType implements Enum {
|
|||
commentMap = new HashMap<>();
|
||||
setLength(enumm.getLength());
|
||||
String[] names = enumm.getNames();
|
||||
for (String name2 : names) {
|
||||
add(name2, enumm.getValue(name2), enumm.getComment(name2));
|
||||
for (String valueName : names) {
|
||||
add(valueName, enumm.getValue(valueName), enumm.getComment(valueName));
|
||||
}
|
||||
stateChanged(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultLabelPrefix() {
|
||||
return name == null ? null : name.toUpperCase();
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue