diff --git a/compiler/test/stdlib/string.test.gr b/compiler/test/stdlib/string.test.gr index 90e83e5c8..7e7507c30 100644 --- a/compiler/test/stdlib/string.test.gr +++ b/compiler/test/stdlib/string.test.gr @@ -551,3 +551,11 @@ assert String.toAsciiLowercase("aBc🌾12Y") == "abc🌾12y" // toAsciiUppercase assert String.toAsciiUppercase("aBc🌾12Y") == "ABC🌾12Y" + +// String.repeat +assert String.repeat(1, "=.") == "=." +assert String.repeat(10, "=") == "==========" +assert String.repeat(10, "=.") == "=.=.=.=.=.=.=.=.=.=." +assert String.repeat(0, "=.") == "" +assert String.repeat(0, "") == "" +assert String.repeat(5, "") == "" diff --git a/stdlib/string.gr b/stdlib/string.gr index cf06927cc..84e3aa389 100644 --- a/stdlib/string.gr +++ b/stdlib/string.gr @@ -2338,3 +2338,40 @@ provide let toAsciiUppercase = string => { } implode(chars) } + +/** + * Produces a new string by repeating a substring a given number of times. + * + * @param count: The number of times to repeat the string + * @param string: The string to repeat + * @returns A string containing the repeated input string + * + * @throws InvalidArgument(String): When the `count` is not an integer + * @throws InvalidArgument(String): When the `count` is negative + * + * @example assert String.repeat(5, "=") == "=====" + * @example assert String.repeat(0, ".") == "" + * + * @since v0.6.7 + */ +@unsafe +provide let repeat = (count, string: String) => { + use WasmI32.{ (+), (*), (<), (&), (!=) } + if ((WasmI32.fromGrain(count) & 1n) != 1n) { + throw InvalidArgument("Invalid count value") + } + let rawCount = untagSimpleNumber(count) + if (rawCount < 0n) { + throw InvalidArgument("Invalid count must be a positive integer or zero") + } + let stringPtr = WasmI32.fromGrain(string) + let byteLength = WasmI32.load(stringPtr, 4n) + let stringPtr = stringPtr + 8n + let newStringPtr = allocateString(byteLength * rawCount) + let strContentPtr = newStringPtr + 8n + for (let mut i = 0n; i < rawCount; i += 1n) { + Memory.copy(strContentPtr + byteLength * i, stringPtr, byteLength) + } + ignore(string) + return WasmI32.toGrain(newStringPtr): String +} diff --git a/stdlib/string.md b/stdlib/string.md index 58ab18066..3f7e79ebb 100644 --- a/stdlib/string.md +++ b/stdlib/string.md @@ -1174,3 +1174,46 @@ Examples: assert String.toAsciiUppercase("aBc123") == "ABC123" ``` +### String.**repeat** + +
+Added in next +No other changes yet. +
+ +```grain +repeat : (count: Number, string: String) => String +``` + +Produces a new string by repeating a substring a given number of times. + +Parameters: + +|param|type|description| +|-----|----|-----------| +|`count`|`Number`|The number of times to repeat the string| +|`string`|`String`|The string to repeat| + +Returns: + +|type|description| +|----|-----------| +|`String`|A string containing the repeated input string| + +Throws: + +`InvalidArgument(String)` + +* When the `count` is not an integer +* When the `count` is negative + +Examples: + +```grain +assert String.repeat(5, "=") == "=====" +``` + +```grain +assert String.repeat(0, ".") == "" +``` +