Skip to content

Commit b30be51

Browse files
authored
builtin: fix runes.to_upper() (fix #22742) (#22755)
1 parent 2ebbbd8 commit b30be51

File tree

17 files changed

+536
-26
lines changed

17 files changed

+536
-26
lines changed

vlib/builtin/rune.v

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)