Skip to content

Commit dd4d647

Browse files
committed
Merge pull request #373 from PseudoKnight/optimizations
Optimizations
2 parents e299493 + 304e675 commit dd4d647

File tree

7 files changed

+117
-98
lines changed

7 files changed

+117
-98
lines changed

src/main/java/com/laytonsmith/core/ArgumentValidation.java

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,13 @@
11
package com.laytonsmith.core;
22

33
import com.laytonsmith.annotations.typeof;
4-
import com.laytonsmith.core.constructs.CArray;
5-
import com.laytonsmith.core.constructs.CBoolean;
6-
import com.laytonsmith.core.constructs.CByteArray;
7-
import com.laytonsmith.core.constructs.CClassType;
8-
import com.laytonsmith.core.constructs.CDouble;
9-
import com.laytonsmith.core.constructs.CInt;
10-
import com.laytonsmith.core.constructs.CMutablePrimitive;
11-
import com.laytonsmith.core.constructs.CNull;
12-
import com.laytonsmith.core.constructs.CString;
13-
import com.laytonsmith.core.constructs.Construct;
14-
import com.laytonsmith.core.constructs.Target;
4+
import com.laytonsmith.core.constructs.*;
155
import com.laytonsmith.core.exceptions.ConfigRuntimeException;
166
import com.laytonsmith.core.functions.Exceptions;
177
import com.laytonsmith.core.natives.interfaces.ArrayAccess;
188

