Support String.downcase and String.upcase according to Unicode 6.2.0

This commit is contained in:
José Valim
2012-10-21 23:35:03 +02:00
parent 318454c092
commit b2c8669c4c
5 changed files with 24510 additions and 31 deletions
+3
View File
@@ -1,3 +1,6 @@
* enhancements
* [String] Support String.downcase and String.upcase according to Unicode 6.2.0
# v0.7.0 (2012-10-20)
* enhancements
+6 -3
View File
@@ -36,9 +36,12 @@ lib/elixir/src/elixir.app.src: src/elixir.app.src
erlang:
@ cd lib/elixir && $(REBAR) compile
# We need to compile only EEx (without the app)
# file so we can compile Mix
elixir: kernel lib/eex/ebin/Elixir-EEx.beam mix ex_unit eex iex
lib/elixir/ebin/Elixir-String-Unicode.beam: lib/elixir/priv/unicode.ex lib/elixir/priv/UnicodeData.txt
@ echo "==> unicode (compile)";
elixirc lib/elixir/priv/unicode.ex -o lib/elixir/ebin;
# We need to compile only EEx (without the app) file so we can compile Mix
elixir: kernel lib/elixir/ebin/Elixir-String-Unicode.beam lib/eex/ebin/Elixir-EEx.beam mix ex_unit eex iex
kernel: $(KERNEL)
$(KERNEL): lib/elixir/lib/*.ex lib/elixir/lib/*/*.ex $(FORCE)
+12 -28
View File
@@ -128,7 +128,11 @@ defmodule String do
end
@doc """
Convert all characters on the given string to upper case.
Convert all characters on the given string to upcase.
This function relies on the simple uppercase mapping
available in Unicode 6.2.0, check http://unicode.org/reports/tr44/
for more information.
## Examples
@@ -137,22 +141,14 @@ defmodule String do
String.upcase("josé") #=> "JOSÉ"
"""
def upcase(<<>>), do: <<>>
def upcase(<<195, c, t :: binary>>) when c in 160..191 do
<<195, c - 32, upcase(t) :: binary>>
end
def upcase(<<c, t :: binary>>) when c in ?a..?z do
<<c - 32, upcase(t) :: binary>>
end
def upcase(<<c, t :: binary>>) do
<<c , upcase(t) :: binary>>
end
defdelegate upcase(binary), to: String.Unicode
@doc """
Convert all characters on the given string to down case.
Convert all characters on the given string to downcase.
This function relies on the simple lowercase mapping
available in Unicode 6.2.0, check http://unicode.org/reports/tr44/
for more information.
## Examples
@@ -161,19 +157,7 @@ defmodule String do
String.downcase("JOSÉ") #=> "josé"
"""
def downcase(<<>>), do: <<>>
def downcase(<<195, c, t :: binary>>) when c in 128..159 do
<<195, c + 32, downcase(t) :: binary>>
end
def downcase(<<c, t :: binary>>) when c in ?A..?Z do
<<c + 32, downcase(t) :: binary>>
end
def downcase(<<c, t :: binary>>) do
<<c , downcase(t) :: binary>>
end
defdelegate downcase(binary), to: String.Unicode
@doc """
Returns a string where trailing char have been
File diff suppressed because it is too large Load Diff
+60
View File
@@ -0,0 +1,60 @@
# This file has its compilation step because
# it needs to parse String.Unicode data and
# compile a digested module.
defmodule String.Unicode do
@moduledoc false
to_binary = fn(codepoint) ->
:unicode.characters_to_binary([binary_to_integer(codepoint, 16)])
end
path = File.expand_path("../UnicodeData.txt", __FILE__)
codes = Enum.reduce File.iterator!(path), [], fn(line, acc) ->
[ codepoint, _name, _category,
_class, _bidi, _decomposition,
_numeric_1, _numeric_2, _numeric_3,
_bidi_mirror, _unicode_1, _iso,
upper, lower, _title ] = :binary.split(line, ";", [:global])
if upper != "" or lower != "" do
[{ to_binary.(codepoint), upper, lower }|acc]
else
acc
end
end
# Downcase
lc { codepoint, _upper, lower } inlist codes, lower != "" do
lower = to_binary.(lower)
args = quote do: [unquote(codepoint) <> t]
code = quote do: unquote(lower) <> downcase(t)
def :downcase, args, [], do: code
end
def downcase(<< h, t :: binary >>) do
<< h >> <> downcase(t)
end
def downcase(<< >>) do
<< >>
end
# Upcase
lc { codepoint, upper, _lower } inlist codes, upper != "" do
upper = to_binary.(upper)
args = quote do: [unquote(codepoint) <> t]
code = quote do: unquote(upper) <> upcase(t)
def :upcase, args, [], do: code
end
def upcase(<< h, t :: binary >>) do
<< h >> <> upcase(t)
end
def upcase(<< >>) do
<< >>
end
end