Skip to content

Commit 62697df

Browse files
tckbJosé Valim
authored andcommitted
Add performant impl for string upcase/downcase :ascii mode (#7680)
The existing implementation with binary comprehensions turned out to be slower than the other modes. The current implementation is >= 2.5X faster than the earlier implementation. Signed-off-by: José Valim <[email protected]>
1 parent 132b80a commit 62697df

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

lib/elixir/lib/string.ex

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -644,15 +644,19 @@ defmodule String do
644644
end
645645

646646
def upcase(string, :ascii) when is_binary(string) do
647-
for <<x <- string>>,
648-
do: if(x >= ?a and x <= ?z, do: <<x - 32>>, else: <<x>>),
649-
into: ""
647+
IO.iodata_to_binary(upcase_ascii(string))
650648
end
651649

652650
def upcase(string, mode) when mode in @conditional_mappings do
653651
String.Casing.upcase(string, [], mode)
654652
end
655653

654+
defp upcase_ascii(<<char, rest::bits>>) when char >= ?a and char <= ?z,
655+
do: [char - 32 | upcase_ascii(rest)]
656+
657+
defp upcase_ascii(<<char, rest::bits>>), do: [char | upcase_ascii(rest)]
658+
defp upcase_ascii(<<>>), do: []
659+
656660
@doc """
657661
Converts all characters in the given string to lowercase according to `mode`.
658662
@@ -700,15 +704,19 @@ defmodule String do
700704
end
701705

702706
def downcase(string, :ascii) when is_binary(string) do
703-
for <<x <- string>>,
704-
do: if(x >= ?A and x <= ?Z, do: <<x + 32>>, else: <<x>>),
705-
into: ""
707+
IO.iodata_to_binary(downcase_ascii(string))
706708
end
707709

708710
def downcase(string, mode) when mode in @conditional_mappings do
709711
String.Casing.downcase(string, [], mode)
710712
end
711713

714+
defp downcase_ascii(<<char, rest::bits>>) when char >= ?A and char <= ?Z,
715+
do: [char + 32 | downcase_ascii(rest)]
716+
717+
defp downcase_ascii(<<char, rest::bits>>), do: [char | downcase_ascii(rest)]
718+
defp downcase_ascii(<<>>), do: []
719+
712720
@doc """
713721
Converts the first character in the given string to
714722
uppercase and the remainder to lowercase according to `mode`.

0 commit comments

Comments
 (0)