Skip to content

Commit

Permalink
Merge pull request #23787 from JuliaLang/sk/repeatchar
Browse files Browse the repository at this point in the history
more efficient repeat(Char, n)
  • Loading branch information
StefanKarpinski authored Sep 20, 2017
2 parents 2562263 + 14253b9 commit 9202df2
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 4 deletions.
39 changes: 35 additions & 4 deletions base/strings/string.jl
Original file line number Diff line number Diff line change
Expand Up @@ -455,12 +455,43 @@ julia> repeat('A', 3)
```
"""
function repeat(c::Char, r::Integer)
if isascii(c)
r < 0 && throw(ArgumentError("can't repeat a character $r times"))
r < 0 && throw(ArgumentError("can't repeat a character $r times"))
r == 0 && return ""
ch = UInt(c)
if ch < 0x80
out = _string_n(r)
ccall(:memset, Ptr{Void}, (Ptr{UInt8}, Cint, Csize_t), out, c, r)
return out
elseif ch < 0x800
out = _string_n(2r)
p16 = reinterpret(Ptr{UInt16}, pointer(out))
u16 = ((ch >> 0x6) | (ch & 0x3f) << 0x8) % UInt16 | 0x80c0
@inbounds for i = 1:r
unsafe_store!(p16, u16, i)
end
elseif ch < 0x10000
(0xd800 ch 0xdfff) || throw(ArgumentError("invalid character 0x$(hex(ch))"))
out = _string_n(3r)
p = pointer(out)
b1 = (ch >> 0xc) % UInt8 | 0xe0
b2 = ((ch >> 0x6) & 0x3f) % UInt8 | 0x80
b3 = (ch & 0x3f) % UInt8 | 0x80
@inbounds for i = 1:r
unsafe_store!(p, b1)
unsafe_store!(p, b2, 2)
unsafe_store!(p, b3, 3)
p += 3
end
elseif ch < 0x110000
out = _string_n(4r)
p32 = reinterpret(Ptr{UInt32}, pointer(out))
u32 = ((ch >> 0x12) | ((ch >> 0x4) & 0x03f00) |
((ch << 0xa) & 0x3f0000) | ((ch & 0x3f) << 0x18)) % UInt32 | 0x808080f0
@inbounds for i = 1:r
unsafe_store!(p32, u32)
p32 += 4
end
else
return repeat(string(c), r)
throw(ArgumentError("invalid character 0x$(hex(ch))"))
end
return out
end
17 changes: 17 additions & 0 deletions test/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,23 @@ Base.endof(x::CharStr) = endof(x.chars)
@test repeat("x",1) == repeat('x',1) == "x"^1 == 'x'^1 == GenericString("x")^1 == "x"
@test repeat("x",0) == repeat('x',0) == "x"^0 == 'x'^0 == GenericString("x")^0 == ""

for S in ["xxx", "ååå", "∀∀∀", "🍕🍕🍕"]
c = S[1]
s = string(c)
@test_throws ArgumentError repeat(c, -1)
@test_throws ArgumentError repeat(s, -1)
@test_throws ArgumentError repeat(S, -1)
@test repeat(c, 0) == ""
@test repeat(s, 0) == ""
@test repeat(S, 0) == ""
@test repeat(c, 1) == s
@test repeat(s, 1) == s
@test repeat(S, 1) == S
@test repeat(c, 3) == S
@test repeat(s, 3) == S
@test repeat(S, 3) == S*S*S
end

# issue #12495: check that logical indexing attempt raises ArgumentError
@test_throws ArgumentError "abc"[[true, false, true]]
@test_throws ArgumentError "abc"[BitArray([true, false, true])]
Expand Down

0 comments on commit 9202df2

Please sign in to comment.