Skip to content

Commit

Permalink
Fix #6 by supporting AbstractString inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
quinnj committed Sep 25, 2018
1 parent 25f4741 commit 7ca4166
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 62 deletions.
8 changes: 4 additions & 4 deletions src/Parsers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ function parse end
"Attempt to parse a value of type `T` from `IO` `io`. Returns `nothing` on parser failures and invalid values."
function tryparse end

function parse(str::String, ::Type{T}; kwargs...) where {T}
function parse(str::AbstractString, ::Type{T}; kwargs...) where {T}
io = IOBuffer(str)
res = parse(defaultparser, io, T; kwargs...)
return ok(res.code) ? res.result : throw(Error(io, res))
Expand All @@ -248,7 +248,7 @@ function parse(io::IO, ::Type{T}; kwargs...) where {T}
res = parse(defaultparser, io, T; kwargs...)
return ok(res.code) ? res.result : throw(Error(io, res))
end
function parse(f::Base.Callable, str::String, ::Type{T}; kwargs...) where {T}
function parse(f::Base.Callable, str::AbstractString, ::Type{T}; kwargs...) where {T}
io = IOBuffer(str)
res = parse!(f, io, Result(T); kwargs...)
return ok(res.code) ? res.result : throw(Error(io, res))
Expand All @@ -258,15 +258,15 @@ function parse(f::Base.Callable, io::IO, ::Type{T}; kwargs...) where {T}
return ok(res.code) ? res.result : throw(Error(io, res))
end

function tryparse(str::String, ::Type{T}; kwargs...) where {T}
function tryparse(str::AbstractString, ::Type{T}; kwargs...) where {T}
res = parse(defaultparser, IOBuffer(str), T; kwargs...)
return ok(res.code) ? res.result : nothing
end
function tryparse(io::IO, ::Type{T}; kwargs...) where {T}
res = parse(defaultparser, io, T; kwargs...)
return ok(res.code) ? res.result : nothing
end
function tryparse(f::Base.Callable, str::String, ::Type{T}; kwargs...) where {T}
function tryparse(f::Base.Callable, str::AbstractString, ::Type{T}; kwargs...) where {T}
res = parse!(f, IOBuffer(str), Result(T); kwargs...)
return ok(res.code) ? res.result : nothing
end
Expand Down
130 changes: 72 additions & 58 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -501,64 +501,6 @@ include("floats.jl")
include("dates.jl")
include("bools.jl")

@testset "Misc" begin

@test Parsers.parse("101", Int) === 101
@test Parsers.parse("101,101", Float64; decimal=',') === 101.101
@test Parsers.parse(IOBuffer("true"), Bool) === true
@test_throws Parsers.Error Parsers.parse("abc", Int)

@test Parsers.tryparse("abc", Int) === nothing
@test Parsers.tryparse(IOBuffer("101,101"), Float32; decimal=',') === Float32(101.101)

# custom parser
function int2str(io::IO, r::Parsers.Result{Int}, args...)
v = 0
while !eof(io) && (UInt8('0') <= Parsers.peekbyte(io) <= UInt8('9'))
v *= 10
v += Int(Parsers.readbyte(io) - UInt8('0'))
end
r.result = v
r.code = OK
return r
end

@test Parsers.parse(int2str, "101", Int) === 101
@test Parsers.parse(int2str, IOBuffer("101"), Int) === 101
@test Parsers.tryparse(int2str, "101", Int) === 101
@test Parsers.tryparse(int2str, IOBuffer("101"), Int) === 101

@test Parsers.parse("01/20/2018", Date; dateformat="mm/dd/yyyy") === Date(2018, 1, 20)

@test_throws Parsers.Error Parsers.parse("", Missing)
@test Parsers.tryparse("", Missing) === nothing

r = Parsers.parse(Parsers.Quoted('{', '}', '\\'), IOBuffer("{1}"), Int)
@test r.result === 1
@test r.code === OK | QUOTED | EOF
@test r.pos == 0

