@@ -81,3 +81,65 @@ pub fn (c rune) length_in_bytes() int {
8181 }
8282 return - 1
8383}
84+
85+ // `to_upper` convert to uppercase mode.
86+ pub fn (c rune) to_upper () rune {
87+ if c < 0x80 {
88+ if c > = `a` && c < = `z` {
89+ return c - 32
90+ }
91+ return c
92+ }
93+ return c.map_to (.to_upper)
94+ }
95+
96+ // `to_lower` convert to lowercase mode.
97+ pub fn (c rune) to_lower () rune {
98+ if c < 0x80 {
99+ if c > = `A` && c < = `Z` {
100+ return c + 32
101+ }
102+ return c
103+ }
104+ return c.map_to (.to_lower)
105+ }
106+
107+ // `to_title` convert to title mode.
108+ pub fn (c rune) to_title () rune {
109+ return c.to_upper ()
110+ }
111+
112+ // `map_to` rune map mode: .to_upper/.to_lower/.to_title
113+ @[direct_array_access]
114+ fn (c rune) map_to (mode MapMode) rune {
115+ mut start := 0
116+ mut end := rune_maps.len / rune_maps_columns_in_row
117+ // Binary search
118+ for start < end {
119+ middle := (start + end) / 2
120+ cur_map := unsafe { & rune_maps[middle * rune_maps_columns_in_row] }
121+ if c > = u32 (unsafe { * cur_map }) && c < = u32 (unsafe { * (cur_map + 1 ) }) {
122+ offset := if mode == .to_upper {
123+ unsafe { * (cur_map + 2 ) }
124+ } else {
125+ unsafe { * (cur_map + 3 ) }
126+ }
127+ if offset == rune_maps_ul {
128+ is_odd := (c - unsafe { * cur_map }) % 2 == 1
129+ if mode == .to_upper && is_odd {
130+ return c - 1
131+ } else if mode == .to_lower && ! is_odd {
132+ return c + 1
133+ }
134+ return c
135+ }
136+ return c + offset
137+ }
138+ if c < u32 (unsafe { * cur_map }) {
139+ end = middle
140+ } else {
141+ start = middle + 1
142+ }
143+ }
144+ return c
145+ }
0 commit comments