Skip to content

Commit f6a5065

Browse files
authored
Merge branch 'dev/patch' into fix-turkish-lang
2 parents a2f32ea + 9111b87 commit f6a5065

File tree

4 files changed

+132
-28
lines changed

4 files changed

+132
-28
lines changed

src/main/java/ch/njol/skript/classes/data/DefaultOperations.java

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,53 @@ public class DefaultOperations {
3232
static {
3333
// Number - Number
3434
Arithmetics.registerOperation(Operator.ADDITION, Number.class, (left, right) -> {
35-
if (Utils.isInteger(left, right))
36-
return left.longValue() + right.longValue();
35+
if (Utils.isInteger(left, right)) {
36+
long result = left.longValue() + right.longValue();
37+
// catches overflow, from Math.addExact(long, long)
38+
if (((left.longValue() ^ result) & (right.longValue() ^ result)) >= 0)
39+
return result;
40+
}
3741
return left.doubleValue() + right.doubleValue();
3842
});
3943
Arithmetics.registerOperation(Operator.SUBTRACTION, Number.class, (left, right) -> {
40-
if (Utils.isInteger(left, right))
41-
return left.longValue() - right.longValue();
44+
if (Utils.isInteger(left, right)) {
45+
long result = left.longValue() - right.longValue();
46+
// catches overflow, from Math.addExact(long, long)
47+
if (((left.longValue() ^ result) & (right.longValue() ^ result)) >= 0)
48+
return result;
49+
}
4250
return left.doubleValue() - right.doubleValue();
4351
});
4452
Arithmetics.registerOperation(Operator.MULTIPLICATION, Number.class, (left, right) -> {
45-
if (Utils.isInteger(left, right))
46-
return left.longValue() * right.longValue();
47-
return left.doubleValue() * right.doubleValue();
53+
if (!Utils.isInteger(left, right))
54+
return left.doubleValue() * right.doubleValue();
55+
56+
// catch overflow, from Math.multiplyExact(long, long)
57+
long longLeft = left.longValue();
58+
long longRight = right.longValue();
59+
long ax = Math.abs(longLeft);
60+
long ay = Math.abs(longRight);
61+
62+
long result = left.longValue() * right.longValue();
63+
64+
if (((ax | ay) >>> 31 != 0)) {
65+
// Some bits greater than 2^31 that might cause overflow
66+
// Check the result using the divide operator
67+
// and check for the special case of Long.MIN_VALUE * -1
68+
if (((longRight != 0) && (result / longRight != longLeft)) ||
69+
(longLeft == Long.MIN_VALUE && longRight == -1)) {
70+
return left.doubleValue() * right.doubleValue();
71+
}
72+
}
73+
return result;
4874
});
4975
Arithmetics.registerOperation(Operator.DIVISION, Number.class, (left, right) -> left.doubleValue() / right.doubleValue());
5076
Arithmetics.registerOperation(Operator.EXPONENTIATION, Number.class, (left, right) -> Math.pow(left.doubleValue(), right.doubleValue()));
5177
Arithmetics.registerDifference(Number.class, (left, right) -> {
52-
if (Utils.isInteger(left, right))
53-
return Math.abs(left.longValue() - right.longValue());
54-
return Math.abs(left.doubleValue() - right.doubleValue());
78+
double result = Math.abs(left.doubleValue() - right.doubleValue());
79+
if (Utils.isInteger(left, right) && result < Long.MAX_VALUE && result > Long.MIN_VALUE)
80+
return (long) result;
81+
return result;
5582
});
5683
Arithmetics.registerDefaultValue(Number.class, () -> 0L);
5784

src/main/java/ch/njol/skript/expressions/ExprJoinSplit.java

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
package ch.njol.skript.expressions;
2020

2121
import java.util.regex.Pattern;
22+
import java.util.regex.PatternSyntaxException;
2223

2324
import ch.njol.skript.SkriptConfig;
25+
import ch.njol.skript.lang.Literal;
2426
import org.bukkit.event.Event;
2527
import org.jetbrains.annotations.Nullable;
2628

@@ -36,14 +38,11 @@
3638
import ch.njol.util.Kleenean;
3739
import ch.njol.util.StringUtils;
3840

39-
/**
40-
* @author Peter Güttinger
41-
*/
4241
@Name("Join & Split")
4342
@Description("Joins several texts with a common delimiter (e.g. \", \"), or splits a text into multiple texts at a given delimiter.")
4443
@Examples({
45-
"message \"Online players: %join all players with \"\" | \"\"%\" # %all players% would use the default \"x, y, and z\"",
46-
"set {_s::*} to the string argument split at \",\""
44+
"message \"Online players: %join all players' names with \"\" | \"\"%\" # %all players% would use the default \"x, y, and z\"",
45+
"set {_s::*} to the string argument split at \",\""
4746
})
4847
@Since("2.1, 2.5.2 (regex support), 2.7 (case sensitivity)")
4948
public class ExprJoinSplit extends SimpleExpression<String> {
@@ -61,33 +60,47 @@ public class ExprJoinSplit extends SimpleExpression<String> {
6160
private boolean regex;
6261
private boolean caseSensitivity;
6362

64-
@SuppressWarnings("null")
6563
private Expression<String> strings;
66-
@Nullable
67-
private Expression<String> delimiter;
64+
private @Nullable Expression<String> delimiter;
65+
66+
private @Nullable Pattern pattern;
6867

6968
@Override
70-
@SuppressWarnings({"unchecked", "null"})
7169
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
7270
join = matchedPattern == 0;
7371
regex = matchedPattern >= 3;
7472
caseSensitivity = SkriptConfig.caseSensitive.value() || parseResult.hasTag("case");
73+
//noinspection unchecked
7574
strings = (Expression<String>) exprs[0];
75+
//noinspection unchecked
7676
delimiter = (Expression<String>) exprs[1];
77+
if (!join && delimiter instanceof Literal) {
78+
String stringPattern = ((Literal<String>) delimiter).getSingle();
79+
try {
80+
this.pattern = compilePattern(stringPattern);
81+
} catch (PatternSyntaxException e) {
82+
Skript.error("'" + stringPattern + "' is not a valid regular expression");
83+
return false;
84+
}
85+
}
7786
return true;
7887
}
7988

8089
@Override
81-
@Nullable
82-
protected String[] get(Event event) {
90+
protected String @Nullable [] get(Event event) {
8391
String[] strings = this.strings.getArray(event);
8492
String delimiter = this.delimiter != null ? this.delimiter.getSingle(event) : "";
8593
if (strings.length == 0 || delimiter == null)
8694
return new String[0];
87-
if (join) {
95+
if (join)
8896
return new String[] {StringUtils.join(strings, delimiter)};
89-
} else {
90-
return strings[0].split(regex ? delimiter : (caseSensitivity ? "" : "(?i)") + Pattern.quote(delimiter), -1);
97+
try {
98+
Pattern pattern = this.pattern;
99+
if (pattern == null)
100+
pattern = compilePattern(delimiter);
101+
return pattern.split(strings[0], -1);
102+
} catch (PatternSyntaxException e) {
103+
return new String[0];
91104
}
92105
}
93106

@@ -103,10 +116,28 @@ public Class<? extends String> getReturnType() {
103116

104117
@Override
105118
public String toString(@Nullable Event event, boolean debug) {
106-
if (join)
107-
return "join " + strings.toString(event, debug) + (delimiter != null ? " with " + delimiter.toString(event, debug) : "");
108-
return (regex ? "regex " : "") + "split " + strings.toString(event, debug) + (delimiter != null ? " at " + delimiter.toString(event, debug) : "")
109-
+ (regex ? "" : "(case sensitive: " + caseSensitivity + ")");
119+
StringBuilder builder = new StringBuilder();
120+
if (join) {
121+
builder.append("join ").append(strings.toString(event, debug));
122+
if (delimiter != null)
123+
builder.append(" with ").append(delimiter.toString(event, debug));
124+
return builder.toString();
125+
}
126+
127+
assert delimiter != null;
128+
if (regex)
129+
builder.append("regex ");
130+
builder.append("split ")
131+
.append(strings.toString(event, debug))
132+
.append(" at ")
133+
.append(delimiter.toString(event, debug));
134+
if (!regex)
135+
builder.append(" (case sensitive: ").append(caseSensitivity).append(")");
136+
return builder.toString();
137+
}
138+
139+
private Pattern compilePattern(String delimiter) {
140+
return Pattern.compile(regex ? delimiter : (caseSensitivity ? "" : "(?i)") + Pattern.quote(delimiter));
110141
}
111142

112143
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
test "regex exceptions not handled":
2+
parse:
3+
set {_split::*} to regex split "test" at "\b{_name}\b"
4+
assert last parse logs is "'\b{_name}\b' is not a valid regular expression" with "regex split did not error with invalid regex literal"
5+
6+
set {_pattern} to "\b{_name}\b"
7+
set {_split::*} to regex split "test" at {_pattern}
8+
assert {_split::*} is not set with "regex split returned a value with invalid regex expression"
9+
10+
assert regex split "apple,banana;cherry" at "[,;]" is "apple", "banana" and "cherry" with "regex split did not split correctly with literal"
11+
set {_pattern} to "[,;]"
12+
assert regex split "apple,banana;cherry" at {_pattern} is "apple", "banana" and "cherry" with "regex split did not split correctly with expression"
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
test "long overflow, addition":
2+
set {_double-const} to 9000000000000000000.0
3+
set {_long-const} to 9000000000000000000
4+
5+
loop 100 times:
6+
set {_double} to {_double} + {_double-const}
7+
set {_long} to {_long} + {_long-const}
8+
assert {_double} is {_long} with "long value did not overflow to a double"
9+
10+
assert {_long} is 9000000000000000000 * 100.0 with "wrong final value"
11+
12+
test "long underflow, subtraction":
13+
set {_double-const} to 9000000000000000000.0
14+
set {_long-const} to 9000000000000000000
15+
16+
loop 100 times:
17+
set {_double} to {_double} - {_double-const}
18+
set {_long} to {_long} - {_long-const}
19+
assert {_double} is {_long} with "long value did not overflow to a double"
20+
21+
assert {_long} is 9000000000000000000 * -100.0 with "wrong final value"
22+
23+
test "long overflow, multiplication":
24+
set {_double} to 10.0
25+
set {_long} to 10
26+
27+
loop 100 times:
28+
set {_double} to {_double} * 10
29+
set {_long} to {_long} * 10
30+
assert {_double} is {_long} with "long value did not overflow to a double"
31+
32+
# the 6 is due to floating point error
33+
assert {_long} is 100000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000 with "wrong final value"
34+

0 commit comments

Comments
 (0)