@@ -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,125 @@ 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
+ # safe_sub{T<:Integer}(n1::T, n2::T) = ((n2 > 0) ? (n1 < (typemin(T) + n2)) : (n1 > (typemax(T) + n2))) ? Nullable{T}() : Nullable{T}(n1 - n2)
1537
+ # safe_div{T<:Integer}(n1::T, n2::T) = ((n1 == typemin(T)) && (n2 == T(-1))) ? Nullable{T}() : Nullable{T}(div(n1, n2))
1538
+ # safe_abs{T<:Integer}(n::T) = (n == typemin(T)) ? Nullable{T}() : abs(n)
1539
+
1540
+ function tryparse_internal {T<:Integer} (:: Type{T} , s:: AbstractString , base:: Int , a:: Int , raise:: Bool )
1541
+ _n = Nullable {T} ()
1526
1542
sgn, base, i = parseint_preamble (T<: Signed ,s,base)
1543
+ if i == 0
1544
+ raise && throw (ArgumentError (" premature end of integer: $(repr (s)) " ))
1545
+ return _n
1546
+ end
1527
1547
c, i = parseint_next (s,i)
1548
+ if i == 0
1549
+ raise && throw (ArgumentError (" premature end of integer: $(repr (s)) " ))
1550
+ return _n
1551
+ end
1552
+
1528
1553
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)
1554
+ m:: T = div (typemax (T)- base+ 1 ,base)
1531
1555
n:: T = 0
1532
1556
while n <= m
1533
1557
d:: T = ' 0' <= c <= ' 9' ? c- ' 0' :
1534
1558
' A' <= c <= ' Z' ? c- ' A' + 10 :
1535
1559
' a' <= c <= ' z' ? c- ' a' + a : base
1536
- d < base || throw (ArgumentError (" invalid base $base digit $(repr (c)) in $(repr (s)) " ))
1560
+ if d >= base
1561
+ raise && throw (ArgumentError (" invalid base $base digit $(repr (c)) in $(repr (s)) " ))
1562
+ return _n
1563
+ end
1537
1564
n *= base
1538
1565
n += d
1539
1566
if done (s,i)
1540
1567
n *= sgn
1541
- return n
1568
+ return Nullable {T} (n)
1542
1569
end
1543
1570
c, i = next (s,i)
1544
1571
isspace (c) && break
1545
1572
end
1546
1573
(T <: Signed ) && (n *= sgn)
1547
1574
while ! isspace (c)
1548
1575
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)) " ))
1576
+ ' A' <= c <= ' Z' ? c- ' A' + 10 :
1577
+ ' a' <= c <= ' z' ? c- ' a' + a : base
1578
+ if d >= base
1579
+ raise && throw (ArgumentError (" invalid base $base digit $(repr (c)) in $(repr (s)) " ))
1580
+ return _n
1581
+ end
1552
1582
(T <: Signed ) && (d *= sgn)
1553
- n = checked_mul (n,base)
1554
- n = checked_add (n,d)
1555
- done (s,i) && return n
1583
+
1584
+ safe_n = safe_mul (n, base)
1585
+ isnull (safe_n) || (safe_n = safe_add (get (safe_n), d))
1586
+ if isnull (safe_n)
1587
+ raise && throw (OverflowError ())
1588
+ return _n
1589
+ end
1590
+ n = get (safe_n)
1591
+ done (s,i) && return Nullable {T} (n)
1556
1592
c, i = next (s,i)
1557
1593
end
1558
1594
while ! done (s,i)
1559
1595
c, i = next (s,i)
1560
- isspace (c) || throw (ArgumentError (" extra characters after whitespace in $(repr (s)) " ))
1596
+ if ! isspace (c)
1597
+ raise && throw (ArgumentError (" extra characters after whitespace in $(repr (s)) " ))
1598
+ return _n
1599
+ end
1561
1600
end
1562
- return n
1601
+ return Nullable {T} (n)
1563
1602
end
1564
- parseint_nocheck {T<:Integer} (:: Type{T} , s:: AbstractString , base:: Int ) =
1565
- parseint_nocheck (T, s, base, base <= 36 ? 10 : 36 )
1603
+ tryparse_internal {T<:Integer} (:: Type{T} , s:: AbstractString , base:: Int , raise:: Bool ) =
1604
+ tryparse_internal (T, s, base, base <= 36 ? 10 : 36 , raise)
1605
+ tryparse {T<:Integer} (:: Type{T} , s:: AbstractString , base:: Int ) =
1606
+ 2 <= base <= 62 ? tryparse_internal (T,s,Int (base),false ) : throw (ArgumentError (" invalid base: base must be 2 ≤ base ≤ 62, got $base " ))
1607
+ tryparse {T<:Integer} (:: Type{T} , s:: AbstractString ) = tryparse_internal (T,s,0 ,false )
1566
1608
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 )
1609
+ function parseint {T<:Integer} (:: Type{T} , s:: AbstractString , base:: Integer )
1610
+ (2 <= base <= 62 ) || throw (ArgumentError (" invalid base: base must be 2 ≤ base ≤ 62, got $base " ))
1611
+ get (tryparse_internal (T, s, base, true ))
1612
+ end
1613
+ parseint {T<:Integer} (:: Type{T} , s:: AbstractString ) = get (tryparse_internal (T, s, 0 , true ))
1570
1614
parseint (s:: AbstractString , base:: Integer ) = parseint (Int,s,base)
1571
- parseint (s:: AbstractString ) = parseint_nocheck (Int,s, 0 )
1615
+ parseint (s:: AbstractString ) = parseint (Int,s)
1572
1616
1573
1617
# # stringifying integers more efficiently ##
1574
1618
1575
1619
string (x:: Union(Int8,Int16,Int32,Int64,Int128) ) = dec (x)
1576
1620
1577
1621
# # string to float functions ##
1578
1622
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
1623
+ tryparse (:: Type{Float64} , s:: AbstractString ) = ccall (:jl_try_strtod , Nullable{Float64}, (Ptr{UInt8},), s)
1624
+ tryparse (:: Type{Float64} , s:: SubString ) = ccall (:jl_try_substrtod , Nullable{Float64}, (Ptr{UInt8},Csize_t,Cint), s. string, s. offset, s. endof)
1599
1625
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
1626
+ tryparse (:: Type{Float32} , s:: AbstractString ) = ccall ( :jl_try_strtof , Nullable{Float32}, (Ptr{UInt8},), s )
1627
+ tryparse ( :: Type{Float32} , s :: SubString ) = ccall ( :jl_try_substrtof , Nullable{Float32}, (Ptr{UInt8},Csize_t,Cint), s . string, s . offset, s . endof )
1628
+
1629
+ function parse {T<:Union(Float32,Float64)} ( :: Type{T} , s :: AbstractString )
1630
+ nf = tryparse (T, s)
1631
+ isnull (nf) ? throw ( ArgumentError ( " invalid number format $( repr (s)) for $T " )) : get (nf)
1606
1632
end
1607
1633
1608
- float (x:: AbstractString ) = parsefloat (x)
1609
- parsefloat (x:: AbstractString ) = parsefloat (Float64,x)
1634
+ parsefloat {T<:Union(Float32,Float64)} (:: Type{T} , s:: AbstractString ) = parse (T,s)
1635
+
1636
+ float (x:: AbstractString ) = parse (Float64,x)
1637
+ parsefloat (x:: AbstractString ) = parse (Float64,x)
1610
1638
1611
1639
float {S<:AbstractString} (a:: AbstractArray{S} ) = map! (float, similar (a,typeof (float (0 ))), a)
1612
1640
1641
+ function float_isvalid {T<:Union(Float32,Float64)} (s:: AbstractString , out:: Array{T,1} )
1642
+ tf = tryparse (T, s)
1643
+ isnull (tf) || (out[1 ] = get (tf))
1644
+ ! isnull (tf)
1645
+ end
1646
+
1647
+ float32_isvalid (s:: AbstractString , out:: Array{Float32,1} ) = float_isvalid (s, out)
1648
+ float64_isvalid (s:: AbstractString , out:: Array{Float64,1} ) = float_isvalid (s, out)
1649
+
1613
1650
# find the index of the first occurrence of a value in a byte array
1614
1651
1615
1652
typealias ByteArray Union (Array{UInt8,1 },Array{Int8,1 })
0 commit comments