mollusk 0e4acfb8f2 fix incorrect folder name for julia-0.6.x
Former-commit-id: ef2c7401e0876f22d2f7762d182cfbcd5a7d9c70
2018-06-11 03:28:36 -07:00

647 lines
19 KiB
Julia

# 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