Skip to content

Commit

Permalink
add peek(io, UInt8) and peek(io, Char) (JuliaLang#16025)
Browse files Browse the repository at this point in the history
  • Loading branch information
bicycle1885 committed May 3, 2016
1 parent fe92747 commit bcbac06
Show file tree
Hide file tree
Showing 13 changed files with 79 additions and 24 deletions.
4 changes: 2 additions & 2 deletions base/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ using ..Terminals
import ..Terminals: raw!, width, height, cmove, getX,
getY, clear_line, beep

import Base: ensureroom, peek, show, AnyDict
import Base: ensureroom, show, AnyDict

abstract TextInterface
abstract ModeState
Expand Down Expand Up @@ -290,7 +290,7 @@ char_move_left(s::PromptState) = char_move_left(s.input_buffer)
function char_move_left(buf::IOBuffer)
while position(buf) > 0
seek(buf, position(buf)-1)
c = peek(buf)
c = peek(buf, UInt8)
(((c & 0x80) == 0) || ((c & 0xc0) == 0xc0)) && break
end
pos = position(buf)
Expand Down
2 changes: 1 addition & 1 deletion base/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ function hist_from_file(hp, file)
while !isempty(line)
push!(lines, chomp(line[2:end]))
eof(file) && break
ch = Base.peek(file)
ch = peek(file, Char)
ch == ' ' && error(munged_history_message, countlines)
ch != '\t' && break
line = hist_getline(file)
Expand Down
7 changes: 7 additions & 0 deletions base/docs/helpdb/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5922,6 +5922,13 @@ Open a file and read its contents. `args` is passed to `read`: this is equivalen
"""
read(filename, args...)

"""
peek(stream::IO, T)
Similar to `read`, but does not advance the reading position.
"""
peek(stream, t)

"""
@timev
Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,7 @@ export
poll_file,
position,
RawFD,
peek,
read,
read!,
readavailable,
Expand Down
34 changes: 31 additions & 3 deletions base/iobuffer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,43 @@ end
return byte
end

function peek(from::AbstractIOBuffer)
from.readable || throw(ArgumentError("read failed, IOBuffer is not readable"))
read{T}(from::AbstractIOBuffer, ::Type{Ptr{T}}) = convert(Ptr{T}, read(from, UInt))

function peek(from::AbstractIOBuffer, ::Type{UInt8})
from.readable || throw(ArgumentError("peek failed, IOBuffer is not readable"))
if from.ptr > from.size
throw(EOFError())
end
return from.data[from.ptr]
end

read{T}(from::AbstractIOBuffer, ::Type{Ptr{T}}) = convert(Ptr{T}, read(from, UInt))
function peek(from::AbstractIOBuffer, ::Type{Char})
from.readable || throw(ArgumentError("peek failed, IOBuffer is not readable"))
ptr = from.ptr
if ptr > from.size
throw(EOFError())
end
ch = from.data[ptr]
if ch < 0x80
# ASCII
return Char(ch)
else
# UTF8
trailing = utf8_trailing[ch+1]
if trailing > from.size - ptr
throw(EOFError())
end
c::UInt32 = 0
for _ in 1:trailing
c += ch
c <<= 6
ch = from.data[ptr+=1]
end
c += ch
c -= utf8_offset[trailing+1]
return Char(c)
end
end

isreadable(io::AbstractIOBuffer) = io.readable
iswritable(io::AbstractIOBuffer) = io.writable
Expand Down
19 changes: 11 additions & 8 deletions base/iostream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -254,27 +254,30 @@ function read(s::IOStream, nb::Integer; all::Bool=true)
end

## Character streams ##
const _chtmp = Array(Char, 1)
function peekchar(s::IOStream)
const _chtmp = Ref{Char}()
function peek(s::IOStream, ::Type{Char})
if ccall(:ios_peekutf8, Cint, (Ptr{Void}, Ptr{Char}), s, _chtmp) < 0
return Char(-1)
throw(EOFError())
end
return _chtmp[1]
return _chtmp[]
end

function peek(s::IOStream)
ccall(:ios_peekc, Cint, (Ptr{Void},), s)
function peek(s::IOStream, ::Type{UInt8})
if eof(s)
throw(EOFError())
end
return convert(UInt8, ccall(:ios_peekc, Cint, (Ptr{Void},), s))
end

function skipchars(s::IOStream, pred; linecomment::Char=Char(0xffffffff))
ch = peekchar(s); status = Int(ch)
ch = peek(s, Char); status = Int(ch)
while status >= 0 && (pred(ch) || ch == linecomment)
if ch == linecomment
readline(s)
else
read(s, Char) # advance one character
end
ch = peekchar(s); status = Int(ch)
ch = peek(s, Char); status = Int(ch)
end
return s
end
4 changes: 2 additions & 2 deletions base/markdown/Common/block.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function paragraph(stream::IO, md::MD)
while !eof(stream)
char = read(stream, Char)
if char == '\n' || char == '\r'
char == '\r' && peek(stream) == '\n' && read(stream, Char)
char == '\r' && peek(stream, Char) == '\n' && read(stream, Char)
if prev_char == '\\'
write(buffer, '\n')
elseif blankline(stream) || parse(stream, md, breaking = true)
Expand Down Expand Up @@ -198,7 +198,7 @@ function list(stream::IO, block::MD)
c = read(stream, Char)
if c == '\n'
eof(stream) && break
next = peek(stream)
next = peek(stream, Char)
if next == '\n'
break
else
Expand Down
2 changes: 1 addition & 1 deletion base/markdown/Julia/interp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ end

function interpinner(stream::IO, greedy = false)
startswith(stream, '$') || return
(eof(stream) || peek(stream) in whitespace) && return
(eof(stream) || peek(stream, Char) in whitespace) && return
try
return Base.parse(stream::IOBuffer, greedy = greedy)
catch e
Expand Down
2 changes: 1 addition & 1 deletion base/markdown/parse/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function parseinline(stream::IO, md::MD, config::Config)
content = []
buffer = IOBuffer()
while !eof(stream)
char = peek(stream)
char = peek(stream, Char)
if haskey(config.inner, char) &&
(inner = parseinline(stream, md, config.inner[char])) !== nothing
c = takebuf_string(buffer)
Expand Down
9 changes: 4 additions & 5 deletions base/markdown/parse/util.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# This file is a part of Julia. License is MIT: http://julialang.org/license

import Base: peek

macro dotimes(n, body)
quote
for i = 1:$(esc(n))
Expand All @@ -16,7 +14,8 @@ const whitespace = " \t\r"
Skip any leading whitespace. Returns io.
"""
function skipwhitespace(io::IO; newlines = true)
while !eof(io) && (peek(io) in whitespace || (newlines && peek(io) == '\n'))
while !eof(io) && (peek(io, Char) in whitespace ||
newlines && peek(io, Char) == '\n')
read(io, Char)
end
return io
Expand Down Expand Up @@ -82,7 +81,7 @@ function startswith(stream::IO, s::AbstractString; eat = true, padding = false,
end

function startswith(stream::IO, c::Char; eat = true)
if !eof(stream) && peek(stream) == c
if !eof(stream) && peek(stream, Char) == c
eat && read(stream, Char)
return true
else
Expand Down Expand Up @@ -181,7 +180,7 @@ function parse_inline_wrapper(stream::IO, delimiter::AbstractString; rep = false
startswith(stream, delimiter^n) || return nothing
while startswith(stream, delimiter); n += 1; end
!rep && n > nmin && return nothing
!eof(stream) && peek(stream) in whitespace && return nothing
!eof(stream) && peek(stream, Char) in whitespace && return nothing

buffer = IOBuffer()
while !eof(stream)
Expand Down
2 changes: 1 addition & 1 deletion base/precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ precompile(Base.notify, (Condition, Any))
precompile(Base.open, (ASCIIString, ASCIIString))
precompile(Base.parse_input_line, (ASCIIString,))
precompile(Base.parse, (Type{Int}, ASCIIString, Int))
precompile(Base.peek, (Base.IOBuffer,))
precompile(Base.peek, (Base.IOBuffer, Type{Char}))
precompile(Base.pop!, (Array{Any,1},))
precompile(Base.position, (IOBuffer,))
precompile(Base.prepend!, (Array{Dict{Any, Any}, 1}, Array{Dict{Any, Any}, 1}))
Expand Down
14 changes: 14 additions & 0 deletions test/file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1095,3 +1095,17 @@ function test_13559()
rm(fn)
end
@unix_only test_13559()

# test peek (#16025)
let n = tempname()
w = open(n, "a")
io = open(n)
write(w, "A"); flush(w)
@test peek(io, UInt8) === 0x41
@test peek(io, Char) === 'A'
read(io, UInt8)
@test_throws EOFError peek(io, UInt8)
@test_throws EOFError peek(io, Char)
close(io); close(w)
rm(n)
end
3 changes: 3 additions & 0 deletions test/iobuffer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ ioslength(io::IOBuffer) = (io.seekable ? io.size : nb_available(io))
let io = IOBuffer()
@test eof(io)
@test_throws EOFError read(io,UInt8)
@test_throws EOFError peek(io,UInt8)
@test write(io,"abc") == 3
@test isreadable(io)
@test iswritable(io)
Expand All @@ -14,6 +15,7 @@ let io = IOBuffer()
@test eof(io)
seek(io, 0)
@test read(io,UInt8) == convert(UInt8, 'a')
@test peek(io,UInt8) == convert(UInt8, 'b')
a = Array(UInt8, 2)
@test read!(io, a) == a
@test a == UInt8['b','c']
Expand Down Expand Up @@ -154,6 +156,7 @@ end

# pr #11554
let io=IOBuffer(SubString("***αhelloworldω***",4,16)), io2 = IOBuffer(b"goodnightmoon", true, true)
@test peek(io, Char) == 'α'
@test read(io, Char) == 'α'
@test_throws ArgumentError write(io,"!")
@test_throws ArgumentError write(io,'β')
Expand Down

0 comments on commit bcbac06

Please sign in to comment.