Skip to content

Commit b43e247

Browse files
authored
optimized textwidth(::Char) for ASCII (#55398)
1 parent b3a62b4 commit b43e247

File tree

2 files changed

+23
-0
lines changed

2 files changed

+23
-0
lines changed

base/strings/unicode.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,15 @@ julia> textwidth('⛵')
256256
```
257257
"""
258258
function textwidth(c::AbstractChar)
259+
ismalformed(c) && return 1
260+
i = codepoint(c)
261+
i < 0x7f && return Int(i >= 0x20) # ASCII fast path
262+
Int(ccall(:utf8proc_charwidth, Cint, (UInt32,), i))
263+
end
264+
265+
function textwidth(c::Char)
266+
b = bswap(reinterpret(UInt32, c)) # from isascii(c)
267+
b < 0x7f && return Int(b >= 0x20) # ASCII fast path
259268
ismalformed(c) && return 1
260269
Int(ccall(:utf8proc_charwidth, Cint, (UInt32,), c))
261270
end

test/strings/util.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
SubStr(s) = SubString("abc$(s)de", firstindex(s) + 3, lastindex(s) + 3)
44

5+
@testset "textwidth" begin
6+
for (c, w) in [('x', 1), ('α', 1), ('🍕', 2), ('\0', 0), ('\u0302', 0), ('\xc0', 1)]
7+
@test textwidth(c) == w
8+
@test textwidth(c^3) == w*3
9+
@test w == @invoke textwidth(c::AbstractChar)
10+
end
11+
for i in 0x00:0x7f # test all ASCII chars (which have fast path)
12+
w = Int(ccall(:utf8proc_charwidth, Cint, (UInt32,), i))
13+
c = Char(i)
14+
@test textwidth(c) == w
15+
@test w == @invoke textwidth(c::AbstractChar)
16+
end
17+
end
18+
519
@testset "padding (lpad and rpad)" begin
620
@test lpad("foo", 2) == "foo"
721
@test rpad("foo", 2) == "foo"

0 commit comments

Comments
 (0)