diff --git a/src/main/java/ortus/boxlang/runtime/bifs/global/array/ArrayResize.java b/src/main/java/ortus/boxlang/runtime/bifs/global/array/ArrayResize.java new file mode 100644 index 000000000..c6b872206 --- /dev/null +++ b/src/main/java/ortus/boxlang/runtime/bifs/global/array/ArrayResize.java @@ -0,0 +1,55 @@ + +package ortus.boxlang.runtime.bifs.global.array; + +import ortus.boxlang.runtime.bifs.BIF; +import ortus.boxlang.runtime.bifs.BoxBIF; +import ortus.boxlang.runtime.bifs.BoxMember; +import ortus.boxlang.runtime.context.IBoxContext; +import ortus.boxlang.runtime.scopes.ArgumentsScope; +import ortus.boxlang.runtime.scopes.Key; +import ortus.boxlang.runtime.types.Argument; +import ortus.boxlang.runtime.types.Array; +import ortus.boxlang.runtime.types.BoxLangType; + +@BoxBIF +@BoxMember( type = BoxLangType.ARRAY ) +public class ArrayResize extends BIF { + + /** + * Constructor + */ + public ArrayResize() { + super(); + declaredArguments = new Argument[] { + new Argument( true, "modifiablearray", Key.array ), + new Argument( true, "any", Key.size ) + }; + } + + /** + * Resets an array to a specified minimum number of elements. + * This can improve performance, if used to size an array to its + * expected maximum. For more than 500 elements, use arrayResize + * immediately after using the ArrayNew tag. + * + * @param context The context in which the BIF is being invoked. + * @param arguments Argument scope for the BIF. + * + * @argument.array The array to resize + * + * @argument.size The new minimum size of the array + */ + public Object invoke( IBoxContext context, ArgumentsScope arguments ) { + Array actualObj = arguments.getAsArray( Key.array ); + Integer size = arguments.getAsInteger( Key.size ); + + if ( actualObj.size() < size ) { + for ( int i = actualObj.size(); i < size; i++ ) { + actualObj.add( null ); + } + } + + return true; + } + +} diff --git a/src/main/java/ortus/boxlang/runtime/scopes/Key.java b/src/main/java/ortus/boxlang/runtime/scopes/Key.java index 1ea4b7b6e..f938279f3 100644 --- a/src/main/java/ortus/boxlang/runtime/scopes/Key.java +++ b/src/main/java/ortus/boxlang/runtime/scopes/Key.java @@ -98,6 +98,8 @@ public class Key { public static final Key mask = Key.of( "mask" ); public static final Key dateFormat = Key.of( "dateFormat" ); public static final Key timeFormat = Key.of( "timeFormat" ); + public static final Key size = Key.of( "size" ); + /** * -------------------------------------------------------------------------- * Private Properties diff --git a/src/test/java/ortus/boxlang/runtime/bifs/global/array/ArrayResizeTest.java b/src/test/java/ortus/boxlang/runtime/bifs/global/array/ArrayResizeTest.java new file mode 100644 index 000000000..813f1994c --- /dev/null +++ b/src/test/java/ortus/boxlang/runtime/bifs/global/array/ArrayResizeTest.java @@ -0,0 +1,115 @@ + +/** + * [BoxLang] + * + * Copyright [2023] [Ortus Solutions, Corp] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ortus.boxlang.runtime.bifs.global.array; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import ortus.boxlang.runtime.BoxRuntime; +import ortus.boxlang.runtime.context.IBoxContext; +import ortus.boxlang.runtime.context.ScriptingBoxContext; +import ortus.boxlang.runtime.scopes.Key; +import ortus.boxlang.runtime.scopes.VariablesScope; +import ortus.boxlang.runtime.types.Array; +import ortus.boxlang.runtime.types.Struct; + +public class ArrayResizeTest { + + static BoxRuntime instance; + static IBoxContext context; + static Struct variables; + static Key result = new Key( "result" ); + + @BeforeAll + public static void setUp() { + instance = BoxRuntime.getInstance( true ); + context = new ScriptingBoxContext( instance.getRuntimeContext() ); + variables = ( Struct ) context.getScopeNearby( VariablesScope.name ); + } + + @AfterAll + public static void teardown() { + instance.shutdown(); + } + + @BeforeEach + public void setupEach() { + variables.clear(); + } + + @DisplayName( "It should grow an array using nulls" ) + @Test + public void testGrow() { + instance.executeSource( + """ + nums = []; + result = ArrayResize( nums, 3 ); + """, + context ); + Array arr = variables.getAsArray( Key.of( "nums" ) ); + assertThat( variables.get( result ) ).isEqualTo( true ); + assertThat( arr.size() ).isEqualTo( 3 ); + assertThat( arr.get( 0 ) ).isNull(); + assertThat( arr.get( 1 ) ).isNull(); + assertThat( arr.get( 2 ) ).isNull(); + } + + @DisplayName( "It should not grow an array that is already bigger than the provided size" ) + @Test + public void testBigger() { + instance.executeSource( + """ + nums = [ 1, 2, 3, 4, 5 ]; + result = ArrayResize( nums, 3 ); + """, + context ); + Array arr = variables.getAsArray( Key.of( "nums" ) ); + assertThat( variables.get( result ) ).isEqualTo( true ); + assertThat( arr.size() ).isEqualTo( 5 ); + assertThat( arr.get( 0 ) ).isEqualTo( 1 ); + assertThat( arr.get( 1 ) ).isEqualTo( 2 ); + assertThat( arr.get( 2 ) ).isEqualTo( 3 ); + assertThat( arr.get( 3 ) ).isEqualTo( 4 ); + assertThat( arr.get( 4 ) ).isEqualTo( 5 ); + } + + @DisplayName( "It should allow member invocation" ) + @Test + public void testMemberInvocation() { + instance.executeSource( + """ + nums = []; + result = nums.resize( 3 ); + """, + context ); + Array arr = variables.getAsArray( Key.of( "nums" ) ); + assertThat( variables.get( result ) ).isEqualTo( true ); + assertThat( arr.size() ).isEqualTo( 3 ); + assertThat( arr.get( 0 ) ).isNull(); + assertThat( arr.get( 1 ) ).isNull(); + assertThat( arr.get( 2 ) ).isNull(); + } + +}