Skip to content

Commit 03de1f1

Browse files
committed
Optimize array_contains functions
Improve runtime performance on `array_contains()`, `array_scontains()` and `array_contains_ic()` by iterating over the array values whenever possible, rather than creating a keyset to iterate over and calling the getter to get all values.
1 parent 63ff249 commit 03de1f1

File tree

4 files changed

+103
-11
lines changed

4 files changed

+103
-11
lines changed

src/main/java/com/laytonsmith/core/constructs/CArray.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ public Version since() {
814814
@Override
815815
public Iterator<Mixed> iterator() {
816816
if(associativeMode) {
817-
throw new RuntimeException("iterator() cannot be called on an associative array");
817+
return associativeArray.values().iterator();
818818
} else {
819819
return array.iterator();
820820
}

src/main/java/com/laytonsmith/core/constructs/CByteArray.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,20 @@ public void removeValues(Mixed construct) {
583583

584584
@Override
585585
public Iterator<Mixed> iterator() {
586-
throw new CREUnsupportedOperationException("Iterating a byte array is not supported.", getTarget());
586+
return new Iterator<Mixed>() {
587+
588+
private int index = 0;
589+
590+
@Override
591+
public boolean hasNext() {
592+
return this.index <= maxValue;
593+
}
594+
595+
@Override
596+
public Mixed next() {
597+
return new CInt(data.get(this.index++), Target.UNKNOWN);
598+
}
599+
};
587600
}
588601

589602
@Override
@@ -696,6 +709,24 @@ protected SortedMap<String, Mixed> getAssociativeArray() {
696709
throw new Error("This error should not happen. Please report this bug to the developers");
697710
}
698711

712+
@Override
713+
public Iterator<Mixed> iterator() {
714+
return new Iterator<Mixed>() {
715+
716+
private int index = 0;
717+
718+
@Override
719+
public boolean hasNext() {
720+
return this.index <= backing.length;
721+
}
722+
723+
@Override
724+
public Mixed next() {
725+
return new CInt(backing[this.index++], Target.UNKNOWN);
726+
}
727+
};
728+
}
729+
699730
@Override
700731
public String docs() {
701732
return "A read-only subclass of array, which is used to make reading byte arrays more efficient.";

src/main/java/com/laytonsmith/core/constructs/CSlice.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,43 @@ public int size() {
165165
};
166166
}
167167

168+
@Override
169+
public Iterator<Mixed> iterator() {
170+
if(start <= finish) {
171+
return new Iterator<Mixed>() {
172+
173+
private long current = start;
174+
private long last = finish;
175+
176+
@Override
177+
public boolean hasNext() {
178+
return this.current <= this.last;
179+
}
180+
181+
@Override
182+
public Mixed next() {
183+
return new CInt(this.current++, Target.UNKNOWN);
184+
}
185+
};
186+
} else {
187+
return new Iterator<Mixed>() {
188+
189+
private long current = start;
190+
private long last = finish;
191+
192+
@Override
193+
public boolean hasNext() {
194+
return this.current >= this.last;
195+
}
196+
197+
@Override
198+
public Mixed next() {
199+
return new CInt(this.current--, Target.UNKNOWN);
200+
}
201+
};
202+
}
203+
}
204+
168205
@Override
169206
public long size() {
170207
return size;

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

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -712,9 +712,17 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws CancelCommand
712712
CArray ca = ArgumentValidation.getArray(args[0], t);
713713
aa = ca;
714714
}
715-
for(Mixed key : aa.keySet()) {
716-
if(new equals().exec(t, env, aa.get(key, t), args[1]).getBoolean()) {
717-
return CBoolean.TRUE;
715+
if(aa instanceof CArray ca) {
716+
for(Mixed val : ca) {
717+
if(new equals().exec(t, env, val, args[1]).getBoolean()) {
718+
return CBoolean.TRUE;
719+
}
720+
}
721+
} else {
722+
for(Mixed key : aa.keySet()) {
723+
if(new equals().exec(t, env, aa.get(key, t), args[1]).getBoolean()) {
724+
return CBoolean.TRUE;
725+
}
718726
}
719727
}
720728
return CBoolean.FALSE;
@@ -822,9 +830,17 @@ public Mixed exec(Target t, Environment environment, Mixed... args) throws Confi
822830
} else {
823831
aa = ArgumentValidation.getArray(args[0], t);
824832
}
825-
for(Mixed key : aa.keySet()) {
826-
if(new equals_ic().exec(t, environment, aa.get(key, t), args[1]).getBoolean()) {
827-
return CBoolean.TRUE;
833+
if(aa instanceof CArray ca) {
834+
for(Mixed val : ca) {
835+
if(new equals_ic().exec(t, environment, val, args[1]).getBoolean()) {
836+
return CBoolean.TRUE;
837+
}
838+
}
839+
} else {
840+
for(Mixed key : aa.keySet()) {
841+
if(new equals_ic().exec(t, environment, aa.get(key, t), args[1]).getBoolean()) {
842+
return CBoolean.TRUE;
843+
}
828844
}
829845
}
830846
return CBoolean.FALSE;
@@ -876,9 +892,17 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws CancelCommand
876892
} else {
877893
aa = ArgumentValidation.getArray(args[0], t);
878894
}
879-
for(Mixed key : aa.keySet()) {
880-
if(new sequals().exec(t, env, aa.get(key, t), args[1]).getBoolean()) {
881-
return CBoolean.TRUE;
895+
if(aa instanceof CArray ca) {
896+
for(Mixed val : ca) {
897+
if(new sequals().exec(t, env, val, args[1]).getBoolean()) {
898+
return CBoolean.TRUE;
899+
}
900+
}
901+
} else {
902+
for(Mixed key : aa.keySet()) {
903+
if(new sequals().exec(t, env, aa.get(key, t), args[1]).getBoolean()) {
904+
return CBoolean.TRUE;
905+
}
882906
}
883907
}
884908
return CBoolean.FALSE;

0 commit comments

Comments
 (0)