Skip to content

Commit

Permalink
Optimise string.pad_left, string.pad_right. Optimise string.slice on JS.
Browse files Browse the repository at this point in the history
  • Loading branch information
richard-viney authored and lpil committed Oct 9, 2024
1 parent 0a087d5 commit 4c3ea20
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 25 deletions.
50 changes: 25 additions & 25 deletions src/gleam/string.gleam
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//// Strings in Gleam are UTF-8 binaries. They can be written in your code as
//// text surrounded by `"double quotes"`.

import gleam/iterator.{type Iterator}
import gleam/iterator
import gleam/list
import gleam/option.{type Option, None, Some}
import gleam/order
Expand Down Expand Up @@ -222,13 +222,8 @@ pub fn slice(from string: String, at_index idx: Int, length len: Int) -> String
}

@external(erlang, "gleam_stdlib", "slice")
fn do_slice(string: String, idx: Int, len: Int) -> String {
string
|> to_graphemes
|> list.drop(idx)
|> list.take(len)
|> concat
}
@external(javascript, "../gleam_stdlib.mjs", "string_slice")
fn do_slice(string: String, idx: Int, len: Int) -> String

/// Drops contents of the first `String` that occur before the second `String`.
/// If the `from` string does not contain the `before` string, `from` is returned unchanged.
Expand Down Expand Up @@ -489,13 +484,18 @@ fn do_join(strings: List(String), separator: String) -> String {
/// // -> "121"
/// ```
///
pub fn pad_left(string: String, to desired_length: Int, with pad_string: String) {
pub fn pad_left(
string: String,
to desired_length: Int,
with pad_string: String,
) -> String {
let current_length = length(string)
let to_pad_length = desired_length - current_length
padding(to_pad_length, pad_string)
|> iterator.append(iterator.single(string))
|> iterator.to_list
|> concat

case to_pad_length <= 0 {
True -> string
False -> padding(to_pad_length, pad_string) <> string
}
}

/// Pads a `String` on the right until it has a given length.
Expand All @@ -521,22 +521,22 @@ pub fn pad_right(
string: String,
to desired_length: Int,
with pad_string: String,
) {
) -> String {
let current_length = length(string)
let to_pad_length = desired_length - current_length
iterator.single(string)
|> iterator.append(padding(to_pad_length, pad_string))
|> iterator.to_list
|> concat

case to_pad_length <= 0 {
True -> string
False -> string <> padding(to_pad_length, pad_string)
}
}

fn padding(size: Int, pad_string: String) -> Iterator(String) {
let pad_length = length(pad_string)
let num_pads = size / pad_length
let extra = size % pad_length
iterator.repeat(pad_string)
|> iterator.take(num_pads)
|> iterator.append(iterator.single(slice(pad_string, 0, extra)))
fn padding(size: Int, pad_string: String) -> String {
let pad_string_length = length(pad_string)
let num_pads = size / pad_string_length
let extra = size % pad_string_length

repeat(pad_string, num_pads) <> slice(pad_string, 0, extra)
}

/// Removes whitespace on both sides of a `String`.
Expand Down
28 changes: 28 additions & 0 deletions src/gleam_stdlib.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,34 @@ export function length(data) {
return data.length;
}

export function string_slice(string, idx, len) {
if (len <= 0 || idx >= string.length) {
return "";
}

const iterator = graphemes_iterator(string);
if (iterator) {
while (idx-- > 0) {
iterator.next();
}

let result = "";

while (len-- > 0) {
const v = iterator.next().value;
if (v === undefined) {
break;
}

result += v.segment;
}

return result;
} else {
return string.match(/./gsu).slice(idx, idx + len).join("");
}
}

export function crop_string(string, substring) {
return string.substring(string.indexOf(substring));
}
Expand Down

0 comments on commit 4c3ea20

Please sign in to comment.