Skip to content

Commit

Permalink
rename to tryparse. call tryparse for floatNN_isvalid methods
Browse files Browse the repository at this point in the history
  • Loading branch information
tanmaykm committed Mar 12, 2015
1 parent 7f8b140 commit 59e6cdb
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 123 deletions.
4 changes: 1 addition & 3 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,7 @@ export
fldmod,
flipsign,
float,
maybefloat32,
maybefloat64,
maybeint,
tryparse,
floor,
fma,
frexp,
Expand Down
17 changes: 7 additions & 10 deletions base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export BigInt
import Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), ($),
binomial, cmp, convert, div, divrem, factorial, fld, gcd, gcdx, lcm, mod,
ndigits, promote_rule, rem, show, isqrt, string, isprime, powermod,
sum, trailing_zeros, trailing_ones, count_ones, base, parseint,
sum, trailing_zeros, trailing_ones, count_ones, base, parseint, tryparse_internal,
serialize, deserialize, bin, oct, dec, hex, isequal, invmod,
prevpow2, nextpow2, ndigits0z, widen, signed

Expand Down Expand Up @@ -76,28 +76,25 @@ signed(x::BigInt) = x
BigInt(x::BigInt) = x
BigInt(s::AbstractString) = parseint(BigInt,s)

function parse_bigint(s::AbstractString, base::Int, nothrow::Bool)
function tryparse_internal(::Type{BigInt}, s::AbstractString, base::Int, raise::Bool)
_n = Nullable{BigInt}()
s = bytestring(s)
sgn, base, i = Base.parseint_preamble(true,s,base)
if i == 0
nothrow && return _n
throw(ArgumentError("premature end of integer: $(repr(s))"))
raise && throw(ArgumentError("premature end of integer: $(repr(s))"))
return _n
end
z = BigInt()
err = ccall((:__gmpz_set_str, :libgmp),
Int32, (Ptr{BigInt}, Ptr{UInt8}, Int32),
&z, SubString(s,i), base)
if err != 0
nothrow && return _n
throw(ArgumentError("invalid BigInt: $(repr(s))"))
raise && throw(ArgumentError("invalid BigInt: $(repr(s))"))
return _n
end
Nullable(sgn < 0 ? -z : z)
end

Base.maybeint_internal(::Type{BigInt}, s::AbstractString, base::Int) = parse_bigint(s, base, true)
Base.parseint_nocheck(::Type{BigInt}, s::AbstractString, base::Int) = get(parse_bigint(s, base, false))

function BigInt(x::Union(Clong,Int32))
z = BigInt()
ccall((:__gmpz_set_si, :libgmp), Void, (Ptr{BigInt}, Clong), &z, x)
Expand Down Expand Up @@ -228,7 +225,7 @@ function serialize(s, n::BigInt)
serialize(s, base(62,n))
end

deserialize(s, ::Type{BigInt}) = Base.parseint_nocheck(BigInt, deserialize(s), 62)
deserialize(s, ::Type{BigInt}) = (tryparse_internal(BigInt, deserialize(s), 62, true)).value

