https://github.com/JuliaLang/julia
Tip revision: a865ca2777a883d4d67a77e71e5aa3ed59fe8f6d authored by Jeff Bezanson on 15 August 2014, 03:12:32 UTC
more scheme portability fixes
more scheme portability fixes
Tip revision: a865ca2
io.jl
## core stream types ##
# the first argument to any IO MUST be a POINTER (to a JL_STREAM) or using show on it will cause memory corruption
# Generic IO functions
## byte-order mark, ntoh & hton ##
const ENDIAN_BOM = reinterpret(Uint32,uint8([1:4]))[1]
if ENDIAN_BOM == 0x01020304
ntoh(x) = x
hton(x) = x
ltoh(x) = bswap(x)
htol(x) = bswap(x)
elseif ENDIAN_BOM == 0x04030201
ntoh(x) = bswap(x)
hton(x) = bswap(x)
ltoh(x) = x
htol(x) = x
else
error("seriously? what is this machine?")
end
isreadonly(s) = isreadable(s) && !iswritable(s)
## binary I/O ##
# all subtypes should implement this
write(s::IO, x::Uint8) = error(typeof(s)," does not support byte I/O")
write(io::IO, x) = throw(MethodError(write, (io, x)))
write(io::IO, xs...) = for x in xs write(io, x) end
if ENDIAN_BOM == 0x01020304
function write(s::IO, x::Integer)
sz = sizeof(x)
for n = sz:-1:1
write(s, uint8((x>>>((n-1)<<3))))
end
sz
end
else
function write(s::IO, x::Integer)
sz = sizeof(x)
for n = 1:sz
write(s, uint8((x>>>((n-1)<<3))))
end
sz
end
end
write(s::IO, x::Bool) = write(s, uint8(x))
write(s::IO, x::Float16) = write(s, reinterpret(Int16,x))
write(s::IO, x::Float32) = write(s, reinterpret(Int32,x))
write(s::IO, x::Float64) = write(s, reinterpret(Int64,x))
function write(s::IO, a::AbstractArray)
nb = 0
for i = 1:length(a)
nb += write(s, a[i])
end
nb
end
function write(s::IO, c::Char)
if c < 0x80
write(s, uint8(c))
return 1
elseif c < 0x800
write(s, uint8(( c >> 6 ) | 0xC0))
write(s, uint8(( c & 0x3F ) | 0x80))
return 2
elseif c < 0x10000
write(s, uint8(( c >> 12 ) | 0xE0))
write(s, uint8(((c >> 6) & 0x3F ) | 0x80))
write(s, uint8(( c & 0x3F ) | 0x80))
return 3
elseif c < 0x110000
write(s, uint8(( c >> 18 ) | 0xF0))
write(s, uint8(((c >> 12) & 0x3F ) | 0x80))
write(s, uint8(((c >> 6) & 0x3F ) | 0x80))
write(s, uint8(( c & 0x3F ) | 0x80))
return 4
else
return write(s, '\ufffd')
end
end
function write(s::IO, p::Ptr, n::Integer)
for i=1:n
write(s, unsafe_load(p, i))
end
n
end
function write(io::IO, s::Symbol)
pname = convert(Ptr{Uint8}, s)
write(io, pname, int(ccall(:strlen, Csize_t, (Ptr{Uint8},), pname)))
end
# all subtypes should implement this
read(s::IO, x::Type{Uint8}) = error(typeof(s)," does not support byte I/O")
function read{T <: Integer}(s::IO, ::Type{T})
x = zero(T)
for n = 1:sizeof(x)
x |= (convert(T,read(s,Uint8))<<((n-1)<<3))
end
return x
end
read(s::IO, ::Type{Bool}) = (read(s,Uint8)!=0)
read(s::IO, ::Type{Float16}) = box(Float16,unbox(Int16,read(s,Int16)))
read(s::IO, ::Type{Float32}) = box(Float32,unbox(Int32,read(s,Int32)))
read(s::IO, ::Type{Float64}) = box(Float64,unbox(Int64,read(s,Int64)))
read{T}(s::IO, t::Type{T}, d1::Int, dims::Int...) =
read(s, t, tuple(d1,dims...))
read{T}(s::IO, t::Type{T}, d1::Integer, dims::Integer...) =
read(s, t, map(int,tuple(d1,dims...)))
read{T}(s::IO, ::Type{T}, dims::Dims) = read!(s, Array(T, dims))
function read!{T}(s::IO, a::Array{T})
for i = 1:length(a)
a[i] = read(s, T)
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]
char(c)
end
function readuntil(s::IO, delim::Char)
if delim < 0x80
data = readuntil(s, uint8(delim))
enc = byte_string_classify(data)
return (enc==1) ? ASCIIString(data) : UTF8String(data)
end
out = IOBuffer()
while !eof(s)
c = read(s, Char)
write(out, c)
if c == delim
break
end
end
takebuf_string(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
out
end
# based on code by Glen Hertz
function readuntil(s::IO, t::String)
l = length(t)
if l == 0
return ""
end
if l > 40
warn("readuntil(IO,String) will perform poorly with a long string")
end
out = IOBuffer()
m = Array(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 takebuf_string(out)
end
readline(s::IO) = readuntil(s, '\n')
readchomp(x) = chomp!(readall(x))
# read up to nb bytes into nb, returning # bytes read
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 up to nb bytes from s, returning a Vector{Uint8} of bytes read.
function readbytes(s::IO, nb=typemax(Int))
b = Array(Uint8, nb == typemax(Int) ? 1024 : nb)
nr = readbytes!(s, b, nb)
resize!(b, nr)
end
function readall(s::IO)
b = readbytes(s)
return is_valid_ascii(b) ? ASCIIString(b) : UTF8String(b)
end
readall(filename::String) = open(readall, filename)
## high-level iterator interfaces ##
type EachLine
stream::IO
ondone::Function
EachLine(stream) = EachLine(stream, ()->nothing)
EachLine(stream, ondone) = new(stream, ondone)
end
eachline(stream::IO) = EachLine(stream)
start(itr::EachLine) = nothing
function done(itr::EachLine, nada)
if !eof(itr.stream)
return false
end
itr.ondone()
true
end
next(itr::EachLine, nada) = (readline(itr.stream), nothing)
eltype(itr::EachLine) = ByteString
readlines(s=STDIN) = collect(eachline(s))
# 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.
function mark(io::IO)
io.mark = position(io)
end
function unmark(io::IO)
!ismarked(io) && return false
io.mark = -1
return true
end
function reset(io::IO)
!ismarked(io) && error(io, " not marked")
m = io.mark
seek(io, m)
io.mark = -1 # must be after seek, or seek may fail
return m
end
ismarked(io::IO) = io.mark >= 0