diff --git a/realscoreboard-api/pom.xml b/realscoreboard-api/pom.xml index 3e07ddc..def0d10 100644 --- a/realscoreboard-api/pom.xml +++ b/realscoreboard-api/pom.xml @@ -102,5 +102,11 @@ 1.18.46 compile + + junit + junit + 4.13.2 + test + - \ No newline at end of file + diff --git a/realscoreboard-api/src/main/java/joserodpt/realscoreboard/api/conditions/Condition.java b/realscoreboard-api/src/main/java/joserodpt/realscoreboard/api/conditions/Condition.java index 416a1e9..45f6a53 100644 --- a/realscoreboard-api/src/main/java/joserodpt/realscoreboard/api/conditions/Condition.java +++ b/realscoreboard-api/src/main/java/joserodpt/realscoreboard/api/conditions/Condition.java @@ -19,9 +19,21 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import java.util.regex.Pattern; + @Getter @Setter public class Condition { + private static final Pattern NUMBER_PATTERN = Pattern.compile( + "[+-]?(?:" + + "NaN|Infinity|" + + "(?:" + + "(?:[0-9]+(?:\\.[0-9]*)?|\\.[0-9]+)(?:[eE][+-]?[0-9]+)?|" + + "0[xX](?:[0-9a-fA-F]+(?:\\.[0-9a-fA-F]*)?|\\.[0-9a-fA-F]+)[pP][+-]?[0-9]+" + + ")[fFdD]?" + + ")" + ); + private String condition, met, notMet; private RealScoreboardAPI rsa; @@ -54,20 +66,15 @@ public boolean parseExpression(String expression) { return evaluate(left, operator, right); } - // Helper method to parse operands as integers, doubles, booleans, or strings + // Helper method to parse operands as numbers, booleans, or strings private Object parseValue(String value) { - // Try to parse as an integer - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - // Not an integer, continue + Integer integer = parseInteger(value); + if (integer != null) { + return integer; } - // Try to parse as a double - try { + if (NUMBER_PATTERN.matcher(value).matches()) { return Double.parseDouble(value); - } catch (NumberFormatException e) { - // Not a double, continue } // Try to parse as a boolean @@ -79,6 +86,43 @@ private Object parseValue(String value) { return value; } + private Integer parseInteger(String value) { + if (value == null || value.isEmpty()) { + return null; + } + + int index = 0; + boolean negative = false; + char first = value.charAt(0); + if (first == '-' || first == '+') { + negative = first == '-'; + index++; + } + + if (index == value.length()) { + return null; + } + + int limit = negative ? Integer.MIN_VALUE : -Integer.MAX_VALUE; + int multiplicationLimit = limit / 10; + int result = 0; + + while (index < value.length()) { + int digit = Character.digit(value.charAt(index++), 10); + if (digit < 0 || result < multiplicationLimit) { + return null; + } + + result *= 10; + if (result < limit + digit) { + return null; + } + result -= digit; + } + + return negative ? result : -result; + } + // Helper method to evaluate the expression based on the operator private boolean evaluate(Object left, String operator, Object right) { // Handle numeric comparisons (Integer and Double) diff --git a/realscoreboard-api/src/test/java/joserodpt/realscoreboard/api/conditions/ConditionTest.java b/realscoreboard-api/src/test/java/joserodpt/realscoreboard/api/conditions/ConditionTest.java new file mode 100644 index 0000000..f67365e --- /dev/null +++ b/realscoreboard-api/src/test/java/joserodpt/realscoreboard/api/conditions/ConditionTest.java @@ -0,0 +1,41 @@ +package joserodpt.realscoreboard.api.conditions; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class ConditionTest { + private final Condition condition = new Condition(null, "", "", ""); + + @Test + public void evaluatesTextWithoutChangingStringOperators() { + assertTrue(condition.parseExpression("compact == compact")); + assertTrue(condition.parseExpression("full != compact")); + assertTrue(condition.parseExpression("compact startsWith comp")); + assertTrue(condition.parseExpression("full contains ull")); + assertTrue(condition.parseExpression("1.2.3 == 1.2.3")); + assertFalse(condition.parseExpression("compact == full")); + } + + @Test + public void preservesIntegerAndFloatingPointComparisons() { + assertTrue(condition.parseExpression("2147483647 == 2147483647")); + assertTrue(condition.parseExpression("-2147483648 == -2147483648")); + assertTrue(condition.parseExpression("\u0661 == 1")); + assertTrue(condition.parseExpression("2147483648 > 2147483647")); + assertTrue(condition.parseExpression("1.25 < 1.5")); + assertTrue(condition.parseExpression("1e3 == 1000")); + assertTrue(condition.parseExpression("1f == 1")); + assertTrue(condition.parseExpression("0x1.0p2 == 4")); + assertTrue(condition.parseExpression("Infinity > 1")); + assertFalse(condition.parseExpression("NaN == NaN")); + } + + @Test + public void preservesBooleanComparisons() { + assertTrue(condition.parseExpression("true == true")); + assertTrue(condition.parseExpression("true != false")); + assertFalse(condition.parseExpression("false != false")); + } +}