@@ -208,6 +208,8 @@ defmodule String do
208
208
@ type grapheme :: t
209
209
@ type pattern :: t | [ t ] | :binary . cp ( )
210
210
211
+ @ conditional_mappings [ :greek ]
212
+
211
213
@ doc """
212
214
Checks if a string contains only printable characters.
213
215
@@ -604,7 +606,12 @@ defmodule String do
604
606
defdelegate normalize ( string , form ) , to: String.Normalizer
605
607
606
608
@ doc """
607
- Converts all characters in the given string to uppercase.
609
+ Converts all characters in the given string to uppercase according to `mode`.
610
+
611
+ `mode` may be `:default`, `:ascii` or `:greek`. The `:default` mode considers
612
+ all non-conditional transformations outlined in the Unicode standard. `:ascii`
613
+ uppercases only the letters a to z. `:greek` includes the context sensitive
614
+ mappings found in Greek.
608
615
609
616
## Examples
610
617
@@ -617,12 +624,38 @@ defmodule String do
617
624
iex> String.upcase("olá")
618
625
"OLÁ"
619
626
627
+ The `:ascii` mode ignores Unicode characters and provides a more
628
+ performant implementation when you know the string contains only
629
+ ASCII characters:
630
+
631
+ iex> String.upcase("olá", :ascii)
632
+ "OLá"
633
+
620
634
"""
621
- @ spec upcase ( t ) :: t
622
- defdelegate upcase ( binary ) , to: String.Casing
635
+ @ spec upcase ( t , :default | :ascii | :greek ) :: t
636
+ def upcase ( string , mode \\ :default )
637
+
638
+ def upcase ( string , :default ) when is_binary ( string ) do
639
+ String.Casing . upcase ( string , "" , :default )
640
+ end
641
+
642
+ def upcase ( string , :ascii ) when is_binary ( string ) do
643
+ for << x <- string >> ,
644
+ do: if ( x >= ?a and x <= ?z , do: << x - 32 >> , else: << x >> ) ,
645
+ into: ""
646
+ end
647
+
648
+ def upcase ( string , mode ) when mode in @ conditional_mappings do
649
+ String.Casing . upcase ( string , "" , mode )
650
+ end
623
651
624
652
@ doc """
625
- Converts all characters in the given string to lowercase.
653
+ Converts all characters in the given string to lowercase according to `mode`.
654
+
655
+ `mode` may be `:default`, `:ascii` or `:greek`. The `:default` mode considers
656
+ all non-conditional transformations outlined in the Unicode standard. `:ascii`
657
+ lowercases only the letters A to Z. `:greek` includes the context sensitive
658
+ mappings found in Greek.
626
659
627
660
## Examples
628
661
@@ -635,18 +668,47 @@ defmodule String do
635
668
iex> String.downcase("OLÁ")
636
669
"olá"
637
670
671
+ The `:ascii` mode ignores Unicode characters and provides a more
672
+ performant implementation when you know the string contains only
673
+ ASCII characters:
674
+
675
+ iex> String.downcase("OLÁ", :ascii)
676
+ "olÁ"
677
+
678
+ And `:greek` properly handles the context sensitive sigma in Greek:
679
+
680
+ iex> String.downcase("ΣΣ")
681
+ "ςς"
682
+
683
+ iex> String.downcase("ΣΣ", :greek)
684
+ "σς"
685
+
638
686
"""
639
- @ spec downcase ( t ) :: t
640
- defdelegate downcase ( binary ) , to: String.Casing
687
+ @ spec downcase ( t , :default | :ascii | :greek ) :: t
688
+ def downcase ( string , mode \\ :default )
689
+
690
+ def downcase ( string , :default ) when is_binary ( string ) do
691
+ String.Casing . downcase ( string , "" , :default )
692
+ end
693
+
694
+ def downcase ( string , :ascii ) when is_binary ( string ) do
695
+ for << x <- string >> ,
696
+ do: if ( x >= ?A and x <= ?Z , do: << x + 32 >> , else: << x >> ) ,
697
+ into: ""
698
+ end
699
+
700
+ def downcase ( string , mode ) when mode in @ conditional_mappings do
701
+ String.Casing . downcase ( string , "" , mode )
702
+ end
641
703
642
704
@ doc """
643
705
Converts the first character in the given string to
644
- uppercase and the remainder to lowercase.
706
+ uppercase and the remainder to lowercase according to `mode` .
645
707
646
- This relies on the titlecase information provided
647
- by the Unicode Standard. Note this function makes
648
- no attempt to capitalize all words in the string
649
- (usually known as titlecase) .
708
+ `mode` may be `:default`, `:ascii` or `:greek`. The `:default` mode considers
709
+ all non-conditional transformations outlined in the Unicode standard. `:ascii`
710
+ lowercases only the letters A to Z. `:greek` includes the context sensitive
711
+ mappings found in Greek .
650
712
651
713
## Examples
652
714
@@ -660,10 +722,17 @@ defmodule String do
660
722
"Olá"
661
723
662
724
"""
663
- @ spec capitalize ( t ) :: t
664
- def capitalize ( string ) when is_binary ( string ) do
665
- { char , rest } = String.Casing . titlecase_once ( string )
666
- char <> downcase ( rest )
725
+ @ spec capitalize ( t , :default | :ascii | :greek ) :: t
726
+ def capitalize ( string , mode \\ :default )
727
+
728
+ def capitalize ( << char , rest :: binary >> , :ascii ) do
729
+ char = if char >= ?a and char <= ?z , do: char - 32 , else: char
730
+ << char >> <> downcase ( rest , :ascii )
731
+ end
732
+
733
+ def capitalize ( string , mode ) when is_binary ( string ) do
734
+ { char , rest } = String.Casing . titlecase_once ( string , mode )
735
+ char <> downcase ( rest , mode )
667
736
end
668
737
669
738
@ doc false
0 commit comments