mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
Merge remote-tracking branch 'origin/GP-3112_Dan_destroyTupleRecord'
This commit is contained in:
@@ -1,51 +0,0 @@
|
|||||||
/* ###
|
|
||||||
* 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 generic;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public interface ComparableTupleRecord<T extends ComparableTupleRecord<T>>
|
|
||||||
extends TupleRecord<T>, Comparable<T> {
|
|
||||||
List<Function<T, ? extends Comparable<?>>> getComparableFieldAccessors();
|
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
||||||
@Override
|
|
||||||
default List<Function<T, ?>> getFieldAccessors() {
|
|
||||||
return (List) getComparableFieldAccessors();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
|
||||||
default int compareTo(T that) {
|
|
||||||
if (that == null) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int result = this.getClass().hashCode() - that.getClass().hashCode();
|
|
||||||
if (result != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
for (Function<T, ? extends Comparable<?>> field : getComparableFieldAccessors()) {
|
|
||||||
Comparable vthis = field.apply((T) this);
|
|
||||||
Comparable vthat = field.apply(that);
|
|
||||||
result = vthis.compareTo(vthat);
|
|
||||||
if (result != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/* ###
|
|
||||||
* 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 generic;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public interface TupleRecord<T extends TupleRecord<T>> {
|
|
||||||
List<Function<T, ?>> getFieldAccessors();
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
default boolean doEquals(Object that) {
|
|
||||||
if (!this.getClass().equals(that.getClass())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (Function<T, ?> field : getFieldAccessors()) {
|
|
||||||
if (!Objects.equals(field.apply((T) this), field.apply((T) that))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
default int doHashCode() {
|
|
||||||
int hash = 1;
|
|
||||||
for (Function<T, ?> field : getFieldAccessors()) {
|
|
||||||
hash *= 31;
|
|
||||||
Object val = field.apply((T) this);
|
|
||||||
if (val == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
hash += val.hashCode();
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,12 +19,9 @@ import java.beans.PropertyEditor;
|
|||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import generic.ComparableTupleRecord;
|
|
||||||
import generic.theme.GColor;
|
import generic.theme.GColor;
|
||||||
import ghidra.framework.options.annotation.*;
|
import ghidra.framework.options.annotation.*;
|
||||||
import ghidra.framework.plugintool.Plugin;
|
import ghidra.framework.plugintool.Plugin;
|
||||||
@@ -33,71 +30,43 @@ import ghidra.util.HelpLocation;
|
|||||||
|
|
||||||
public interface AutoOptions {
|
public interface AutoOptions {
|
||||||
|
|
||||||
static class CategoryAndName implements ComparableTupleRecord<CategoryAndName> {
|
record CategoryAndName(String category, String name) implements Comparable<CategoryAndName> {
|
||||||
public static final List<Function<CategoryAndName, ? extends Comparable<?>>> ACCESSORS =
|
|
||||||
List.of(CategoryAndName::getCategory, CategoryAndName::getName);
|
|
||||||
|
|
||||||
private final String category;
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
protected static String getPluginPackageName(Plugin plugin) {
|
protected static String getPluginPackageName(Plugin plugin) {
|
||||||
return plugin.getPluginDescription().getPluginPackage().getName();
|
return plugin.getPluginDescription().getPluginPackage().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String computeCategory(String[] categoryNames, Plugin plugin) {
|
||||||
|
return categoryNames.length == 0
|
||||||
|
? getPluginPackageName(plugin)
|
||||||
|
: computeName(categoryNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String computeName(String[] names) {
|
||||||
|
return String.join(".", names);
|
||||||
|
}
|
||||||
|
|
||||||
public CategoryAndName(AutoOptionDefined annotation, Plugin plugin) {
|
public CategoryAndName(AutoOptionDefined annotation, Plugin plugin) {
|
||||||
String[] categoryNames = annotation.category();
|
this(computeCategory(annotation.category(), plugin), computeName(annotation.name()));
|
||||||
if (categoryNames.length == 0) {
|
|
||||||
this.category = getPluginPackageName(plugin);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.category = StringUtils.join(categoryNames, ".");
|
|
||||||
}
|
|
||||||
this.name = StringUtils.join(annotation.name(), ".");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CategoryAndName(AutoOptionConsumed annotation, Plugin plugin) {
|
public CategoryAndName(AutoOptionConsumed annotation, Plugin plugin) {
|
||||||
// Same code because annotations cannot extend one another
|
// Same code because annotations cannot extend one another
|
||||||
String[] categoryNames = annotation.category();
|
this(computeCategory(annotation.category(), plugin), computeName(annotation.name()));
|
||||||
if (categoryNames.length == 0) {
|
}
|
||||||
this.category = getPluginPackageName(plugin);
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(CategoryAndName that) {
|
||||||
|
int cmp;
|
||||||
|
cmp = this.category.compareTo(that.category);
|
||||||
|
if (cmp != 0) {
|
||||||
|
return cmp;
|
||||||
}
|
}
|
||||||
else {
|
cmp = this.name.compareTo(that.name);
|
||||||
this.category = StringUtils.join(categoryNames, ".");
|
if (cmp != 0) {
|
||||||
|
return cmp;
|
||||||
}
|
}
|
||||||
this.name = StringUtils.join(annotation.name(), ".");
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
public CategoryAndName(String category, String name) {
|
|
||||||
this.category = category;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Function<CategoryAndName, ? extends Comparable<?>>> getComparableFieldAccessors() {
|
|
||||||
return ACCESSORS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCategory() {
|
|
||||||
return category;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return doHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
return doEquals(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return category + ":" + name;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,8 +120,8 @@ public interface AutoOptions {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CategoryAndName key = new CategoryAndName(annotation, plugin);
|
CategoryAndName key = new CategoryAndName(annotation, plugin);
|
||||||
ToolOptions options = plugin.getTool().getOptions(key.getCategory());
|
ToolOptions options = plugin.getTool().getOptions(key.category);
|
||||||
if (options.isRegistered(key.getName())) {
|
if (options.isRegistered(key.name)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
f.setAccessible(true);
|
f.setAccessible(true);
|
||||||
@@ -194,7 +163,7 @@ public interface AutoOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (defaultValue instanceof GColor gColor) {
|
if (defaultValue instanceof GColor gColor) {
|
||||||
options.registerThemeColorBinding(key.getName(), gColor.getId(), help, description);
|
options.registerThemeColorBinding(key.name, gColor.getId(), help, description);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
else if ( is font option ) {
|
else if ( is font option ) {
|
||||||
@@ -208,10 +177,10 @@ public interface AutoOptions {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
else {
|
else {
|
||||||
options.registerOption(key.getName(), type, defaultValue, help, description,
|
options.registerOption(key.name, type, defaultValue, help, description,
|
||||||
editor);
|
editor);
|
||||||
// TODO: Wish Ghidra would do this upon any option registration
|
// TODO: Wish Ghidra would do this upon any option registration
|
||||||
options.putObject(key.getName(), defaultValue, type);
|
options.putObject(key.name, defaultValue, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ public class AutoOptionsListener<R> implements OptionsChangeListener {
|
|||||||
Set<OptionSetter<R>> settersForReceiver =
|
Set<OptionSetter<R>> settersForReceiver =
|
||||||
settersByOption.computeIfAbsent(key, k -> new HashSet<>());
|
settersByOption.computeIfAbsent(key, k -> new HashSet<>());
|
||||||
settersForReceiver.add((OptionSetter) setter);
|
settersForReceiver.add((OptionSetter) setter);
|
||||||
categories.add(key.getCategory());
|
categories.add(key.category());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,10 +227,10 @@ public class AutoOptionsListener<R> implements OptionsChangeListener {
|
|||||||
|
|
||||||
public void notifyCurrentValues(PluginTool tool, R receiver) {
|
public void notifyCurrentValues(PluginTool tool, R receiver) {
|
||||||
for (Map.Entry<CategoryAndName, Set<OptionSetter<R>>> ent : settersByOption
|
for (Map.Entry<CategoryAndName, Set<OptionSetter<R>>> ent : settersByOption
|
||||||
.entrySet()) {
|
.entrySet()) {
|
||||||
CategoryAndName key = ent.getKey();
|
CategoryAndName key = ent.getKey();
|
||||||
ToolOptions options = tool.getOptions(key.getCategory());
|
ToolOptions options = tool.getOptions(key.category());
|
||||||
Option opt = options.getOption(key.getName(), OptionType.NO_TYPE, null);
|
Option opt = options.getOption(key.name(), OptionType.NO_TYPE, null);
|
||||||
if (!opt.isRegistered()) {
|
if (!opt.isRegistered()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -315,7 +315,7 @@ public class AutoOptionsListener<R> implements OptionsChangeListener {
|
|||||||
public AutoOptionsListener(Plugin plugin, R receiver) {
|
public AutoOptionsListener(Plugin plugin, R receiver) {
|
||||||
this.receiver = receiver;
|
this.receiver = receiver;
|
||||||
this.profile = (ReceiverProfile<R>) PROFILES_BY_RECEIVER_CLASS
|
this.profile = (ReceiverProfile<R>) PROFILES_BY_RECEIVER_CLASS
|
||||||
.computeIfAbsent(receiver.getClass(), cls -> new ReceiverProfile<>(cls, plugin));
|
.computeIfAbsent(receiver.getClass(), cls -> new ReceiverProfile<>(cls, plugin));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user