Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix unicode indexing in parse(Complex, string) #51758

Merged
merged 1 commit into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions base/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -321,14 +321,14 @@ function tryparse_internal(::Type{Complex{T}}, s::Union{String,SubString{String}
if i₊ == i # leading ± sign
i₊ = something(findnext(in(('+','-')), s, i₊+1), 0)
end
if i₊ != 0 && s[i₊-1] in ('e','E') # exponent sign
if i₊ != 0 && s[prevind(s, i₊)] in ('e','E') # exponent sign
Copy link
Member Author

@stevengj stevengj Oct 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self: Checks like this could be sped up further if we used codeunits(s) and did byte indexing/comparisons rather than Char comparisons. It would uglify the code and maybe the speedup would be small, however?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(In any case, speedups to this function should go into a separate PR, not a bugfix PR, since speedups need not be backported.)

i₊ = something(findnext(in(('+','-')), s, i₊+1), 0)
end

# find trailing im/i/j
iᵢ = something(findprev(in(('m','i','j')), s, e), 0)
if iᵢ > 0 && s[iᵢ] == 'm' # im
iᵢ -= 1
iᵢ = prevind(s, iᵢ)
if s[iᵢ] != 'i'
raise && throw(ArgumentError("expected trailing \"im\", found only \"m\""))
return nothing
Expand All @@ -337,7 +337,7 @@ function tryparse_internal(::Type{Complex{T}}, s::Union{String,SubString{String}

if i₊ == 0 # purely real or imaginary value
if iᵢ > i && !(iᵢ == i+1 && s[i] in ('+','-')) # purely imaginary (not "±inf")
x = tryparse_internal(T, s, i, iᵢ-1, raise)
x = tryparse_internal(T, s, i, prevind(s, iᵢ), raise)
x === nothing && return nothing
return Complex{T}(zero(x),x)
else # purely real
Expand All @@ -353,11 +353,11 @@ function tryparse_internal(::Type{Complex{T}}, s::Union{String,SubString{String}
end

# parse real part
re = tryparse_internal(T, s, i, i₊-1, raise)
re = tryparse_internal(T, s, i, prevind(s, i₊), raise)
re === nothing && return nothing

# parse imaginary part
im = tryparse_internal(T, s, i₊+1, iᵢ-1, raise)
im = tryparse_internal(T, s, i₊+1, prevind(s, iᵢ), raise)
im === nothing && return nothing

return Complex{T}(re, s[i₊]=='-' ? -im : im)
Expand Down
2 changes: 2 additions & 0 deletions test/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,8 @@ end
@test_throws ArgumentError parse(Complex{T}, bad)
end
@test_throws ArgumentError parse(Complex{Int}, "3 + 4.2im")
@test_throws ArgumentError parse(ComplexF64, "3 β+ 4im")
@test_throws ArgumentError parse(ComplexF64, "3 + 4αm")
end

@testset "parse and tryparse type inference" begin
Expand Down