From 7ca4166a22c98deece40cbf48da1e4753e863ff2 Mon Sep 17 00:00:00 2001 From: quinnj Date: Mon, 24 Sep 2018 20:37:40 -0600 Subject: [PATCH] Fix #6 by supporting AbstractString inputs --- src/Parsers.jl | 8 +-- test/runtests.jl | 130 ++++++++++++++++++++++++++--------------------- 2 files changed, 76 insertions(+), 62 deletions(-) diff --git a/src/Parsers.jl b/src/Parsers.jl index 6102669b85..6875ea7c3c 100644 --- a/src/Parsers.jl +++ b/src/Parsers.jl @@ -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)) @@ -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)) @@ -258,7 +258,7 @@ 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 @@ -266,7 +266,7 @@ 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 diff --git a/test/runtests.jl b/test/runtests.jl index 1d082618b5..a2bd199e3a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -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) @@ -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