3535import com .laytonsmith .core .exceptions .ProgramFlowManipulationException ;
3636import com .laytonsmith .core .functions .BasicLogic .equals ;
3737import com .laytonsmith .core .functions .BasicLogic .equals_ic ;
38+ import com .laytonsmith .core .functions .BasicLogic .sequals ;
3839import com .laytonsmith .core .functions .DataHandling .array ;
3940import com .laytonsmith .core .functions .Exceptions .ExceptionType ;
4041import com .laytonsmith .core .natives .interfaces .ArrayAccess ;
@@ -586,7 +587,7 @@ public ExampleScript[] examples() throws ConfigCompileException {
586587 }
587588
588589 @ api
589- @ seealso ({array_index_exists .class })
590+ @ seealso ({array_index_exists .class , array_scontains . class })
590591 public static class array_contains extends AbstractFunction implements Optimizable {
591592
592593 @ Override
@@ -601,17 +602,16 @@ public Integer[] numArgs() {
601602
602603 @ Override
603604 public Construct exec (Target t , Environment env , Construct ... args ) throws CancelCommandException , ConfigRuntimeException {
604- if (args [0 ] instanceof CArray ) {
605- CArray ca = (CArray ) args [0 ];
606- for (Construct key : ca .keySet ()){
607- if (new equals ().exec (t , env , ca .get (key , t ), args [1 ]).getBoolean ()){
608- return CBoolean .TRUE ;
609- }
605+ if (!(args [0 ] instanceof CArray )) {
606+ throw ConfigRuntimeException .BuildException ("Argument 1 of " + this .getName () + " must be an array" , ExceptionType .CastException , t );
607+ }
608+ CArray ca = (CArray ) args [0 ];
609+ for (Construct key : ca .keySet ()){
610+ if (new equals ().exec (t , env , ca .get (key , t ), args [1 ]).getBoolean ()){
611+ return CBoolean .TRUE ;
610612 }
611- return CBoolean .FALSE ;
612- } else {
613- throw ConfigRuntimeException .BuildException ("Argument 1 of array_contains must be an array" , ExceptionType .CastException , t );
614613 }
614+ return CBoolean .FALSE ;
615615 }
616616
617617 @ Override
@@ -658,6 +658,7 @@ public Set<OptimizationOption> optimizationOptions() {
658658 }
659659
660660 @ api
661+ @ seealso ({array_contains .class })
661662 public static class array_contains_ic extends AbstractFunction implements Optimizable {
662663
663664 @ Override
@@ -706,7 +707,7 @@ public Construct exec(Target t, Environment environment, Construct... args) thro
706707 }
707708 return CBoolean .FALSE ;
708709 } else {
709- throw ConfigRuntimeException .BuildException ("Argument 1 of array_contains_ic must be an array" , ExceptionType .CastException , t );
710+ throw ConfigRuntimeException .BuildException ("Argument 1 of " + this . getName () + " must be an array" , ExceptionType .CastException , t );
710711 }
711712 }
712713
@@ -725,6 +726,79 @@ public Set<OptimizationOption> optimizationOptions() {
725726 }
726727 }
727728
729+ @ api
730+ @ seealso ({array_index_exists .class , array_contains .class })
731+ public static class array_scontains extends AbstractFunction implements Optimizable {
732+
733+ @ Override
734+ public String getName () {
735+ return "array_scontains" ;
736+ }
737+
738+ @ Override
739+ public Integer [] numArgs () {
740+ return new Integer []{2 };
741+ }
742+
743+ @ Override
744+ public Construct exec (Target t , Environment env , Construct ... args ) throws CancelCommandException , ConfigRuntimeException {
745+ if (!(args [0 ] instanceof CArray )) {
746+ throw ConfigRuntimeException .BuildException ("Argument 1 of " + this .getName () + " must be an array" , ExceptionType .CastException , t );
747+ }
748+ CArray ca = (CArray ) args [0 ];
749+ for (Construct key : ca .keySet ()){
750+ if (new sequals ().exec (t , env , ca .get (key , t ), args [1 ]).getBoolean ()){
751+ return CBoolean .TRUE ;
752+ }
753+ }
754+ return CBoolean .FALSE ;
755+ }
756+
757+ @ Override
758+ public ExceptionType [] thrown () {
759+ return new ExceptionType []{ExceptionType .CastException };
760+ }
761+
762+ @ Override
763+ public String docs () {
764+ return "boolean {array, testValue} Checks if the array contains a value of the same datatype and value as testValue."
765+ + " For associative arrays, only the values are searched, the keys are ignored."
766+ + " If you need to check for the existance of a particular key, use array_index_exists()." ;
767+ }
768+
769+ @ Override
770+ public boolean isRestricted () {
771+ return false ;
772+ }
773+
774+ @ Override
775+ public CHVersion since () {
776+ return CHVersion .V3_3_1 ;
777+ }
778+
779+ @ Override
780+ public Boolean runAsync () {
781+ return null ;
782+ }
783+
784+ @ Override
785+ public ExampleScript [] examples () throws ConfigCompileException {
786+ return new ExampleScript []{
787+ new ExampleScript ("Demonstrates finding a value" , "array_scontains(array(0, 1, 2), 2)" ),
788+ new ExampleScript ("Demonstrates not finding a value because of a value mismatch" , "array_scontains(array(0, 1, 2), 5)" ),
789+ new ExampleScript ("Demonstrates not finding a value because of a type mismatch" , "array_scontains(array(0, 1, 2), '2')" ),
790+ new ExampleScript ("Demonstrates finding a value listed multiple times" , "array_scontains(array(1, 1, 1), 1)" ),
791+ new ExampleScript ("Demonstrates finding a string" , "array_scontains(array('a', 'b', 'c'), 'b')" ),
792+ new ExampleScript ("Demonstrates finding a value in an associative array" , "array_scontains(array('a': 1, 'b': 2), 2)" )
793+ };
794+ }
795+
796+ @ Override
797+ public Set <OptimizationOption > optimizationOptions () {
798+ return EnumSet .of (OptimizationOption .NO_SIDE_EFFECTS );
799+ }
800+ }
801+
728802 @ api
729803 public static class array_index_exists extends AbstractFunction implements Optimizable {
730804
0 commit comments