@@ -1487,27 +1487,33 @@ parseint{T<:Integer}(::Type{T}, c::Char, base::Integer) = convert(T,parseint(c,b
1487
1487
parseint {T<:Integer} (:: Type{T} , c:: Char ) = convert (T,parseint (c))
1488
1488
1489
1489
function parseint_next (s:: AbstractString , i:: Int = start (s))
1490
- done (s,i) && throw ( ArgumentError ( " premature end of integer: $( repr (s)) " ) )
1490
+ done (s,i) && ( return Char ( 0 ), 0 , 0 )
1491
1491
j = i
1492
1492
c, i = next (s,i)
1493
1493
c, i, j
1494
1494
end
1495
1495
1496
1496
function parseint_preamble (signed:: Bool , s:: AbstractString , base:: Int )
1497
1497
c, i, j = parseint_next (s)
1498
+
1498
1499
while isspace (c)
1499
1500
c, i, j = parseint_next (s,i)
1500
1501
end
1502
+ (j == 0 ) && (return 0 , 0 , 0 )
1503
+
1501
1504
sgn = 1
1502
1505
if signed
1503
1506
if c == ' -' || c == ' +'
1504
1507
(c == ' -' ) && (sgn = - 1 )
1505
1508
c, i, j = parseint_next (s,i)
1506
1509
end
1507
1510
end
1511
+
1508
1512
while isspace (c)
1509
1513
c, i, j = parseint_next (s,i)
1510
1514
end
1515
+ (j == 0 ) && (return 0 , 0 , 0 )
1516
+
1511
1517
if base == 0
1512
1518
if c == ' 0' && ! done (s,i)
1513
1519
c, i = next (s,i)
@@ -1522,94 +1528,121 @@ function parseint_preamble(signed::Bool, s::AbstractString, base::Int)
1522
1528
return sgn, base, j
1523
1529
end
1524
1530
1525
- function parseint_nocheck {T<:Integer} (:: Type{T} , s:: AbstractString , base:: Int , a:: Int )
1531
+ safe_add {T<:Integer} (n1:: T , n2:: T ) = ((n2 > 0 ) ? (n1 > (typemax (T) - n2)) : (n1 < (typemin (T) - n2))) ? Nullable {T} () : Nullable {T} (n1 + n2)
1532
+ safe_mul {T<:Integer} (n1:: T , n2:: T ) = ((n2 > 0 ) ? ((n1 > div (typemax (T),n2)) || (n1 < div (typemin (T),n2))) :
1533
+ (n2 < - 1 ) ? ((n1 > div (typemin (T),n2)) || (n1 < div (typemax (T),n2))) :
1534
+ ((n2 == - 1 ) && n1 == typemin (T))) ? Nullable {T} () : Nullable {T} (n1 * n2)
1535
+
1536
+ function tryparse_internal {T<:Integer} (:: Type{T} , s:: AbstractString , base:: Int , a:: Int , raise:: Bool )
1537
+ _n = Nullable {T} ()
1526
1538
sgn, base, i = parseint_preamble (T<: Signed ,s,base)
1539
+ if i == 0
1540
+ raise && throw (ArgumentError (" premature end of integer: $(repr (s)) " ))
1541
+ return _n
1542
+ end
1527
1543
c, i = parseint_next (s,i)
1544
+ if i == 0
1545
+ raise && throw (ArgumentError (" premature end of integer: $(repr (s)) " ))
1546
+ return _n
1547
+ end
1548
+
1528
1549
base = convert (T,base)
1529
- # # FIXME : remove 128-bit specific code once 128-bit div doesn't rely on BigInt
1530
- m:: T = T=== UInt128 || T=== Int128 ? typemax (T) : div (typemax (T)- base+ 1 ,base)
1550
+ m:: T = div (typemax (T)- base+ 1 ,base)
1531
1551
n:: T = 0
1532
1552
while n <= m
1533
1553
d:: T = ' 0' <= c <= ' 9' ? c- ' 0' :
1534
1554
' A' <= c <= ' Z' ? c- ' A' + 10 :
1535
1555
' a' <= c <= ' z' ? c- ' a' + a : base
1536
- d < base || throw (ArgumentError (" invalid base $base digit $(repr (c)) in $(repr (s)) " ))
1556
+ if d >= base
1557
+ raise && throw (ArgumentError (" invalid base $base digit $(repr (c)) in $(repr (s)) " ))
1558
+ return _n
1559
+ end
1537
1560
n *= base
1538
1561
n += d
1539
1562
if done (s,i)
1540
1563
n *= sgn
1541
- return n
1564
+ return Nullable {T} (n)
1542
1565
end
1543
1566
c, i = next (s,i)
1544
1567
isspace (c) && break
1545
1568
end
1546
1569
(T <: Signed ) && (n *= sgn)
1547
1570
while ! isspace (c)
1548
1571
d:: T = ' 0' <= c <= ' 9' ? c- ' 0' :
1549
- ' A' <= c <= ' Z' ? c- ' A' + 10 :
1550
- ' a' <= c <= ' z' ? c- ' a' + a : base
1551
- d < base || throw (ArgumentError (" invalid base $base digit $(repr (c)) in $(repr (s)) " ))
1572
+ ' A' <= c <= ' Z' ? c- ' A' + 10 :
1573
+ ' a' <= c <= ' z' ? c- ' a' + a : base
1574
+ if d >= base
1575
+ raise && throw (ArgumentError (" invalid base $base digit $(repr (c)) in $(repr (s)) " ))
1576
+ return _n
1577
+ end
1552
1578
(T <: Signed ) && (d *= sgn)
1553
- n = checked_mul (n,base)
1554
- n = checked_add (n,d)
1555
- done (s,i) && return n
1579
+
1580
+ safe_n = safe_mul (n, base)
1581
+ isnull (safe_n) || (safe_n = safe_add (get (safe_n), d))
1582
+ if isnull (safe_n)
1583
+ raise && throw (OverflowError ())
1584
+ return _n
1585
+ end
1586
+ n = get (safe_n)
1587
+ done (s,i) && return Nullable {T} (n)
1556
1588
c, i = next (s,i)
1557
1589
end
1558
1590
while ! done (s,i)
1559
1591
c, i = next (s,i)
1560
- isspace (c) || throw (ArgumentError (" extra characters after whitespace in $(repr (s)) " ))
1592
+ if ! isspace (c)
1593
+ raise && throw (ArgumentError (" extra characters after whitespace in $(repr (s)) " ))
1594
+ return _n
1595
+ end
1561
1596
end
1562
- return n
1597
+ return Nullable {T} (n)
1563
1598
end
1564
- parseint_nocheck {T<:Integer} (:: Type{T} , s:: AbstractString , base:: Int ) =
1565
- parseint_nocheck (T, s, base, base <= 36 ? 10 : 36 )
1599
+ tryparse_internal {T<:Integer} (:: Type{T} , s:: AbstractString , base:: Int , raise:: Bool ) =
1600
+ tryparse_internal (T, s, base, base <= 36 ? 10 : 36 , raise)
1601
+ tryparse {T<:Integer} (:: Type{T} , s:: AbstractString , base:: Int ) =
1602
+ 2 <= base <= 62 ? tryparse_internal (T,s,Int (base),false ) : throw (ArgumentError (" invalid base: base must be 2 ≤ base ≤ 62, got $base " ))
1603
+ tryparse {T<:Integer} (:: Type{T} , s:: AbstractString ) = tryparse_internal (T,s,0 ,false )
1566
1604
1567
- parseint {T<:Integer} (:: Type{T} , s:: AbstractString , base:: Integer ) =
1568
- 2 <= base <= 62 ? parseint_nocheck (T,s,Int (base)) : throw (ArgumentError (" invalid base: base must be 2 ≤ base ≤ 62, got $base " ))
1569
- parseint {T<:Integer} (:: Type{T} , s:: AbstractString ) = parseint_nocheck (T,s,0 )
1605
+ function parseint {T<:Integer} (:: Type{T} , s:: AbstractString , base:: Integer )
1606
+ (2 <= base <= 62 ) || throw (ArgumentError (" invalid base: base must be 2 ≤ base ≤ 62, got $base " ))
1607
+ get (tryparse_internal (T, s, base, true ))
1608
+ end
1609
+ parseint {T<:Integer} (:: Type{T} , s:: AbstractString ) = get (tryparse_internal (T, s, 0 , true ))
1570
1610
parseint (s:: AbstractString , base:: Integer ) = parseint (Int,s,base)
1571
- parseint (s:: AbstractString ) = parseint_nocheck (Int,s, 0 )
1611
+ parseint (s:: AbstractString ) = parseint (Int,s)
1572
1612
1573
1613
# # stringifying integers more efficiently ##
1574
1614
1575
1615
string (x:: Union(Int8,Int16,Int32,Int64,Int128) ) = dec (x)
1576
1616
1577
1617
# # string to float functions ##
1578
1618
1579
- float64_isvalid (s:: AbstractString , out:: Array{Float64,1} ) =
1580
- ccall (:jl_strtod , Int32, (Ptr{UInt8},Ptr{Float64}), s, out) == 0
1581
- float32_isvalid (s:: AbstractString , out:: Array{Float32,1} ) =
1582
- ccall (:jl_strtof , Int32, (Ptr{UInt8},Ptr{Float32}), s, out) == 0
1583
-
1584
- float64_isvalid (s:: SubString , out:: Array{Float64,1} ) =
1585
- ccall (:jl_substrtod , Int32, (Ptr{UInt8},Csize_t,Cint,Ptr{Float64}), s. string, s. offset, s. endof, out) == 0
1586
- float32_isvalid (s:: SubString , out:: Array{Float32,1} ) =
1587
- ccall (:jl_substrtof , Int32, (Ptr{UInt8},Csize_t,Cint,Ptr{Float32}), s. string, s. offset, s. endof, out) == 0
1588
-
1589
- begin
1590
- local tmp:: Array{Float64,1} = Array (Float64,1 )
1591
- local tmpf:: Array{Float32,1} = Array (Float32,1 )
1592
- global parsefloat
1593
- function parsefloat (:: Type{Float64} , s:: AbstractString )
1594
- if ! float64_isvalid (s, tmp)
1595
- throw (ArgumentError (" parsefloat(Float64,::AbstractString): invalid number format $(repr (s)) " ))
1596
- end
1597
- return tmp[1 ]
1598
- end
1619
+ tryparse (:: Type{Float64} , s:: AbstractString ) = ccall (:jl_try_strtod , Nullable{Float64}, (Ptr{UInt8},), s)
1620
+ tryparse (:: Type{Float64} , s:: SubString ) = ccall (:jl_try_substrtod , Nullable{Float64}, (Ptr{UInt8},Csize_t,Cint), s. string, s. offset, s. endof)
1599
1621
1600
- function parsefloat (:: Type{Float32} , s:: AbstractString )
1601
- if ! float32_isvalid (s, tmpf )
1602
- throw ( ArgumentError ( " parsefloat(Float32,::AbstractString): invalid number format $( repr (s)) " ))
1603
- end
1604
- return tmpf[ 1 ]
1605
- end
1622
+ tryparse (:: Type{Float32} , s:: AbstractString ) = ccall ( :jl_try_strtof , Nullable{Float32}, (Ptr{UInt8},), s )
1623
+ tryparse ( :: Type{Float32} , s :: SubString ) = ccall ( :jl_try_substrtof , Nullable{Float32}, (Ptr{UInt8},Csize_t,Cint), s . string, s . offset, s . endof )
1624
+
1625
+ function parse {T<:Union(Float32,Float64)} ( :: Type{T} , s :: AbstractString )
1626
+ nf = tryparse (T, s)
1627
+ isnull (nf) ? throw ( ArgumentError ( " invalid number format $( repr (s)) for $T " )) : get (nf)
1606
1628
end
1607
1629
1608
- float (x:: AbstractString ) = parsefloat (x)
1609
- parsefloat (x:: AbstractString ) = parsefloat (Float64,x)
1630
+ parsefloat {T<:Union(Float32,Float64)} (:: Type{T} , s:: AbstractString ) = parse (T,s)
1631
+
1632
+ float (x:: AbstractString ) = parse (Float64,x)
1633
+ parsefloat (x:: AbstractString ) = parse (Float64,x)
1610
1634
1611
1635
float {S<:AbstractString} (a:: AbstractArray{S} ) = map! (float, similar (a,typeof (float (0 ))), a)
1612
1636
1637
+ function float_isvalid {T<:Union(Float32,Float64)} (s:: AbstractString , out:: Array{T,1} )
1638
+ tf = tryparse (T, s)
1639
+ isnull (tf) || (out[1 ] = get (tf))
1640
+ ! isnull (tf)
1641
+ end
1642
+
1643
+ float32_isvalid (s:: AbstractString , out:: Array{Float32,1} ) = float_isvalid (s, out)
1644
+ float64_isvalid (s:: AbstractString , out:: Array{Float64,1} ) = float_isvalid (s, out)
1645
+
1613
1646
# find the index of the first occurrence of a value in a byte array
1614
1647
1615
1648
typealias ByteArray Union (Array{UInt8,1 },Array{Int8,1 })
0 commit comments