From 88b7867fc85af824a0320d805631e97322fbacdc Mon Sep 17 00:00:00 2001 From: Milan Mimica Date: Mon, 20 Nov 2023 11:57:14 +0100 Subject: [PATCH] Allow arbitrary expression IDs (closes #163) (#164) Co-authored-by: Milan Mimica --- .../gliwka/hyperscan/wrapper/Database.java | 29 +++++++++---------- .../gliwka/hyperscan/wrapper/Expression.java | 22 +++++++------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/gliwka/hyperscan/wrapper/Database.java b/src/main/java/com/gliwka/hyperscan/wrapper/Database.java index 7b87e78..07368e5 100644 --- a/src/main/java/com/gliwka/hyperscan/wrapper/Database.java +++ b/src/main/java/com/gliwka/hyperscan/wrapper/Database.java @@ -19,7 +19,7 @@ * Database containing compiled expressions ready for scanning using the Scanner */ public class Database implements Closeable { - private final Expression[] expressions; + private final Map expressions; private final int expressionCount; private NativeDatabase database; @@ -38,13 +38,17 @@ private Database(NativeDatabase database, List expressions) { boolean hasIds = expressions.get(0).getId() != null; + this.expressions = new HashMap<>(expressionCount); if (hasIds) { - int maxId = expressions.stream().mapToInt(Expression::getId).max().getAsInt(); - this.expressions = new Expression[maxId + 1]; - - expressions.forEach(expression -> this.expressions[expression.getId()] = expression); + for (Expression expression : expressions) { + if (this.expressions.put(expression.getId(), expression) != null) + throw new IllegalStateException("Expression ID must be unique within a Database."); + } } else { - this.expressions = expressions.toArray(new Expression[0]); + int i = 0; + for (Expression expression : expressions) { + this.expressions.put(i++, expression); + } } } @@ -94,7 +98,6 @@ public static Database compile(List expressions) throws CompileError throw new IllegalStateException("You can't mix expressions with and without id's in a single database"); } - for (int i = 0; i < expressionsSize; i++) { flags[i] = expressions.get(i).getFlagBits(); @@ -141,11 +144,7 @@ public long getSize() { } Expression getExpression(int id) { - return expressions[id]; - } - - int getExpressionCount() { - return expressionCount; + return expressions.get(id); } @Override @@ -179,7 +178,7 @@ public void save(OutputStream expressionsOut, OutputStream databaseOut) throws I DataOutputStream expressionsDataOut = new DataOutputStream(expressionsOut); // How many expressions will be present. We need this to know when to stop reading. expressionsDataOut.writeInt(expressionCount); - for (Expression expression : expressions) { + for (Expression expression : expressions.values()) { if (expression == null) { continue; } @@ -289,13 +288,13 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Database database = (Database) o; - return expressionCount == database.expressionCount && Arrays.deepEquals(expressions, database.expressions); + return expressionCount == database.expressionCount && expressions.equals(database.expressions); } @Override public int hashCode() { int result = Objects.hash(expressionCount); - result = 31 * result + Arrays.hashCode(expressions); + result = 31 * result + expressions.hashCode(); return result; } } diff --git a/src/main/java/com/gliwka/hyperscan/wrapper/Expression.java b/src/main/java/com/gliwka/hyperscan/wrapper/Expression.java index 390b1ca..c884da1 100644 --- a/src/main/java/com/gliwka/hyperscan/wrapper/Expression.java +++ b/src/main/java/com/gliwka/hyperscan/wrapper/Expression.java @@ -16,8 +16,8 @@ @ToString public class Expression { @Getter @NonNull private final String expression; - @Getter private EnumSet flags = EnumSet.of(ExpressionFlag.NO_FLAG); - @Getter private Integer id; + @Getter private final EnumSet flags; + @Getter private final Integer id; /** * Represents the validation results for a expression @@ -37,34 +37,32 @@ public static class ValidationResult { } public Expression(@NonNull String expression) { - this.expression = expression; + this(expression, EnumSet.of(ExpressionFlag.NO_FLAG), null); } public Expression(@NonNull String expression, Integer id) { - this.expression = expression; - this.id = id; + this(expression, EnumSet.of(ExpressionFlag.NO_FLAG), id); } public Expression(@NonNull String expression, @NonNull EnumSet flags) { - this.expression = expression; - this.flags = flags; + this(expression, flags, null); } public Expression(@NonNull String expression, @NonNull ExpressionFlag flag) { - this.expression = expression; - this.flags = EnumSet.of(flag); + this(expression, EnumSet.of(flag), null); } public Expression(@NonNull String expression, @NonNull EnumSet flags, Integer id) { + if (id != null && id < 0) + throw new IllegalArgumentException("id must be >=0: " + id); + this.expression = expression; this.flags = flags; this.id = id; } public Expression(@NonNull String expression, @NonNull ExpressionFlag flag, Integer id) { - this.expression = expression; - this.flags = EnumSet.of(flag); - this.id = id; + this(expression, EnumSet.of(flag), id); } public ValidationResult validate() {