9+
import java.util.regex.Pattern;
10+
1911
/**
2012
* This class provides a way to validate, parse, and manipulate arguments passed
2113
* to functions in a standard, minimalist way, ultimately retrieving java
@@ -159,6 +151,36 @@ public static double getNumber(Construct c, Target t) {
159151
return d;
160152
}
161153

154+
// Matches a string that will be successfully parsed by Double.parseDouble(String)
155+
// Based on https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String-
156+
private static final Pattern VALID_DOUBLE = Pattern.compile(
157+
"[\\x00-\\x20]*" + // leading whitespace
158+
"[+-]?(" +
159+
"(" +
160+
"((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)([eE][+-]?(\\p{Digit}+))?)" +
161+
"|" +
162+
"(\\.(\\p{Digit}+)([eE][+-]?(\\p{Digit}+))?)" +
163+
"|" +
164+
// Hexadecimal strings
165+
"((" +
166+
"(0[xX](\\p{XDigit}+)(\\.)?)" +
167+
"|" +
168+
"(0[xX](\\p{XDigit}+)?(\\.)(\\p{XDigit}+))" +
169+
")[pP][+-]?(\\p{Digit}+))" +
170+
")[fFdD]?" +
171+
")[\\x00-\\x20]*" // trailing whitespace
172+
);
173+
174+
/**
175+
* Validates that a construct's value is a number or string that can be returned by GetNumber()
176+
*
177+
* @param c Construct
178+
* @return boolean
179+
*/
180+
public static boolean isNumber(Construct c) {
181+
return c instanceof CNumber || VALID_DOUBLE.matcher(c.val()).matches();
182+
}
183+
162184
/**
163185
* Alias to getNumber
164186
*

src/main/java/com/laytonsmith/core/Static.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ public static void SendMessage(final MCCommandSender m, String msg, final Target
504504
m.sendMessage(msg);
505505
} else {
506506
msg = Static.MCToANSIColors(msg);
507-
if (msg.matches("(?sm).*\033.*")) {
507+
if (msg.contains("\033")) {
508508
//We have terminal colors, we need to reset them at the end
509509
msg += TermColors.reset();
510510
}
@@ -564,19 +564,16 @@ public static String getBlockPrefix() {
564564
public static MCItemStack ParseItemNotation(String functionName, String notation, int qty, Target t) {
565565
int type = 0;
566566
short data = 0;
567-
MCItemStack is = null;
568-
if (notation.matches("\\d*:\\d*")) {
567+
MCItemStack is;
569568
String[] sData = notation.split(":");
570569
try {
571-
type = (int) Integer.parseInt(sData[0]);
570+
type = Integer.parseInt(sData[0]);
572571
if (sData.length > 1) {
573572
data = (short) Integer.parseInt(sData[1]);
574573
}
575574
} catch (NumberFormatException e) {
576-
throw new ConfigRuntimeException("Item value passed to " + functionName + " is invalid: " + notation, ExceptionType.FormatException, t);
577-
}
578-
} else {
579-
type = Static.getInt32(Static.resolveConstruct(notation, t), t);
575+
throw new ConfigRuntimeException("Item value passed to " + functionName + " is invalid: " + notation,
576+
ExceptionType.FormatException, t);
580577
}
581578

582579
is = StaticLayer.GetItemStack(type, qty);

src/main/java/com/laytonsmith/core/functions/BasicLogic.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.laytonsmith.annotations.breakable;
66
import com.laytonsmith.annotations.core;
77
import com.laytonsmith.annotations.seealso;
8+
import com.laytonsmith.core.ArgumentValidation;
89
import com.laytonsmith.core.CHVersion;
910
import com.laytonsmith.core.Optimizable;
1011
import com.laytonsmith.core.ParseTree;
@@ -782,8 +783,7 @@ public CBoolean exec(Target t, Environment env, Construct... args) throws Cancel
782783
}
783784
if(Static.anyNulls(args)){
784785
boolean equals = true;
785-
for(int i = 0; i < args.length; i++){
786-
Construct c = args[i];
786+
for(Construct c : args){
787787
if(!(c instanceof CNull)){
788788
equals = false;
789789
}
@@ -817,16 +817,22 @@ public CBoolean exec(Target t, Environment env, Construct... args) throws Cancel
817817
}
818818
}
819819
try {
820+
// Validate that these are numbers, so that getNumber doesn't throw an exception.
821+
if(!ArgumentValidation.isNumber(args[0])) {
822+
return CBoolean.FALSE;
823+
}
820824
boolean equals = true;
821825
for (int i = 1; i < args.length; i++) {
826+
if(!ArgumentValidation.isNumber(args[i])) {
827+
return CBoolean.FALSE;
828+
}
822829
double arg1 = Static.getNumber(args[i - 1], t);
823830
double arg2 = Static.getNumber(args[i], t);
824831
if (arg1 != arg2) {
825-
equals = false;
826-
break;
832+
return CBoolean.FALSE;
827833
}
828834
}
829-
return CBoolean.get(equals);
835+
return CBoolean.TRUE;
830836
} catch (ConfigRuntimeException e) {
831837
return CBoolean.FALSE;
832838
}

src/main/java/com/laytonsmith/core/functions/Cmdline.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public Boolean runAsync() {
8181
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
8282
String msg = Static.MCToANSIColors(args[0].val());
8383
StreamUtils.GetSystemOut().print(msg);
84-
if (msg.matches("(?m).*\033.*")) {
84+
if (msg.contains("\033")) {
8585
//We have color codes in it, we need to reset them
8686
StreamUtils.GetSystemOut().print(TermColors.reset());
8787
}
@@ -146,7 +146,7 @@ public Construct exec(Target t, Environment environment, Construct... args) thro
146146
String msg = Static.MCToANSIColors(args[0].val());
147147
PrintStream se = StreamUtils.GetSystemErr();
148148
se.print(msg);
149-
if (msg.matches("(?m).*\033.*")) {
149+
if (msg.contains("\033")) {
150150
//We have color codes in it, we need to reset them
151151
se.print(TermColors.reset());
152152
}

src/main/java/com/laytonsmith/core/functions/Echoes.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public Construct exec(Target t, Environment env, Construct... args) throws Cance
6161
Static.SendMessage(env.getEnv(CommandHelperEnvironment.class).GetCommandSender(), b.toString(), t);
6262
} else {
6363
String mes = Static.MCToANSIColors(b.toString());
64-
if(mes.matches("(?m).*\033.*")){
64+
if(mes.contains("\033")){
6565
//We have terminal colors, we need to reset them at the end
6666
mes += TermColors.reset();
6767
}
@@ -133,7 +133,7 @@ public Construct exec(final Target t, Environment env, final Construct... args)
133133
Static.SendMessage(p, b.toString(), t);
134134
} else {
135135
String mes = Static.MCToANSIColors(b.toString());
136-
if(mes.matches("(?m).*\033.*")){
136+
if(mes.contains("\033")){
137137
//We have terminal colors, we need to reset them at the end
138138
mes += TermColors.reset();
139139
}
@@ -614,7 +614,7 @@ public Construct exec(Target t, Environment env, Construct... args) throws Cance
614614
prefix = Static.getBoolean(args[1]);
615615
}
616616
mes = (prefix?"CommandHelper: ":"") + Static.MCToANSIColors(mes);
617-
if(mes.matches("(?m).*\033.*")){
617+
if(mes.contains("\033")){
618618
//We have terminal colors, we need to reset them at the end
619619
mes += TermColors.reset();
620620
}

src/main/java/com/laytonsmith/core/functions/Enchantments.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ public String docs() {
449449

450450
@Override
451451
public ExceptionType[] thrown() {
452-
return new ExceptionType[]{ExceptionType.EnchantmentException, ExceptionType.CastException};
452+
return new ExceptionType[]{ExceptionType.EnchantmentException, ExceptionType.FormatException};
453453
}
454454

455455
@Override
@@ -556,7 +556,7 @@ public String docs() {
556556

557557
@Override
558558
public ExceptionType[] thrown() {
559-
return new ExceptionType[]{ExceptionType.CastException};
559+
return new ExceptionType[]{ExceptionType.FormatException};
560560
}
561561

562562
@Override

src/main/java/com/laytonsmith/core/functions/Environment.java

Lines changed: 61 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -84,47 +84,49 @@ public CHVersion since() {
8484
}
8585

8686
@Override
87-
public Construct exec(Target t, com.laytonsmith.core.environments.Environment env, Construct... args) throws CancelCommandException, ConfigRuntimeException {
88-
double x = 0;
89-
double y = 0;
90-
double z = 0;
87+
public Construct exec(Target t, com.laytonsmith.core.environments.Environment env, Construct... args)
88+
throws CancelCommandException, ConfigRuntimeException {
89+
int x;
90+
int y;
91+
int z;
9192
MCWorld w = null;
92-
MCCommandSender sender = env.getEnv(CommandHelperEnvironment.class).GetPlayer();
93-
String world = null;
94-
if (sender instanceof MCPlayer) {
95-
w = ((MCPlayer) sender).getWorld();
93+
MCPlayer player = env.getEnv(CommandHelperEnvironment.class).GetPlayer();
94+
if (player != null) {
95+
w = player.getWorld();
9696
}
97-
if (args.length == 1 || args.length == 2) {
98-
if (args[0] instanceof CArray) {
99-
MCLocation loc = ObjectGenerator.GetGenerator().location(args[0], w, t);
100-
x = loc.getX();
101-
y = loc.getY();
102-
z = loc.getZ();
103-
world = loc.getWorld().getName();
104-
} else {
105-
throw new ConfigRuntimeException("get_block_at expects param 1 to be an array", ExceptionType.CastException, t);
97+
if (args.length < 3) {
98+
if (!(args[0] instanceof CArray)) {
99+
throw new ConfigRuntimeException("get_block_at expects param 1 to be an array",
100+
ExceptionType.CastException, t);
106101
}
102+
MCLocation loc = ObjectGenerator.GetGenerator().location(args[0], w, t);
103+
x = loc.getBlockX();
104+
y = loc.getBlockY();
105+
z = loc.getBlockZ();
106+
w = loc.getWorld();
107107
if (args.length == 2) {
108-
world = args[1].val();
108+
w = Static.getServer().getWorld(args[1].val());
109+
if (w == null) {
110+
throw new ConfigRuntimeException("The specified world " + args[1].val() + " doesn't exist",
111+
ExceptionType.InvalidWorldException, t);
112+
}
109113
}
110-
} else if (args.length == 3 || args.length == 4) {
111-
x = Static.getDouble(args[0], t);
112-
y = Static.getDouble(args[1], t);
113-
z = Static.getDouble(args[2], t);
114+
} else {
115+
x = (int) java.lang.Math.floor(Static.getNumber(args[0], t));
116+
y = (int) java.lang.Math.floor(Static.getNumber(args[1], t));
117+
z = (int) java.lang.Math.floor(Static.getNumber(args[2], t));
114118
if (args.length == 4) {
115-
world = args[3].val();
119+
w = Static.getServer().getWorld(args[3].val());
120+
if (w == null) {
121+
throw new ConfigRuntimeException("The specified world " + args[4].val() + " doesn't exist",
122+
ExceptionType.InvalidWorldException, t);
123+
}
116124
}
117125
}
118-
if (world != null) {
119-
w = Static.getServer().getWorld(world);
120-
}
121126
if (w == null) {
122-
throw new ConfigRuntimeException("The specified world " + world + " doesn't exist", ExceptionType.InvalidWorldException, t);
127+
throw new ConfigRuntimeException("No world was provided", ExceptionType.InvalidWorldException, t);
123128
}
124-
x = java.lang.Math.floor(x);
125-
y = java.lang.Math.floor(y);
126-
z = java.lang.Math.floor(z);
127-
MCBlock b = w.getBlockAt((int) x, (int) y, (int) z);
129+
MCBlock b = w.getBlockAt(x, y, z);
128130
if (b == null) {
129131
throw new ConfigRuntimeException(
130132
"Could not find the block in " + this.getName() + " (are you running in cmdline mode?)",
@@ -164,7 +166,8 @@ public String docs() {
164166

165167
@Override
166168
public ExceptionType[] thrown() {
167-
return new ExceptionType[]{ExceptionType.CastException, ExceptionType.LengthException, ExceptionType.FormatException, ExceptionType.InvalidWorldException};
169+
return new ExceptionType[]{ExceptionType.CastException, ExceptionType.LengthException,
170+
ExceptionType.FormatException, ExceptionType.InvalidWorldException};
168171
}
169172

170173
@Override
@@ -178,68 +181,59 @@ public CHVersion since() {
178181
}
179182

180183
@Override
181-
public Construct exec(Target t, com.laytonsmith.core.environments.Environment env, Construct... args) throws CancelCommandException, ConfigRuntimeException {
182-
double x = 0;
183-
double y = 0;
184-
double z = 0;
184+
public Construct exec(Target t, com.laytonsmith.core.environments.Environment env, Construct... args)
185+
throws CancelCommandException, ConfigRuntimeException {
186+
int x;
187+
int y;
188+
int z;
185189
boolean physics = true;
186-
String id = null;
187-
String world = null;
190+
String id;
188191
MCWorld w = null;
189-
MCCommandSender sender = env.getEnv(CommandHelperEnvironment.class).GetCommandSender();
190-
if (sender instanceof MCPlayer) {
191-
w = ((MCPlayer) sender).getWorld();
192+
MCPlayer player = env.getEnv(CommandHelperEnvironment.class).GetPlayer();
193+
if (player != null) {
194+
w = player.getWorld();
192195
}
193196
if (args.length < 4) {
194197
if (!(args[0] instanceof CArray)) {
195-
throw new ConfigRuntimeException("set_block_at expects param 1 to be an array", ExceptionType.CastException, t);
198+
throw new ConfigRuntimeException("set_block_at expects param 1 to be an array",
199+
ExceptionType.CastException, t);
196200
}
197201
MCLocation l = ObjectGenerator.GetGenerator().location(args[0], w, t);
198202
x = l.getBlockX();
199203
y = l.getBlockY();
200204
z = l.getBlockZ();
201-
world = l.getWorld().getName();
205+
w = l.getWorld();
202206
id = args[1].val();
203207
if (args.length == 3) {
204208
physics = Static.getBoolean(args[2]);
205209
}
206210

207211
} else {
208-
x = Static.getNumber(args[0], t);
209-
y = Static.getNumber(args[1], t);
210-
z = Static.getNumber(args[2], t);
212+
x = (int) java.lang.Math.floor(Static.getNumber(args[0], t));
213+
y = (int) java.lang.Math.floor(Static.getNumber(args[1], t));
214+
z = (int) java.lang.Math.floor(Static.getNumber(args[2], t));
211215
id = args[3].val();
212216
if (args.length >= 5) {
213-
world = args[4].val();
217+
w = Static.getServer().getWorld(args[4].val());
218+
if (w == null) {
219+
throw new ConfigRuntimeException("The specified world " + args[4].val() + " doesn't exist",
220+
ExceptionType.InvalidWorldException, t);
221+
}
222+
} else if (w == null) {
223+
throw new ConfigRuntimeException("No world was provided",
224+
ExceptionType.InvalidWorldException, t);
214225
}
215226
if (args.length == 6) {
216227
physics = Static.getBoolean(args[2]);
217228
}
218229
}
219-
if (world != null) {
220-
w = Static.getServer().getWorld(world);
221-
}
222-
if (w == null) {
223-
throw new ConfigRuntimeException("The specified world " + world + " doesn't exist", ExceptionType.InvalidWorldException, t);
224-
}
225-
x = java.lang.Math.floor(x);
226-
y = java.lang.Math.floor(y);
227-
z = java.lang.Math.floor(z);
228-
int ix = (int) x;
229-
int iy = (int) y;
230-
int iz = (int) z;
231-
MCBlock b = w.getBlockAt(ix, iy, iz);
230+
MCBlock b = w.getBlockAt(x, y, z);
232231
String[] dataAndMeta = id.split(":");
233232
int data;
234-
byte meta;
233+
byte meta = 0;
235234
try {
236-
if(dataAndMeta.length == 1) {
237-
meta = 0;
238-
} else if(dataAndMeta.length == 2) {
235+
if(dataAndMeta.length == 2) {
239236
meta = Byte.parseByte(dataAndMeta[1]); // Throws NumberFormatException.
240-
} else {
241-
throw new ConfigRuntimeException("id must be formatted as such: 'x:y' where x and y are integers",
242-
ExceptionType.FormatException, t);
243237
}
244238
data = Integer.parseInt(dataAndMeta[0]); // Throws NumberFormatException.
245239
} catch(NumberFormatException e) {

0 commit comments

Comments
 (0)