let io=IOBuffer("1,2,null,4"), layers=Parsers.Delimited(Parsers.Quoted(Parsers.Sentinel(["null"])))
r = Parsers.parse(layers, io, Int)
@test r.result === 1
@test r.code === OK | DELIMITED
@test r.pos == 0
r = Parsers.parse(layers, io, Int)
@test r.result === 2
@test r.code === OK | DELIMITED
@test r.pos == 2
r = Parsers.parse(layers, io, Int)
@test r.result === missing
@test r.code === SENTINEL | DELIMITED
@test r.pos == 4
r = Parsers.parse(layers, io, Int)
@test r.result === 4
@test r.code === OK | EOF
@test r.pos == 9
end

end # @testset

@testset "ignore repeated delimiters" begin

let io=IOBuffer("1,,,2,null,4"), layers=Parsers.Delimited(Parsers.Quoted(Parsers.Sentinel(["null"])); ignore_repeated=true)
Expand Down Expand Up @@ -651,4 +593,76 @@ end

end # @testset

@testset "Misc" begin

@test Parsers.parse("101", Int) === 101
@test Parsers.parse("101,101", Float64; decimal=',') === 101.101
@test Parsers.parse(IOBuffer("true"), Bool) === true
@test_throws Parsers.Error Parsers.parse("abc", Int)

@test Parsers.tryparse("abc", Int) === nothing
@test Parsers.tryparse(IOBuffer("101,101"), Float32; decimal=',') === Float32(101.101)

# custom parser
function int2str(io::IO, r::Parsers.Result{Int}, args...)
v = 0
while !eof(io) && (UInt8('0') <= Parsers.peekbyte(io) <= UInt8('9'))
v *= 10
v += Int(Parsers.readbyte(io) - UInt8('0'))
end
r.result = v
r.code = OK
return r
end

@test Parsers.parse(int2str, "101", Int) === 101
@test Parsers.parse(int2str, IOBuffer("101"), Int) === 101
@test Parsers.tryparse(int2str, "101", Int) === 101
@test Parsers.tryparse(int2str, IOBuffer("101"), Int) === 101

@test Parsers.parse("01/20/2018", Date; dateformat="mm/dd/yyyy") === Date(2018, 1, 20)

@test_throws Parsers.Error Parsers.parse("", Missing)
@test Parsers.tryparse("", Missing) === nothing

r = Parsers.parse(Parsers.Quoted('{', '}', '\\'), IOBuffer("{1}"), Int)
@test r.result === 1
@test r.code === OK | QUOTED | EOF
@test r.pos == 0

let io=IOBuffer("1,2,null,4"), layers=Parsers.Delimited(Parsers.Quoted(Parsers.Sentinel(["null"])))
r = Parsers.parse(layers, io, Int)
@test r.result === 1
@test r.code === OK | DELIMITED
@test r.pos == 0
r = Parsers.parse(layers, io, Int)
@test r.result === 2
@test r.code === OK | DELIMITED
@test r.pos == 2
r = Parsers.parse(layers, io, Int)
@test r.result === missing
@test r.code === SENTINEL | DELIMITED
@test r.pos == 4
r = Parsers.parse(layers, io, Int)
@test r.result === 4
@test r.code === OK | EOF
@test r.pos == 9
end

# 6: AbstractString input
@test Parsers.parse(SubString("101"), Int) === 101
@test Parsers.parse(SubString("101,101"), Float64; decimal=',') === 101.101
@test Parsers.parse(IOBuffer("true"), Bool) === true
@test_throws Parsers.Error Parsers.parse("abc", Int)

@test Parsers.tryparse("abc", Int) === nothing
@test Parsers.tryparse(IOBuffer(SubString("101,101")), Float32; decimal=',') === Float32(101.101)

@test Parsers.parse(int2str, SubString("101"), Int) === 101
@test Parsers.parse(int2str, IOBuffer(SubString("101")), Int) === 101
@test Parsers.tryparse(int2str, SubString("101"), Int) === 101
@test Parsers.tryparse(int2str, IOBuffer(SubString("101")), Int) === 101

end # @testset

end # @testset

0 comments on commit 7ca4166

Please sign in to comment.