# Binary ops
for (fJ, fC) in ((:+, :add), (:-,:sub), (:*, :mul),
Expand Down
151 changes: 57 additions & 94 deletions base/string.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1537,12 +1537,18 @@ safe_mul{T<:Integer}(n1::T, n2::T) = ((n2 > 0) ? ((n1 > div(typemax(T),n2)) ||
#safe_div{T<:Integer}(n1::T, n2::T) = ((n1 == typemin(T)) && (n2 == T(-1))) ? Nullable{T}() : Nullable{T}(div(n1, n2))
#safe_abs{T<:Integer}(n::T) = (n == typemin(T)) ? Nullable{T}() : abs(n)

function maybeint_internal{T<:Integer}(::Type{T}, s::AbstractString, base::Int, a::Int)
function tryparse_internal{T<:Integer}(::Type{T}, s::AbstractString, base::Int, a::Int, raise::Bool)
_n = Nullable{T}()
sgn, base, i = parseint_preamble(T<:Signed,s,base)
(i == 0) && return _n
if i == 0
raise && throw(ArgumentError("premature end of integer: $(repr(s))"))
return _n
end
c, i = parseint_next(s,i)
(i == 0) && return _n
if i == 0
raise && throw(ArgumentError("premature end of integer: $(repr(s))"))
return _n
end

base = convert(T,base)
m::T = div(typemax(T)-base+1,base)
Expand All @@ -1551,7 +1557,10 @@ function maybeint_internal{T<:Integer}(::Type{T}, s::AbstractString, base::Int,
d::T = '0' <= c <= '9' ? c-'0' :
'A' <= c <= 'Z' ? c-'A'+10 :
'a' <= c <= 'z' ? c-'a'+a : base
d < base || return _n
if d >= base
raise && throw(ArgumentError("invalid base $base digit $(repr(c)) in $(repr(s))"))
return _n
end
n *= base
n += d
if done(s,i)
Expand All @@ -1566,124 +1575,78 @@ function maybeint_internal{T<:Integer}(::Type{T}, s::AbstractString, base::Int,
d::T = '0' <= c <= '9' ? c-'0' :
'A' <= c <= 'Z' ? c-'A'+10 :
'a' <= c <= 'z' ? c-'a'+a : base
d < base || return _n
if d >= base
raise && throw(ArgumentError("invalid base $base digit $(repr(c)) in $(repr(s))"))
return _n
end
(T <: Signed) && (d *= sgn)

safe_n = safe_mul(n, base)
isnull(safe_n) || (safe_n = safe_add(get(safe_n), d))
isnull(safe_n) && return Nullable{T}()
n = get(safe_n)
safe_n.isnull || (safe_n = safe_add(safe_n.value, d))
if safe_n.isnull
raise && throw(OverflowError())
return _n
end
n = safe_n.value
done(s,i) && return Nullable{T}(n)
c, i = next(s,i)
end
while !done(s,i)
c, i = next(s,i)
isspace(c) || return _n
if !isspace(c)
raise && throw(ArgumentError("extra characters after whitespace in $(repr(s))"))
return _n
end
end
return Nullable{T}(n)
end
maybeint_internal{T<:Integer}(::Type{T}, s::AbstractString, base::Int) =
maybeint_internal(T, s, base, base <= 36 ? 10 : 36)
maybeint{T<:Integer}(::Type{T}, s::AbstractString) = maybeint_internal(T,s,0)
tryparse_internal{T<:Integer}(::Type{T}, s::AbstractString, base::Int, raise::Bool) =
tryparse_internal(T, s, base, base <= 36 ? 10 : 36, raise)
tryparse{T<:Integer}(::Type{T}, s::AbstractString, base::Int) =
2 <= base <= 62 ? tryparse_internal(T,s,Int(base),false) : throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $base"))
tryparse{T<:Integer}(::Type{T}, s::AbstractString) = tryparse_internal(T,s,0,false)

function parseint_nocheck{T<:Integer}(::Type{T}, s::AbstractString, base::Int, a::Int)
sgn, base, i = parseint_preamble(T<:Signed,s,base)
(i == 0) && throw(ArgumentError("premature end of integer: $(repr(s))"))

c, i = parseint_next(s,i)
(i == 0) && throw(ArgumentError("premature end of integer: $(repr(s))"))

base = convert(T,base)
## FIXME: remove 128-bit specific code once 128-bit div doesn't rely on BigInt
m::T = T===UInt128 || T===Int128 ? typemax(T) : div(typemax(T)-base+1,base)
n::T = 0
while n <= m
d::T = '0' <= c <= '9' ? c-'0' :
'A' <= c <= 'Z' ? c-'A'+10 :
'a' <= c <= 'z' ? c-'a'+a : base
d < base || throw(ArgumentError("invalid base $base digit $(repr(c)) in $(repr(s))"))
n *= base
n += d
if done(s,i)
n *= sgn
return n
end
c, i = next(s,i)
isspace(c) && break
end
(T <: Signed) && (n *= sgn)
while !isspace(c)
d::T = '0' <= c <= '9' ? c-'0' :
'A' <= c <= 'Z' ? c-'A'+10 :
'a' <= c <= 'z' ? c-'a'+a : base
d < base || throw(ArgumentError("invalid base $base digit $(repr(c)) in $(repr(s))"))
(T <: Signed) && (d *= sgn)
n = checked_mul(n,base)
n = checked_add(n,d)
done(s,i) && return n
c, i = next(s,i)
end
while !done(s,i)
c, i = next(s,i)
isspace(c) || throw(ArgumentError("extra characters after whitespace in $(repr(s))"))
end
return n
function parseint{T<:Integer}(::Type{T}, s::AbstractString, base::Integer)
(2 <= base <= 62) || throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $base"))
(tryparse_internal(T, s, base, true)).value
end
parseint_nocheck{T<:Integer}(::Type{T}, s::AbstractString, base::Int) =
parseint_nocheck(T, s, base, base <= 36 ? 10 : 36)

parseint{T<:Integer}(::Type{T}, s::AbstractString, base::Integer) =
2 <= base <= 62 ? parseint_nocheck(T,s,Int(base)) : throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $base"))
parseint{T<:Integer}(::Type{T}, s::AbstractString) = parseint_nocheck(T,s,0)
parseint{T<:Integer}(::Type{T}, s::AbstractString) = (tryparse_internal(T, s, 0, true)).value
parseint(s::AbstractString, base::Integer) = parseint(Int,s,base)
parseint(s::AbstractString) = parseint_nocheck(Int,s,0)
parseint(s::AbstractString) = parseint(Int,s)

## stringifying integers more efficiently ##

string(x::Union(Int8,Int16,Int32,Int64,Int128)) = dec(x)

## string to float functions ##

float64_isvalid(s::AbstractString, out::Array{Float64,1}) =
ccall(:jl_strtod, Int32, (Ptr{UInt8},Ptr{Float64}), s, out) == 0
float32_isvalid(s::AbstractString, out::Array{Float32,1}) =
ccall(:jl_strtof, Int32, (Ptr{UInt8},Ptr{Float32}), s, out) == 0

float64_isvalid(s::SubString, out::Array{Float64,1}) =
ccall(:jl_substrtod, Int32, (Ptr{UInt8},Csize_t,Cint,Ptr{Float64}), s.string, s.offset, s.endof, out) == 0
float32_isvalid(s::SubString, out::Array{Float32,1}) =
ccall(:jl_substrtof, Int32, (Ptr{UInt8},Csize_t,Cint,Ptr{Float32}), s.string, s.offset, s.endof, out) == 0

begin
local tmp::Array{Float64,1} = Array(Float64,1)
local tmpf::Array{Float32,1} = Array(Float32,1)
global parsefloat
function parsefloat(::Type{Float64}, s::AbstractString)
if !float64_isvalid(s, tmp)
throw(ArgumentError("parsefloat(Float64,::AbstractString): invalid number format $(repr(s))"))
end
return tmp[1]
end
tryparse(::Type{Float64}, s::AbstractString) = ccall(:jl_try_strtod, Nullable{Float64}, (Ptr{UInt8},), s)
tryparse(::Type{Float64}, s::SubString) = ccall(:jl_try_substrtod, Nullable{Float64}, (Ptr{UInt8},Csize_t,Cint), s.string, s.offset, s.endof)

function parsefloat(::Type{Float32}, s::AbstractString)
if !float32_isvalid(s, tmpf)
throw(ArgumentError("parsefloat(Float32,::AbstractString): invalid number format $(repr(s))"))
end
return tmpf[1]
end
end
tryparse(::Type{Float32}, s::AbstractString) = ccall(:jl_try_strtof, Nullable{Float32}, (Ptr{UInt8},), s)
tryparse(::Type{Float32}, s::SubString) = ccall(:jl_try_substrtof, Nullable{Float32}, (Ptr{UInt8},Csize_t,Cint), s.string, s.offset, s.endof)

float(x::AbstractString) = parsefloat(x)
parsefloat(x::AbstractString) = parsefloat(Float64,x)
function parse{T<:Union(Float32,Float64)}(::Type{T}, s::AbstractString)
nf = tryparse(T, s)
nf.isnull ? throw(ArgumentError("invalid number format $(repr(s)) for $T")) : nf.value
end

maybefloat64(s::AbstractString) = ccall(:jl_maybe_strtod, Nullable{Float64}, (Ptr{UInt8},), s)
maybefloat64(s::SubString) = ccall(:jl_maybe_substrtod, Nullable{Float64}, (Ptr{UInt8},Csize_t,Cint), s.string, s.offset, s.endof)
parsefloat{T<:Union(Float32,Float64)}(::Type{T}, s::AbstractString) = parse(T,s)

maybefloat32(s::AbstractString) = ccall(:jl_maybe_strtof, Nullable{Float32}, (Ptr{UInt8},), s)
maybefloat32(s::SubString) = ccall(:jl_maybe_substrtof, Nullable{Float32}, (Ptr{UInt8},Csize_t,Cint), s.string, s.offset, s.endof)
float(x::AbstractString) = parse(Float64,x)
parsefloat(x::AbstractString) = parse(Float64,x)

float{S<:AbstractString}(a::AbstractArray{S}) = map!(float, similar(a,typeof(float(0))), a)

function float_isvalid{T<:Union(Float32,Float64)}(s::AbstractString, out::Array{T,1})
tf = tryparse(T, s)
tf.isnull || (out[1] = tf.value)
!(tf.isnull)
end

float32_isvalid(s::AbstractString, out::Array{Float32,1}) = float_isvalid(s, out)
float64_isvalid(s::AbstractString, out::Array{Float64,1}) = float_isvalid(s, out)

# find the index of the first occurrence of a value in a byte array

typealias ByteArray Union(Array{UInt8,1},Array{Int8,1})
Expand Down
16 changes: 8 additions & 8 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ int str_isspace(char *p) {
return 1;
}

DLLEXPORT jl_nullable_float64_t jl_maybe_substrtod(char *str, size_t offset, int len)
DLLEXPORT jl_nullable_float64_t jl_try_substrtod(char *str, size_t offset, int len)
{
char *p;
char *bstr = str+offset;
Expand Down Expand Up @@ -793,7 +793,7 @@ DLLEXPORT jl_nullable_float64_t jl_maybe_substrtod(char *str, size_t offset, int
return (jl_nullable_float64_t){(uint8_t)err, out};
}

DLLEXPORT jl_nullable_float64_t jl_maybe_strtod(char *str)
DLLEXPORT jl_nullable_float64_t jl_try_strtod(char *str)
{
char *p;
int err = 0;
Expand All @@ -816,7 +816,7 @@ DLLEXPORT jl_nullable_float64_t jl_maybe_strtod(char *str)

DLLEXPORT int jl_substrtod(char *str, size_t offset, int len, double *out)
{
jl_nullable_float64_t nd = jl_maybe_substrtod(str, offset, len);
jl_nullable_float64_t nd = jl_try_substrtod(str, offset, len);
if(0 == nd.isnull) {
*out = nd.value;
return 0;
Expand All @@ -826,7 +826,7 @@ DLLEXPORT int jl_substrtod(char *str, size_t offset, int len, double *out)

DLLEXPORT int jl_strtod(char *str, double *out)
{
jl_nullable_float64_t nd = jl_maybe_strtod(str);
jl_nullable_float64_t nd = jl_try_strtod(str);
if(0 == nd.isnull) {
*out = nd.value;
return 0;
Expand All @@ -839,7 +839,7 @@ DLLEXPORT int jl_strtod(char *str, double *out)
#define HUGE_VALF (1e25f * 1e25f)
#endif

DLLEXPORT jl_nullable_float32_t jl_maybe_substrtof(char *str, size_t offset, int len)
DLLEXPORT jl_nullable_float32_t jl_try_substrtof(char *str, size_t offset, int len)
{
char *p;
char *bstr = str+offset;
Expand Down Expand Up @@ -879,7 +879,7 @@ DLLEXPORT jl_nullable_float32_t jl_maybe_substrtof(char *str, size_t offset, int
return (jl_nullable_float32_t){(uint8_t)err, out};
}

DLLEXPORT jl_nullable_float32_t jl_maybe_strtof(char *str)
DLLEXPORT jl_nullable_float32_t jl_try_strtof(char *str)
{
char *p;
int err = 0;
Expand All @@ -905,7 +905,7 @@ DLLEXPORT jl_nullable_float32_t jl_maybe_strtof(char *str)

DLLEXPORT int jl_substrtof(char *str, int offset, int len, float *out)
{
jl_nullable_float32_t nf = jl_maybe_substrtof(str, offset, len);
jl_nullable_float32_t nf = jl_try_substrtof(str, offset, len);
if(0 == nf.isnull) {
*out = nf.value;
return 0;
Expand All @@ -915,7 +915,7 @@ DLLEXPORT int jl_substrtof(char *str, int offset, int len, float *out)

DLLEXPORT int jl_strtof(char *str, float *out)
{
jl_nullable_float32_t nf = jl_maybe_strtof(str);
jl_nullable_float32_t nf = jl_try_strtof(str);
if(0 == nf.isnull) {
*out = nf.value;
return 0;
Expand Down
16 changes: 8 additions & 8 deletions test/strings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1409,21 +1409,21 @@ gstr = Base.GenericString("12");
for T in [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128]
for i in [typemax(T), typemin(T)]
s = "$i"
@test get(maybeint(T, s)) == i
@test get(tryparse(T, s)) == i
end
end

for T in [Int8, Int16, Int32, Int64, Int128]
for i in [typemax(T), typemin(T)]
f = "$(i)0"
@test isnull(maybeint(T, f))
@test isnull(tryparse(T, f))
end
end

@test get(maybeint(BigInt, "1234567890")) == BigInt(1234567890)
@test isnull(maybeint(BigInt, "1234567890-"))
@test get(tryparse(BigInt, "1234567890")) == BigInt(1234567890)
@test isnull(tryparse(BigInt, "1234567890-"))

@test get(maybefloat64("64")) == 64.0
@test isnull(maybefloat64("64o"))
@test get(maybefloat32("32")) == 32.0f0
@test isnull(maybefloat32("32o"))
@test get(tryparse(Float64, "64")) == 64.0
@test isnull(tryparse(Float64, "64o"))
@test get(tryparse(Float32, "32")) == 32.0f0
@test isnull(tryparse(Float32, "32o"))

0 comments on commit 59e6cdb

Please sign in to comment.