Repository: JuliaLang/julia
File: base/parse.jl (Julia)

Code before:
julia> parse(Complex{Float64}, "3.2e-1 + 4.5im")
0.32 + 4.5im
```
"""
parse(T::Type, str; base = Int)
parse(::Type{Union{}}, slurp...; kwargs...) = error("cannot parse a value as Union{}")

@noinline _invalid_base(base) = throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $base"))
@noinline _invalid_digit(base, char) = throw(ArgumentError("invalid base $base digit $(repr(char))"))

function parse_char(
        ::Type{T},
        c::AbstractChar,
        base::Integer,
        throw::Bool
    ) where {T <: Integer}
    a::UInt8 = (base <= 36 ? 10 : 36)
    if !(2 <= base <= 62)
        throw ? _invalid_base(base) : return nothing
    end
    base = base % UInt8
    codepoint = c > 'z' ? 0xff : UInt8(c)
    d = if UInt8('0') ≤ codepoint ≤ UInt8('9')
        codepoint - UInt8('0')
    elseif UInt8('A') ≤ codepoint ≤ UInt8('Z')
        codepoint - UInt8('A') + 0x0a # + 10 for the 10 digits
    elseif UInt8('a') ≤ codepoint ≤ UInt8('z')
        codepoint - UInt8('a') + a
    else
        0xff
    end
    if d >= base
        throw ? _invalid_digit(base, c) : return nothing
    end
    return convert(T, d)::T
end

function parse(::Type{T}, c::AbstractChar; base::Integer=10) where {T <: Integer}
    @inline parse_char(T, c, base, true)
end

function tryparse(::Type{T}, c::AbstractChar; base::Integer=10) where {T <: Integer}
    @inline parse_char(T, c, base, false)
end

function parseint_iterate(s::AbstractString, startpos::Int, endpos::Int)
    (0 < startpos <= endpos) || (return Char(0), 0, 0)
    j = startpos
    c, startpos = iterate(s,startpos)::Tuple{Char, Int}
    c, startpos, j
end

Review comment (suggestion):
```suggestion
        codepoint - UInt8('A') + UInt8(10) # + 10 for the 10 digits
```
Given that the comment is referring to "10" and the other UInt8s around here are expressed as conversion from more semantically clear types.

Code after:
julia> parse(Complex{Float64}, "3.2e-1 + 4.5im")
0.32 + 4.5im
```
"""
parse(T::Type, str; base = Int)
parse(::Type{Union{}}, slurp...; kwargs...) = error("cannot parse a value as Union{}")

@noinline function _invalid_base(base)
    throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $base"))
end

@noinline _invalid_digit(base, char) = throw(ArgumentError("invalid base $base digit $(repr(char))"))

function parse_char(::Type{T}, c::AbstractChar, base::Integer, throw::Bool) where T
    a::UInt8 = (base <= 36 ? 10 : 36)
    (2 <= base <= 62) || _invalid_base(base)
    base = base % UInt8
    cp = codepoint(c)
    cp = cp > 0x7a ? 0xff : cp % UInt8
    d = UInt8('0') ≤ cp ≤ UInt8('9') ? cp - UInt8('0') :
        UInt8('A') ≤ cp ≤ UInt8('Z') ? cp - UInt8('A') + UInt8(10) :
        UInt8('a') ≤ cp ≤ UInt8('z') ? cp - UInt8('a') + a :
        0xff
    d < base || (throw ? _invalid_digit(base, c) : return nothing)
    convert(T, d)::T
end

function parse(::Type{T}, c::AbstractChar; base::Integer=10) where {T <: Integer}
    @inline parse_char(T, c, base, true)
end

function tryparse(::Type{T}, c::AbstractChar; base::Integer=10) where {T <: Integer}
    @inline parse_char(T, c, base, false)
end

# For consistency with parse(t, AbstractString), support a `base` argument only when T<:Integer
parse(::Type{T}, c::AbstractChar) where T = @inline parse_char(T, c, 10, true)
tryparse(::Type{T}, c::AbstractChar) where T = @inline parse_char(T, c, 10, false)

function parseint_iterate(s::AbstractString, startpos::Int, endpos::Int)
    (0 < startpos <= endpos) || (return Char(0), 0, 0)
    j = startpos
    c, startpos = iterate(s,startpos)::Tuple{Char, Int}
    c, startpos, j
end

function parseint_preamble(signed::Bool, base::Int, s::AbstractString, startpos::Int, endpos::Int)
    c, i, j = parseint_iterate(s, startpos, endpos)

    while isspace(c)
        c, i, j = parseint_iterate(s,i,endpos)