Add: julia-0.6.2
Former-commit-id: ccc667cf67d569f3fb3df39aa57c2134755a7551
This commit is contained in:
646
julia-0.6.2/share/julia/base/io.jl
Normal file
646
julia-0.6.2/share/julia/base/io.jl
Normal file
@@ -0,0 +1,646 @@
|
||||
# This file is a part of Julia. License is MIT: https://julialang.org/license
|
||||
|
||||
# Generic IO stubs -- all subtypes should implement these (if meaningful)
|
||||
|
||||
lock(::IO) = nothing
|
||||
unlock(::IO) = nothing
|
||||
reseteof(x::IO) = nothing
|
||||
|
||||
const SZ_UNBUFFERED_IO = 65536
|
||||
buffer_writes(x::IO, bufsize=SZ_UNBUFFERED_IO) = x
|
||||
|
||||
"""
|
||||
isopen(object) -> Bool
|
||||
|
||||
Determine whether an object - such as a stream, timer, or mmap -- is not yet closed. Once an
|
||||
object is closed, it will never produce a new event. However, a closed stream may still have
|
||||
data to read in its buffer, use [`eof`](@ref) to check for the ability to read data.
|
||||
Use [`poll_fd`](@ref) to be notified when a stream might be writable or readable.
|
||||
"""
|
||||
function isopen end
|
||||
|
||||
"""
|
||||
close(stream)
|
||||
|
||||
Close an I/O stream. Performs a [`flush`](@ref) first.
|
||||
"""
|
||||
function close end
|
||||
function flush end
|
||||
function wait_connected end
|
||||
function wait_readnb end
|
||||
function wait_readbyte end
|
||||
function wait_close end
|
||||
function nb_available end
|
||||
function readavailable end
|
||||
|
||||
"""
|
||||
isreadable(io) -> Bool
|
||||
|
||||
Returns `true` if the specified IO object is readable (if that can be determined).
|
||||
"""
|
||||
function isreadable end
|
||||
|
||||
"""
|
||||
iswritable(io) -> Bool
|
||||
|
||||
Returns `true` if the specified IO object is writable (if that can be determined).
|
||||
"""
|
||||
function iswritable end
|
||||
function copy end
|
||||
function eof end
|
||||
|
||||
"""
|
||||
write(stream::IO, x)
|
||||
write(filename::AbstractString, x)
|
||||
|
||||
Write the canonical binary representation of a value to the given I/O stream or file.
|
||||
Returns the number of bytes written into the stream.
|
||||
|
||||
You can write multiple values with the same `write` call. i.e. the following are equivalent:
|
||||
|
||||
write(stream, x, y...)
|
||||
write(stream, x) + write(stream, y...)
|
||||
"""
|
||||
function write end
|
||||
|
||||
read(s::IO, ::Type{UInt8}) = error(typeof(s)," does not support byte I/O")
|
||||
write(s::IO, x::UInt8) = error(typeof(s)," does not support byte I/O")
|
||||
|
||||
"""
|
||||
unsafe_write(io::IO, ref, nbytes::UInt)
|
||||
|
||||
Copy `nbytes` from `ref` (converted to a pointer) into the `IO` object.
|
||||
|
||||
It is recommended that subtypes `T<:IO` override the following method signature
|
||||
to provide more efficient implementations:
|
||||
`unsafe_write(s::T, p::Ptr{UInt8}, n::UInt)`
|
||||
"""
|
||||
function unsafe_write(s::IO, p::Ptr{UInt8}, n::UInt)
|
||||
local written::Int = 0
|
||||
for i = 1:n
|
||||
written += write(s, unsafe_load(p, i))
|
||||
end
|
||||
return written
|
||||
end
|
||||
|
||||
"""
|
||||
unsafe_read(io::IO, ref, nbytes::UInt)
|
||||
|
||||
Copy `nbytes` from the `IO` stream object into `ref` (converted to a pointer).
|
||||
|
||||
It is recommended that subtypes `T<:IO` override the following method signature
|
||||
to provide more efficient implementations:
|
||||
`unsafe_read(s::T, p::Ptr{UInt8}, n::UInt)`
|
||||
"""
|
||||
function unsafe_read(s::IO, p::Ptr{UInt8}, n::UInt)
|
||||
for i = 1:n
|
||||
unsafe_store!(p, read(s, UInt8)::UInt8, i)
|
||||
end
|
||||
nothing
|
||||
end
|
||||
|
||||
|
||||
# Generic wrappers around other IO objects
|
||||
abstract type AbstractPipe <: IO end
|
||||
function pipe_reader end
|
||||
function pipe_writer end
|
||||
|
||||
write(io::AbstractPipe, byte::UInt8) = write(pipe_writer(io), byte)
|
||||
unsafe_write(io::AbstractPipe, p::Ptr{UInt8}, nb::UInt) = unsafe_write(pipe_writer(io), p, nb)
|
||||
buffer_writes(io::AbstractPipe, args...) = buffer_writes(pipe_writer(io), args...)
|
||||
flush(io::AbstractPipe) = flush(pipe_writer(io))
|
||||
|
||||
read(io::AbstractPipe, byte::Type{UInt8}) = read(pipe_reader(io), byte)
|
||||
unsafe_read(io::AbstractPipe, p::Ptr{UInt8}, nb::UInt) = unsafe_read(pipe_reader(io), p, nb)
|
||||
read(io::AbstractPipe) = read(pipe_reader(io))
|
||||
readuntil(io::AbstractPipe, arg::UInt8) = readuntil(pipe_reader(io), arg)
|
||||
readuntil(io::AbstractPipe, arg::Char) = readuntil(pipe_reader(io), arg)
|
||||
readuntil(io::AbstractPipe, arg::AbstractString) = readuntil(pipe_reader(io), arg)
|
||||
readuntil(io::AbstractPipe, arg) = readuntil(pipe_reader(io), arg)
|
||||
readavailable(io::AbstractPipe) = readavailable(pipe_reader(io))
|
||||
|
||||
isreadable(io::AbstractPipe) = isreadable(pipe_reader(io))
|
||||
iswritable(io::AbstractPipe) = iswritable(pipe_writer(io))
|
||||
isopen(io::AbstractPipe) = isopen(pipe_writer(io)) || isopen(pipe_reader(io))
|
||||
close(io::AbstractPipe) = (close(pipe_writer(io)); close(pipe_reader(io)))
|
||||
wait_readnb(io::AbstractPipe, nb::Int) = wait_readnb(pipe_reader(io), nb)
|
||||
wait_readbyte(io::AbstractPipe, byte::UInt8) = wait_readbyte(pipe_reader(io), byte)
|
||||
wait_close(io::AbstractPipe) = (wait_close(pipe_writer(io)); wait_close(pipe_reader(io)))
|
||||
|
||||
"""
|
||||
nb_available(stream)
|
||||
|
||||
Returns the number of bytes available for reading before a read from this stream or buffer will block.
|
||||
"""
|
||||
nb_available(io::AbstractPipe) = nb_available(pipe_reader(io))
|
||||
|
||||
"""
|
||||
eof(stream) -> Bool
|
||||
|
||||
Tests whether an I/O stream is at end-of-file. If the stream is not yet exhausted, this
|
||||
function will block to wait for more data if necessary, and then return `false`. Therefore
|
||||
it is always safe to read one byte after seeing `eof` return `false`. `eof` will return
|
||||
`false` as long as buffered data is still available, even if the remote end of a connection
|
||||
is closed.
|
||||
"""
|
||||
eof(io::AbstractPipe) = eof(pipe_reader(io))
|
||||
reseteof(io::AbstractPipe) = reseteof(pipe_reader(io))
|
||||
|
||||
|
||||
# Exception-safe wrappers (io = open(); try f(io) finally close(io))
|
||||
|
||||
write(filename::AbstractString, args...) = open(io->write(io, args...), filename, "w")
|
||||
|
||||
"""
|
||||
read(filename::AbstractString, args...)
|
||||
|
||||
Open a file and read its contents. `args` is passed to `read`: this is equivalent to
|
||||
`open(io->read(io, args...), filename)`.
|
||||
"""
|
||||
read(filename::AbstractString, args...) = open(io->read(io, args...), filename)
|
||||
read!(filename::AbstractString, a) = open(io->read!(io, a), filename)
|
||||
|
||||
"""
|
||||
readuntil(stream::IO, delim)
|
||||
readuntil(filename::AbstractString, delim)
|
||||
|
||||
Read a string from an I/O stream or a file, up to and including the given delimiter byte.
|
||||
The text is assumed to be encoded in UTF-8.
|
||||
"""
|
||||
readuntil(filename::AbstractString, args...) = open(io->readuntil(io, args...), filename)
|
||||
|
||||
"""
|
||||
readline(stream::IO=STDIN; chomp::Bool=true)
|
||||
readline(filename::AbstractString; chomp::Bool=true)
|
||||
|
||||
Read a single line of text from the given I/O stream or file (defaults to `STDIN`).
|
||||
When reading from a file, the text is assumed to be encoded in UTF-8. Lines in the
|
||||
input end with `'\\n'` or `"\\r\\n"` or the end of an input stream. When `chomp` is
|
||||
true (as it is by default), these trailing newline characters are removed from the
|
||||
line before it is returned. When `chomp` is false, they are returned as part of the
|
||||
line.
|
||||
"""
|
||||
function readline(filename::AbstractString; chomp::Bool=true)
|
||||
open(filename) do f
|
||||
readline(f, chomp=chomp)
|
||||
end
|
||||
end
|
||||
|
||||
function readline(s::IO=STDIN; chomp::Bool=true)
|
||||
line = readuntil(s, 0x0a)
|
||||
i = length(line)
|
||||
if !chomp || i == 0 || line[i] != 0x0a
|
||||
return String(line)
|
||||
elseif i < 2 || line[i-1] != 0x0d
|
||||
return String(resize!(line,i-1))
|
||||
else
|
||||
return String(resize!(line,i-2))
|
||||
end
|
||||
end
|
||||
|
||||
"""
|
||||
readlines(stream::IO=STDIN; chomp::Bool=true)
|
||||
readlines(filename::AbstractString; chomp::Bool=true)
|
||||
|
||||
Read all lines of an I/O stream or a file as a vector of strings. Behavior is
|
||||
equivalent to saving the result of reading `readline` repeatedly with the same
|
||||
arguments and saving the resulting lines as a vector of strings.
|
||||
"""
|
||||
function readlines(filename::AbstractString; chomp::Bool=true)
|
||||
open(filename) do f
|
||||
readlines(f, chomp=chomp)
|
||||
end
|
||||
end
|
||||
readlines(s=STDIN; chomp::Bool=true) = collect(eachline(s, chomp=chomp))
|
||||
|
||||
## byte-order mark, ntoh & hton ##
|
||||
|
||||
let endian_boms = reinterpret(UInt8, UInt32[0x01020304])
|
||||
global ntoh, hton, ltoh, htol
|
||||
if endian_boms == UInt8[1:4;]
|
||||
ntoh(x) = x
|
||||
hton(x) = x
|
||||
ltoh(x) = bswap(x)
|
||||
htol(x) = bswap(x)
|
||||
const global ENDIAN_BOM = 0x01020304
|
||||
elseif endian_boms == UInt8[4:-1:1;]
|
||||
ntoh(x) = bswap(x)
|
||||
hton(x) = bswap(x)
|
||||
ltoh(x) = x
|
||||
htol(x) = x
|
||||
const global ENDIAN_BOM = 0x04030201
|
||||
else
|
||||
error("seriously? what is this machine?")
|
||||
end
|
||||
end
|
||||
|
||||
"""
|
||||
ENDIAN_BOM
|
||||
|
||||
The 32-bit byte-order-mark indicates the native byte order of the host machine.
|
||||
Little-endian machines will contain the value `0x04030201`. Big-endian machines will contain
|
||||
the value `0x01020304`.
|
||||
"""
|
||||
ENDIAN_BOM
|
||||
|
||||
"""
|
||||
ntoh(x)
|
||||
|
||||
Converts the endianness of a value from Network byte order (big-endian) to that used by the Host.
|
||||
"""
|
||||
ntoh(x)
|
||||
|
||||
"""
|
||||
hton(x)
|
||||
|
||||
Converts the endianness of a value from that used by the Host to Network byte order (big-endian).
|
||||
"""
|
||||
hton(x)
|
||||
|
||||
"""
|
||||
ltoh(x)
|
||||
|
||||
Converts the endianness of a value from Little-endian to that used by the Host.
|
||||
"""
|
||||
ltoh(x)
|
||||
|
||||
"""
|
||||
htol(x)
|
||||
|
||||
Converts the endianness of a value from that used by the Host to Little-endian.
|
||||
"""
|
||||
htol(x)
|
||||
|
||||
|
||||
"""
|
||||
isreadonly(stream) -> Bool
|
||||
|
||||
Determine whether a stream is read-only.
|
||||
"""
|
||||
isreadonly(s) = isreadable(s) && !iswritable(s)
|
||||
|
||||
## binary I/O ##
|
||||
|
||||
write(io::IO, x) = throw(MethodError(write, (io, x)))
|
||||
function write(io::IO, xs...)
|
||||
local written::Int = 0
|
||||
for x in xs
|
||||
written += write(io, x)
|
||||
end
|
||||
return written
|
||||
end
|
||||
|
||||
@noinline unsafe_write{T}(s::IO, p::Ref{T}, n::Integer) = unsafe_write(s, unsafe_convert(Ref{T}, p)::Ptr, n) # mark noinline to ensure ref is gc-rooted somewhere (by the caller)
|
||||
unsafe_write(s::IO, p::Ptr, n::Integer) = unsafe_write(s, convert(Ptr{UInt8}, p), convert(UInt, n))
|
||||
write{T}(s::IO, x::Ref{T}) = unsafe_write(s, x, Core.sizeof(T))
|
||||
write(s::IO, x::Int8) = write(s, reinterpret(UInt8, x))
|
||||
function write(s::IO, x::Union{Int16,UInt16,Int32,UInt32,Int64,UInt64,Int128,UInt128,Float16,Float32,Float64})
|
||||
return write(s, Ref(x))
|
||||
end
|
||||
|
||||
write(s::IO, x::Bool) = write(s, UInt8(x))
|
||||
write(to::IO, p::Ptr) = write(to, convert(UInt, p))
|
||||
|
||||
function write(s::IO, A::AbstractArray)
|
||||
nb = 0
|
||||
for a in A
|
||||
nb += write(s, a)
|
||||
end
|
||||
return nb
|
||||
end
|
||||
|
||||
@noinline function write(s::IO, a::Array{UInt8}) # mark noinline to ensure the array is gc-rooted somewhere (by the caller)
|
||||
return unsafe_write(s, pointer(a), sizeof(a))
|
||||
end
|
||||
|
||||
@noinline function write{T}(s::IO, a::Array{T}) # mark noinline to ensure the array is gc-rooted somewhere (by the caller)
|
||||
if isbits(T)
|
||||
return unsafe_write(s, pointer(a), sizeof(a))
|
||||
else
|
||||
nb = 0
|
||||
for b in a
|
||||
nb += write(s, b)
|
||||
end
|
||||
return nb
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function write(s::IO, ch::Char)
|
||||
c = reinterpret(UInt32, ch)
|
||||
if c < 0x80
|
||||
return write(s, c%UInt8)
|
||||
elseif c < 0x800
|
||||
return (write(s, (( c >> 6 ) | 0xC0)%UInt8)) +
|
||||
(write(s, (( c & 0x3F ) | 0x80)%UInt8))
|
||||
elseif c < 0x10000
|
||||
return (write(s, (( c >> 12 ) | 0xE0)%UInt8)) +
|
||||
(write(s, (((c >> 6) & 0x3F ) | 0x80)%UInt8)) +
|
||||
(write(s, (( c & 0x3F ) | 0x80)%UInt8))
|
||||
elseif c < 0x110000
|
||||
return (write(s, (( c >> 18 ) | 0xF0)%UInt8)) +
|
||||
(write(s, (((c >> 12) & 0x3F ) | 0x80)%UInt8)) +
|
||||
(write(s, (((c >> 6) & 0x3F ) | 0x80)%UInt8)) +
|
||||
(write(s, (( c & 0x3F ) | 0x80)%UInt8))
|
||||
else
|
||||
return write(s, '\ufffd')
|
||||
end
|
||||
end
|
||||
|
||||
function write(io::IO, s::Symbol)
|
||||
pname = unsafe_convert(Ptr{UInt8}, s)
|
||||
return unsafe_write(io, pname, Int(ccall(:strlen, Csize_t, (Cstring,), pname)))
|
||||
end
|
||||
|
||||
function write(to::IO, from::IO)
|
||||
while !eof(from)
|
||||
write(to, readavailable(from))
|
||||
end
|
||||
end
|
||||
|
||||
@noinline unsafe_read(s::IO, p::Ref{T}, n::Integer) where {T} = unsafe_read(s, unsafe_convert(Ref{T}, p)::Ptr, n) # mark noinline to ensure ref is gc-rooted somewhere (by the caller)
|
||||
unsafe_read(s::IO, p::Ptr, n::Integer) = unsafe_read(s, convert(Ptr{UInt8}, p), convert(UInt, n))
|
||||
read(s::IO, x::Ref{T}) where {T} = (unsafe_read(s, x, Core.sizeof(T)); x)
|
||||
|
||||
read(s::IO, ::Type{Int8}) = reinterpret(Int8, read(s, UInt8))
|
||||
function read(s::IO, T::Union{Type{Int16},Type{UInt16},Type{Int32},Type{UInt32},Type{Int64},Type{UInt64},Type{Int128},Type{UInt128},Type{Float16},Type{Float32},Type{Float64}})
|
||||
return read(s, Ref{T}(0))[]::T
|
||||
end
|
||||
|
||||
read(s::IO, ::Type{Bool}) = (read(s, UInt8) != 0)
|
||||
read(s::IO, ::Type{Ptr{T}}) where {T} = convert(Ptr{T}, read(s, UInt))
|
||||
|
||||
read(s::IO, t::Type{T}, d1::Int, dims::Int...) where {T} = read(s, t, tuple(d1,dims...))
|
||||
read(s::IO, t::Type{T}, d1::Integer, dims::Integer...) where {T} =
|
||||
read(s, t, convert(Tuple{Vararg{Int}},tuple(d1,dims...)))
|
||||
|
||||
"""
|
||||
read(stream::IO, T, dims)
|
||||
|
||||
Read a series of values of type `T` from `stream`, in canonical binary representation.
|
||||
`dims` is either a tuple or a series of integer arguments specifying the size of the `Array{T}`
|
||||
to return.
|
||||
"""
|
||||
read(s::IO, ::Type{T}, dims::Dims) where {T} = read!(s, Array{T}(dims))
|
||||
|
||||
@noinline function read!(s::IO, a::Array{UInt8}) # mark noinline to ensure the array is gc-rooted somewhere (by the caller)
|
||||
unsafe_read(s, pointer(a), sizeof(a))
|
||||
return a
|
||||
end
|
||||
|
||||
@noinline function read!(s::IO, a::Array{T}) where T # mark noinline to ensure the array is gc-rooted somewhere (by the caller)
|
||||
if isbits(T)
|
||||
unsafe_read(s, pointer(a), sizeof(a))
|
||||
else
|
||||
for i in eachindex(a)
|
||||
a[i] = read(s, T)
|
||||
end
|
||||
end
|
||||
return a
|
||||
end
|
||||
|
||||
function read(s::IO, ::Type{Char})
|
||||
ch = read(s, UInt8)
|
||||
if ch < 0x80
|
||||
return Char(ch)
|
||||
end
|
||||
|
||||
# mimic utf8.next function
|
||||
trailing = Base.utf8_trailing[ch+1]
|
||||
c::UInt32 = 0
|
||||
for j = 1:trailing
|
||||
c += ch
|
||||
c <<= 6
|
||||
ch = read(s, UInt8)
|
||||
end
|
||||
c += ch
|
||||
c -= Base.utf8_offset[trailing+1]
|
||||
return Char(c)
|
||||
end
|
||||
|
||||
# readuntil_string is useful below since it has
|
||||
# an optimized method for s::IOStream
|
||||
readuntil_string(s::IO, delim::UInt8) = String(readuntil(s, delim))
|
||||
|
||||
function readuntil(s::IO, delim::Char)
|
||||
if delim < Char(0x80)
|
||||
return readuntil_string(s, delim % UInt8)
|
||||
end
|
||||
out = IOBuffer()
|
||||
while !eof(s)
|
||||
c = read(s, Char)
|
||||
write(out, c)
|
||||
if c == delim
|
||||
break
|
||||
end
|
||||
end
|
||||
return String(take!(out))
|
||||
end
|
||||
|
||||
function readuntil{T}(s::IO, delim::T)
|
||||
out = T[]
|
||||
while !eof(s)
|
||||
c = read(s, T)
|
||||
push!(out, c)
|
||||
if c == delim
|
||||
break
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
# based on code by Glen Hertz
|
||||
function readuntil(s::IO, t::AbstractString)
|
||||
l = length(t)
|
||||
if l == 0
|
||||
return ""
|
||||
end
|
||||
if l > 40
|
||||
warn("readuntil(IO,AbstractString) will perform poorly with a long string")
|
||||
end
|
||||
out = IOBuffer()
|
||||
m = Vector{Char}(l) # last part of stream to match
|
||||
t = collect(t)
|
||||
i = 0
|
||||
while !eof(s)
|
||||
i += 1
|
||||
c = read(s, Char)
|
||||
write(out, c)
|
||||
if i <= l
|
||||
m[i] = c
|
||||
else
|
||||
# shift to last part of s
|
||||
for j = 2:l
|
||||
m[j-1] = m[j]
|
||||
end
|
||||
m[l] = c
|
||||
end
|
||||
if i >= l && m == t
|
||||
break
|
||||
end
|
||||
end
|
||||
return String(take!(out))
|
||||
end
|
||||
|
||||
"""
|
||||
readchomp(x)
|
||||
|
||||
Read the entirety of `x` as a string and remove a single trailing newline.
|
||||
Equivalent to `chomp!(readstring(x))`.
|
||||
"""
|
||||
readchomp(x) = chomp!(readstring(x))
|
||||
|
||||
# read up to nb bytes into nb, returning # bytes read
|
||||
|
||||
"""
|
||||
readbytes!(stream::IO, b::AbstractVector{UInt8}, nb=length(b))
|
||||
|
||||
Read at most `nb` bytes from `stream` into `b`, returning the number of bytes read.
|
||||
The size of `b` will be increased if needed (i.e. if `nb` is greater than `length(b)`
|
||||
and enough bytes could be read), but it will never be decreased.
|
||||
"""
|
||||
function readbytes!(s::IO, b::AbstractArray{UInt8}, nb=length(b))
|
||||
olb = lb = length(b)
|
||||
nr = 0
|
||||
while nr < nb && !eof(s)
|
||||
a = read(s, UInt8)
|
||||
nr += 1
|
||||
if nr > lb
|
||||
lb = nr * 2
|
||||
resize!(b, lb)
|
||||
end
|
||||
b[nr] = a
|
||||
end
|
||||
if lb > olb
|
||||
resize!(b, nr) # shrink to just contain input data if was resized
|
||||
end
|
||||
return nr
|
||||
end
|
||||
|
||||
"""
|
||||
read(s::IO, nb=typemax(Int))
|
||||
|
||||
Read at most `nb` bytes from `s`, returning a `Vector{UInt8}` of the bytes read.
|
||||
"""
|
||||
function read(s::IO, nb=typemax(Int))
|
||||
# Let readbytes! grow the array progressively by default
|
||||
# instead of taking of risk of over-allocating
|
||||
b = Vector{UInt8}(nb == typemax(Int) ? 1024 : nb)
|
||||
nr = readbytes!(s, b, nb)
|
||||
return resize!(b, nr)
|
||||
end
|
||||
|
||||
"""
|
||||
readstring(stream::IO)
|
||||
readstring(filename::AbstractString)
|
||||
|
||||
Read the entire contents of an I/O stream or a file as a string.
|
||||
The text is assumed to be encoded in UTF-8.
|
||||
"""
|
||||
readstring(s::IO) = String(read(s))
|
||||
readstring(filename::AbstractString) = open(readstring, filename)
|
||||
|
||||
## high-level iterator interfaces ##
|
||||
|
||||
mutable struct EachLine
|
||||
stream::IO
|
||||
ondone::Function
|
||||
chomp::Bool
|
||||
|
||||
EachLine(stream::IO=STDIN; ondone::Function=()->nothing, chomp::Bool=true) =
|
||||
new(stream, ondone, chomp)
|
||||
end
|
||||
|
||||
"""
|
||||
eachline(stream::IO=STDIN; chomp::Bool=true)
|
||||
eachline(filename::AbstractString; chomp::Bool=true)
|
||||
|
||||
Create an iterable `EachLine` object that will yield each line from an I/O stream
|
||||
or a file. Iteration calls `readline` on the stream argument repeatedly with
|
||||
`chomp` passed through, determining whether trailing end-of-line characters are
|
||||
removed. When called with a file name, the file is opened once at the beginning of
|
||||
iteration and closed at the end. If iteration is interrupted, the file will be
|
||||
closed when the `EachLine` object is garbage collected.
|
||||
"""
|
||||
eachline(stream::IO=STDIN; chomp::Bool=true) = EachLine(stream, chomp=chomp)::EachLine
|
||||
|
||||
function eachline(filename::AbstractString; chomp::Bool=true)
|
||||
s = open(filename)
|
||||
EachLine(s, ondone=()->close(s), chomp=chomp)::EachLine
|
||||
end
|
||||
|
||||
start(itr::EachLine) = nothing
|
||||
function done(itr::EachLine, ::Void)
|
||||
eof(itr.stream) || return false
|
||||
itr.ondone()
|
||||
true
|
||||
end
|
||||
next(itr::EachLine, ::Void) = (readline(itr.stream, chomp=itr.chomp), nothing)
|
||||
|
||||
eltype(::Type{EachLine}) = String
|
||||
|
||||
iteratorsize(::Type{EachLine}) = SizeUnknown()
|
||||
|
||||
# IOStream Marking
|
||||
# Note that these functions expect that io.mark exists for
|
||||
# the concrete IO type. This may not be true for IO types
|
||||
# not in base.
|
||||
|
||||
"""
|
||||
mark(s)
|
||||
|
||||
Add a mark at the current position of stream `s`. Returns the marked position.
|
||||
|
||||
See also [`unmark`](@ref), [`reset`](@ref), [`ismarked`](@ref).
|
||||
"""
|
||||
function mark(io::IO)
|
||||
io.mark = position(io)
|
||||
end
|
||||
|
||||
"""
|
||||
unmark(s)
|
||||
|
||||
Remove a mark from stream `s`. Returns `true` if the stream was marked, `false` otherwise.
|
||||
|
||||
See also [`mark`](@ref), [`reset`](@ref), [`ismarked`](@ref).
|
||||
"""
|
||||
function unmark(io::IO)
|
||||
!ismarked(io) && return false
|
||||
io.mark = -1
|
||||
return true
|
||||
end
|
||||
|
||||
"""
|
||||
reset(s)
|
||||
|
||||
Reset a stream `s` to a previously marked position, and remove the mark. Returns the
|
||||
previously marked position. Throws an error if the stream is not marked.
|
||||
|
||||
See also [`mark`](@ref), [`unmark`](@ref), [`ismarked`](@ref).
|
||||
"""
|
||||
function reset(io::T) where T<:IO
|
||||
ismarked(io) || throw(ArgumentError("$(T) not marked"))
|
||||
m = io.mark
|
||||
seek(io, m)
|
||||
io.mark = -1 # must be after seek, or seek may fail
|
||||
return m
|
||||
end
|
||||
|
||||
"""
|
||||
ismarked(s)
|
||||
|
||||
Returns `true` if stream `s` is marked.
|
||||
|
||||
See also [`mark`](@ref), [`unmark`](@ref), [`reset`](@ref).
|
||||
"""
|
||||
ismarked(io::IO) = io.mark >= 0
|
||||
|
||||
# Make sure all IO streams support flush, even if only as a no-op,
|
||||
# to make it easier to write generic I/O code.
|
||||
|
||||
"""
|
||||
flush(stream)
|
||||
|
||||
Commit all currently buffered writes to the given stream.
|
||||
"""
|
||||
flush(io::IO) = nothing
|
||||
Reference in New Issue
Block a user