From beb436cd511a86e0b34740dd7d96376fa9af1a95 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 22 Jan 2016 15:27:48 -0500 Subject: [PATCH] rename write(io, ptr::Ptr, nb) to unsafe_write(io, p::Ptr{Uint8}, nb::Uint) this better clarifies the behavior of this method (the fallback for write(io, xs...) usually calls write on each element of xs) and provides a fallback implementation for every subtype IO this also allows the deletion of a substantial amount of duplicated and special-case code that is now made redundant once Ref can be stack-allocated, this approach should gain an extra speed bump --- base/LineEdit.jl | 2 +- base/Terminals.jl | 52 ++++++----------------- base/base64.jl | 17 ++++---- base/deprecated.jl | 3 ++ base/exports.jl | 2 + base/filesystem.jl | 12 +----- base/grisu.jl | 22 +++++----- base/io.jl | 100 ++++++++++++++++++++++++++------------------- base/iobuffer.jl | 68 ++++++++---------------------- base/iostream.jl | 18 ++------ base/printf.jl | 22 +++++----- base/serialize.jl | 2 +- base/stream.jl | 45 ++++++-------------- base/sysimg.jl | 10 ++--- 14 files changed, 149 insertions(+), 226 deletions(-) diff --git a/base/LineEdit.jl b/base/LineEdit.jl index 27cb6a04978b53..8bfa6625f244ca 100644 --- a/base/LineEdit.jl +++ b/base/LineEdit.jl @@ -1125,7 +1125,7 @@ end function refresh_multi_line(termbuf::TerminalBuffer, s::SearchState) buf = IOBuffer() - write(buf, pointer(s.query_buffer.data), s.query_buffer.ptr-1) + unsafe_write(buf, pointer(s.query_buffer.data), s.query_buffer.ptr-1) write(buf, "': ") offset = buf.ptr ptr = s.response_buffer.ptr diff --git a/base/Terminals.jl b/base/Terminals.jl index dac425d0142bb4..433a0933304b0a 100644 --- a/base/Terminals.jl +++ b/base/Terminals.jl @@ -22,34 +22,30 @@ export getY, hascolor, pos, - raw!, - writepos + raw! import Base: + check_open, # stream.jl + displaysize, flush, + pipe_reader, + pipe_writer, read, readuntil, - displaysize, - start_reading, - stop_reading, - write, - writemime, - reseteof, - eof, - check_open # stream.jl + writemime ## TextTerminal ## -abstract TextTerminal <: Base.IO +abstract TextTerminal <: Base.AbstractPipe # INTERFACE +pipe_reader(::TextTerminal) = error("Unimplemented") +pipe_writer(::TextTerminal) = error("Unimplemented") displaysize(::TextTerminal) = error("Unimplemented") -writepos(t::TextTerminal, x, y, s::Array{UInt8,1}) = error("Unimplemented") cmove(t::TextTerminal, x, y) = error("Unimplemented") getX(t::TextTerminal) = error("Unimplemented") getY(t::TextTerminal) = error("Unimplemented") pos(t::TextTerminal) = (getX(t), getY(t)) -reseteof(t::TextTerminal) = nothing # Relative moves (Absolute position fallbacks) cmove_up(t::TextTerminal, n) = cmove(getX(t), max(1, getY(t)-n)) @@ -76,18 +72,6 @@ cmove_col(t::TextTerminal, c) = cmove(c, getY(t)) hascolor(::TextTerminal) = false # Utility Functions -function writepos{T}(t::TextTerminal, x, y, b::Array{T}) - if isbits(T) - writepos(t, x, y, reinterpret(UInt8, b)) - else - cmove(t, x, y) - invoke(write, Tuple{IO, Array}, s, a) - end -end -function writepos(t::TextTerminal, x, y, args...) - cmove(t, x, y) - write(t, args...) -end width(t::TextTerminal) = displaysize(t)[2] height(t::TextTerminal) = displaysize(t)[1] @@ -108,6 +92,9 @@ disable_bracketed_paste(t::TextTerminal) = nothing abstract UnixTerminal <: TextTerminal +pipe_reader(t::UnixTerminal) = t.in_stream +pipe_writer(t::UnixTerminal) = t.out_stream + type TerminalBuffer <: UnixTerminal out_stream::Base.IO end @@ -119,8 +106,6 @@ type TTYTerminal <: UnixTerminal err_stream::Base.TTY end -reseteof(t::TTYTerminal) = reseteof(t.in_stream) - const CSI = "\x1b[" cmove_up(t::UnixTerminal, n) = write(t.out_stream, "$(CSI)$(n)A") @@ -166,19 +151,6 @@ clear(t::UnixTerminal) = write(t.out_stream, "\x1b[H\x1b[2J") clear_line(t::UnixTerminal) = write(t.out_stream, "\x1b[0G\x1b[0K") #beep(t::UnixTerminal) = write(t.err_stream,"\x7") -write{T,N}(t::UnixTerminal, a::Array{T,N}) = write(t.out_stream, a) -write(t::UnixTerminal, p::Ptr{UInt8}) = write(t.out_stream, p) -write(t::UnixTerminal, p::Ptr{UInt8}, x::Integer) = write(t.out_stream, p, x) -write(t::UnixTerminal, x::UInt8) = write(t.out_stream, x) -read{T,N}(t::UnixTerminal, x::Array{T,N}) = read(t.in_stream, x) -readuntil(t::UnixTerminal, s::AbstractString) = readuntil(t.in_stream, s) -readuntil(t::UnixTerminal, c::Char) = readuntil(t.in_stream, c) -readuntil(t::UnixTerminal, s) = readuntil(t.in_stream, s) -read(t::UnixTerminal, ::Type{UInt8}) = read(t.in_stream, UInt8) -start_reading(t::UnixTerminal) = start_reading(t.in_stream) -stop_reading(t::UnixTerminal) = stop_reading(t.in_stream) -eof(t::UnixTerminal) = eof(t.in_stream) - @unix_only function hascolor(t::TTYTerminal) startswith(t.term_type, "xterm") && return true try diff --git a/base/base64.jl b/base/base64.jl index 90f0cde3514be6..5b9856dfed1d5b 100644 --- a/base/base64.jl +++ b/base/base64.jl @@ -85,16 +85,15 @@ end ############################################################################# -function write(b::Base64EncodePipe, x::AbstractVector{UInt8}) - n = length(x) +function unsafe_write(b::Base64EncodePipe, x::Ptr{UInt8}, n::UInt) s = 1 # starting index # finish any cached data to write: if b.nb == 1 if n >= 2 - write(b.io, b64(b.b0, x[1], x[2])...) + write(b.io, b64(b.b0, unsafe_load(x, 1), unsafe_load(x, 2))...) s = 3 elseif n == 1 - b.b1 = x[1] + b.b1 = unsafe_load(x, 1) b.nb = 2 return else @@ -102,7 +101,7 @@ function write(b::Base64EncodePipe, x::AbstractVector{UInt8}) end elseif b.nb == 2 if n >= 1 - write(b.io, b64(b.b0, b.b1, x[1])...) + write(b.io, b64(b.b0, b.b1, unsafe_load(x, 1))...) s = 2 else return @@ -110,16 +109,16 @@ function write(b::Base64EncodePipe, x::AbstractVector{UInt8}) end # write all groups of three bytes: while s + 2 <= n - write(b.io, b64(x[s], x[s+1], x[s+2])...) + write(b.io, b64(unsafe_load(x, s), unsafe_load(x, s + 1), unsafe_load(x, s + 2))...) s += 3 end # cache any leftover bytes: if s + 1 == n - b.b0 = x[s] - b.b1 = x[s+1] + b.b0 = unsafe_load(x, s) + b.b1 = unsafe_load(x, s + 1) b.nb = 2 elseif s == n - b.b0 = x[s] + b.b0 = unsafe_load(x, s) b.nb = 1 else b.nb = 0 diff --git a/base/deprecated.jl b/base/deprecated.jl index 13cab4b5a14c51..acdff42c9b1480 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -967,3 +967,6 @@ end #https://github.com/JuliaLang/julia/issues/14608 @deprecate readall readstring @deprecate readbytes read + +# 14766 +@deprecate write(io::IO, p::Ptr, nb::Integer) unsafe_write(io, p, nb) diff --git a/base/exports.jl b/base/exports.jl index 0ac0b168b6583e..7bd57ebd007990 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1332,7 +1332,9 @@ export unsafe_copy!, unsafe_load, unsafe_pointer_to_objref, + #unsafe_read, unsafe_store!, + unsafe_write, # nullable types isnull, diff --git a/base/filesystem.jl b/base/filesystem.jl index 29a534b6d51ddb..2f8ddf111e9f79 100644 --- a/base/filesystem.jl +++ b/base/filesystem.jl @@ -105,7 +105,7 @@ function sendfile(dst::File, src::File, src_offset::Int64, bytes::Int) nothing end -function write(f::File, buf::Ptr{UInt8}, len::Integer, offset::Integer=-1) +function unsafe_write(f::File, buf::Ptr{UInt8}, len::UInt, offset::Int64=Int64(-1)) check_open(f) err = ccall(:jl_fs_write, Int32, (Int32, Ptr{UInt8}, Csize_t, Int64), f.handle, buf, len, offset) @@ -113,15 +113,7 @@ function write(f::File, buf::Ptr{UInt8}, len::Integer, offset::Integer=-1) return len end -write(f::File, c::UInt8) = write(f, UInt8[c]) - -function write{T}(f::File, a::Array{T}) - if isbits(T) - write(f, pointer(a), sizeof(a)) - else - invoke(write, Tuple{IO, Array}, f, a) - end -end +write(f::File, c::UInt8) = write(f, Ref{UInt8}(c)) function truncate(f::File, n::Integer) check_open(f) diff --git a/base/grisu.jl b/base/grisu.jl index ffc984a206b9c3..055baa59832171 100644 --- a/base/grisu.jl +++ b/base/grisu.jl @@ -79,10 +79,10 @@ function _show(io::IO, x::AbstractFloat, mode, n::Int, typed, nanstr, infstr) exp_form = exp_form || (pt >= len && abs(mod(x + 0.05, 10^(pt - len)) - 0.05) > 0.05) # see issue #6608 if exp_form # .00001 to 100000. # => #.#######e### - write(io, pdigits, 1) + unsafe_write(io, pdigits, 1) write(io, '.') if len > 1 - write(io, pdigits+1, len-1) + unsafe_write(io, pdigits+1, len-1) else write(io, '0') end @@ -97,19 +97,19 @@ function _show(io::IO, x::AbstractFloat, mode, n::Int, typed, nanstr, infstr) write(io, '0') pt += 1 end - write(io, pdigits, len) + unsafe_write(io, pdigits, len) elseif pt >= len # => ########00.0 - write(io, pdigits, len) + unsafe_write(io, pdigits, len) while pt > len write(io, '0') len += 1 end write(io, ".0") else # => ####.#### - write(io, pdigits, pt) + unsafe_write(io, pdigits, pt) write(io, '.') - write(io, pdigits+pt, len-pt) + unsafe_write(io, pdigits+pt, len-pt) end typed && isa(x,Float32) && write(io, "f0") typed && isa(x,Float16) && write(io, ")") @@ -144,7 +144,7 @@ function _print_shortest(io::IO, x::AbstractFloat, dot::Bool, mode, n::Int) k = -9<=e<=9 ? 1 : 2 if -pt > k+1 || e+dot > k+1 # => ########e### - write(io, pdigits+0, len) + unsafe_write(io, pdigits+0, len) write(io, 'e') write(io, dec(e)) return @@ -155,10 +155,10 @@ function _print_shortest(io::IO, x::AbstractFloat, dot::Bool, mode, n::Int) write(io, '0') pt += 1 end - write(io, pdigits+0, len) + unsafe_write(io, pdigits+0, len) elseif e >= dot # => ########000. - write(io, pdigits+0, len) + unsafe_write(io, pdigits+0, len) while e > 0 write(io, '0') e -= 1 @@ -167,9 +167,9 @@ function _print_shortest(io::IO, x::AbstractFloat, dot::Bool, mode, n::Int) write(io, '.') end else # => ####.#### - write(io, pdigits+0, pt) + unsafe_write(io, pdigits+0, pt) write(io, '.') - write(io, pdigits+pt, len-pt) + unsafe_write(io, pdigits+pt, len-pt) end nothing end diff --git a/base/io.jl b/base/io.jl index 53123506d0d2b5..4d95906c954220 100644 --- a/base/io.jl +++ b/base/io.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -# Generic IO stubs +# Generic IO stubs -- all subtypes should implement these (if meaningful) lock(::IO) = nothing unlock(::IO) = nothing @@ -23,20 +23,24 @@ function iswritable end function copy end function eof end -# all subtypes should implement this 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") +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 + # Generic wrappers around other IO objects abstract AbstractPipe <: IO function pipe_reader end function pipe_writer end write(io::AbstractPipe, byte::UInt8) = write(pipe_writer(io), byte) -write(io::AbstractPipe, bytes::Vector{UInt8}) = write(pipe_writer(io), bytes) -write{T<:AbstractPipe}(io::T, args...) = write(pipe_writer(io), args...) -write{S<:AbstractPipe}(io::S, a::Array) = write(pipe_writer(io), a) -buffer_or_write(io::AbstractPipe, p::Ptr, n::Integer) = buffer_or_write(pipe_writer(io), p, n) +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)) @@ -100,34 +104,18 @@ function write(io::IO, xs...) for x in xs written += write(io, x) end - written + return written end -if ENDIAN_BOM == 0x01020304 - function write(s::IO, x::Union{Int8,Int16,UInt16,Int32,UInt32,Int64,UInt64,Int128,UInt128}) - sz = sizeof(x) - local written::Int = 0 - for n = sz:-1:1 - written += write(s, (x>>>((n-1)<<3))%UInt8) - end - return written - end -else - function write(s::IO, x::Union{Int8,Int16,UInt16,Int32,UInt32,Int64,UInt64,Int128,UInt128}) - sz = sizeof(x) - local written::Int = 0 - for n = 1:sz - written += write(s, (x>>>((n-1)<<3))%UInt8) - end - return written - end +unsafe_write{T}(s::IO, p::Ref{T}, n::Integer) = unsafe_write(s, unsafe_convert(Ref{T}, p)::Ptr, n) +unsafe_write(s::IO, p::Ptr, n::Integer) = unsafe_write(s, convert(Ptr{UInt8}, p), convert(UInt, n)) +write(s::IO, x::Ref) = unsafe_write(s, x, sizeof(eltype(x))) + +function write(s::IO, x::Union{Int8,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(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)) - write(to::IO, p::Ptr) = write(to, convert(UInt, p)) function write(s::IO, a::AbstractArray) @@ -138,6 +126,19 @@ function write(s::IO, a::AbstractArray) return nb end +function write{T}(s::IO, a::Array{T}) + if isbits(T) + return unsafe_write(s, pointer(a), sizeof(a)) + end + + nb = 0 + for x in a + nb += write(s, x) + end + return nb +end + + function write(s::IO, ch::Char) c = reinterpret(UInt32, ch) if c < 0x80 @@ -159,17 +160,9 @@ function write(s::IO, ch::Char) end end -function write(s::IO, p::Ptr, n::Integer) - local written::Int = 0 - for i=1:n - written += write(s, unsafe_load(p, i)) - end - return written -end - function write(io::IO, s::Symbol) pname = unsafe_convert(Ptr{UInt8}, s) - return write(io, pname, Int(ccall(:strlen, Csize_t, (Cstring,), pname))) + return unsafe_write(io, pname, Int(ccall(:strlen, Csize_t, (Cstring,), pname))) end function write(to::IO, from::IO) @@ -237,7 +230,7 @@ function read(s::IO, ::Type{Char}) end c += ch c -= Base.utf8_offset[trailing+1] - Char(c) + return Char(c) end function readuntil(s::IO, delim::Char) @@ -254,7 +247,7 @@ function readuntil(s::IO, delim::Char) break end end - takebuf_string(out) + return takebuf_string(out) end function readuntil{T}(s::IO, delim::T) @@ -266,7 +259,7 @@ function readuntil{T}(s::IO, delim::T) break end end - out + return out end # based on code by Glen Hertz @@ -365,3 +358,28 @@ next(itr::EachLine, nada) = (readline(itr.stream), nothing) eltype(::Type{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{T<:IO}(io::T) + 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(io::IO) = io.mark >= 0 diff --git a/base/iobuffer.jl b/base/iobuffer.jl index f49eb9291bd171..cd1d3307348147 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -171,7 +171,8 @@ function compact(io::AbstractIOBuffer) return io end -@inline function ensureroom(io::AbstractIOBuffer, nshort::Int) +@inline ensureroom(io::AbstractIOBuffer, nshort::Int) = ensureroom(io, UInt(nshort)) +@inline function ensureroom(io::AbstractIOBuffer, nshort::UInt) io.writable || throw(ArgumentError("ensureroom failed, IOBuffer is not writeable")) if !io.seekable nshort >= 0 || throw(ArgumentError("ensureroom failed, requested number of bytes must be ≥ 0, got $nshort")) @@ -236,7 +237,7 @@ function takebuf_array(io::AbstractIOBuffer) io.ptr = 1 io.size = 0 end - data + return data end function takebuf_array(io::IOBuffer) ismarked(io) && unmark(io) @@ -258,7 +259,7 @@ function takebuf_array(io::IOBuffer) io.ptr = 1 io.size = 0 end - data + return data end function takebuf_string(io::AbstractIOBuffer) b = takebuf_array(io) @@ -272,21 +273,21 @@ function write(to::AbstractIOBuffer, from::AbstractIOBuffer) end written::Int = write_sub(to, from.data, from.ptr, nb_available(from)) from.ptr += written - written + return written end -write(to::AbstractIOBuffer, p::Ptr, nb::Integer) = write(to, p, Int(nb)) -function write(to::AbstractIOBuffer, p::Ptr, nb::Int) +function unsafe_write(to::AbstractIOBuffer, p::Ptr{UInt8}, nb::UInt) ensureroom(to, nb) ptr = (to.append ? to.size+1 : to.ptr) written = min(nb, length(to.data) - ptr + 1) - p_u8 = convert(Ptr{UInt8}, p) for i = 0:written - 1 - @inbounds to.data[ptr + i] = unsafe_load(p_u8 + i) + @inbounds to.data[ptr + i] = unsafe_load(p + i) end to.size = max(to.size, ptr - 1 + written) - if !to.append to.ptr += written end - written + if !to.append + to.ptr += written + end + return written end function write_sub{T}(to::AbstractIOBuffer, a::AbstractArray{T}, offs, nel) @@ -295,17 +296,11 @@ function write_sub{T}(to::AbstractIOBuffer, a::AbstractArray{T}, offs, nel) end local written::Int if isbits(T) && isa(a,Array) - nb = nel * sizeof(T) - ensureroom(to, Int(nb)) - ptr = (to.append ? to.size+1 : to.ptr) - written = min(nb, length(to.data) - ptr + 1) - unsafe_copy!(pointer(to.data, ptr), - convert(Ptr{UInt8}, pointer(a, offs)), written) - to.size = max(to.size, ptr - 1 + written) - if !to.append to.ptr += written end + nb = UInt(nel * sizeof(T)) + written = unsafe_write(to, pointer(a, offs), nb) else written = 0 - ensureroom(to, sizeof(a)) + ensureroom(to, UInt(sizeof(a))) for i = offs:offs+nel-1 written += write(to, a[i]) end @@ -313,10 +308,8 @@ function write_sub{T}(to::AbstractIOBuffer, a::AbstractArray{T}, offs, nel) return written end -write(to::AbstractIOBuffer, a::Array) = write_sub(to, a, 1, length(a)) - @inline function write(to::AbstractIOBuffer, a::UInt8) - ensureroom(to, 1) + ensureroom(to, UInt(1)) ptr = (to.append ? to.size+1 : to.ptr) if ptr > to.maxsize return 0 @@ -324,7 +317,9 @@ write(to::AbstractIOBuffer, a::Array) = write_sub(to, a, 1, length(a)) to.data[ptr] = a end to.size = max(to.size, ptr) - if !to.append to.ptr += 1 end + if !to.append + to.ptr += 1 + end return sizeof(UInt8) end @@ -381,30 +376,3 @@ function readuntil(io::AbstractIOBuffer, delim::UInt8) end A end - -# 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. - -# Note 2: these functions truly belong in io.jl, but serious massive performance issues with type-inference if they aren't available earlier - -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{T<:IO}(io::T) - 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(io::IO) = io.mark >= 0 diff --git a/base/iostream.jl b/base/iostream.jl index 0168db9fc5d014..411ae8cd604241 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -121,19 +121,7 @@ end write(s::IOStream, b::UInt8) = Int(ccall(:ios_putc, Cint, (Cint, Ptr{Void}), b, s.ios)) -function write{T}(s::IOStream, a::Array{T}) - if isbits(T) - if !iswritable(s) - throw(ArgumentError("write failed, IOStream is not writeable")) - end - Int(ccall(:ios_write, Csize_t, (Ptr{Void}, Ptr{Void}, Csize_t), - s.ios, a, length(a)*sizeof(T))) - else - invoke(write, Tuple{IO, Array}, s, a) - end -end - -function write(s::IOStream, p::Ptr, nb::Integer) +function unsafe_write(s::IOStream, p::Ptr{UInt8}, nb::UInt) if !iswritable(s) throw(ArgumentError("write failed, IOStream is not writeable")) end @@ -146,10 +134,10 @@ function write{T,N,A<:Array}(s::IOStream, a::SubArray{T,N,A}) end colsz = size(a,1)*sizeof(T) if N<=1 - return write(s, pointer(a, 1), colsz) + return unsafe_write(s, pointer(a, 1), colsz) else for idxs in CartesianRange((1, size(a)[2:end]...)) - write(s, pointer(a, idxs.I), colsz) + unsafe_write(s, pointer(a, idxs.I), colsz) end return colsz*trailingsize(a,2) end diff --git a/base/printf.jl b/base/printf.jl index c1d48cffb54a9f..64cc298c588927 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -191,11 +191,11 @@ function print_fixed(out, precision, pt, ndigits, trailingzeros=true) write(out, '0') pt += 1 end - write(out, pdigits, ndigits) + unsafe_write(out, pdigits, ndigits) precision -= ndigits elseif ndigits <= pt # dddd000.000000 - write(out, pdigits, ndigits) + unsafe_write(out, pdigits, ndigits) while ndigits < pt write(out, '0') ndigits += 1 @@ -206,9 +206,9 @@ function print_fixed(out, precision, pt, ndigits, trailingzeros=true) else # 0 < pt < ndigits # dd.dd0000 ndigits -= pt - write(out, pdigits, pt) + unsafe_write(out, pdigits, pt) write(out, '.') - write(out, pdigits+pt, ndigits) + unsafe_write(out, pdigits+pt, ndigits) precision -= ndigits end if trailingzeros @@ -314,7 +314,7 @@ function gen_d(flags::ASCIIString, width::Int, precision::Int, c::Char) push!(blk.args, pad(width-1, zeros, '0')) end # print integer - push!(blk.args, :(write(out, pointer(DIGITS), pt))) + push!(blk.args, :(unsafe_write(out, pointer(DIGITS), pt))) # print padding if padding !== nothing && '-' in flags push!(blk.args, pad(width-precision, padding, ' ')) @@ -373,7 +373,7 @@ function gen_f(flags::ASCIIString, width::Int, precision::Int, c::Char) if precision > 0 push!(blk.args, :(print_fixed(out,$precision,pt,len))) else - push!(blk.args, :(write(out, pointer(DIGITS), len))) + push!(blk.args, :(unsafe_write(out, pointer(DIGITS), len))) push!(blk.args, :(while pt >= (len+=1) write(out,'0') end)) '#' in flags && push!(blk.args, :(write(out, '.'))) end @@ -473,12 +473,12 @@ function gen_e(flags::ASCIIString, width::Int, precision::Int, c::Char, inside_g end; if endidx > 1 write(out, '.') - write(out, pointer(DIGITS)+1, endidx-1) + unsafe_write(out, pointer(DIGITS)+1, endidx-1) end )) else push!(blk.args, :(write(out, '.'))) - push!(blk.args, :(write(out, pointer(DIGITS)+1, $(ndigits-1)))) + push!(blk.args, :(unsafe_write(out, pointer(DIGITS)+1, $(ndigits-1)))) if ndigits < precision+1 n = precision+1-ndigits push!(blk.args, pad(n, n, '0')) @@ -577,7 +577,7 @@ function gen_a(flags::ASCIIString, width::Int, precision::Int, c::Char) push!(blk.args, :(write(out, DIGITS[1]))) if precision > 0 push!(blk.args, :(write(out, '.'))) - push!(blk.args, :(write(out, pointer(DIGITS)+1, $(ndigits-1)))) + push!(blk.args, :(unsafe_write(out, pointer(DIGITS)+1, $(ndigits-1)))) if ndigits < precision+1 n = precision+1-ndigits push!(blk.args, pad(n, n, '0')) @@ -590,7 +590,7 @@ function gen_a(flags::ASCIIString, width::Int, precision::Int, c::Char) else push!(vpblk.args, :(write(out, '.'))) end - push!(vpblk.args, :(write(out, pointer(DIGITS)+1, len-1))) + push!(vpblk.args, :(unsafe_write(out, pointer(DIGITS)+1, len-1))) push!(blk.args, ifvpblk) end for ch in expmark @@ -1103,7 +1103,7 @@ function bigfloat_printf(out, d, flags::ASCIIString, width::Int, precision::Int, bufsiz = length(DIGITS) - 1 lng = ccall((:mpfr_snprintf,:libmpfr), Int32, (Ptr{UInt8}, Culong, Ptr{UInt8}, Ptr{BigFloat}...), DIGITS, bufsiz, printf_fmt, &d) lng > 0 || error("invalid printf formatting for BigFloat") - write(out, pointer(DIGITS), min(lng,bufsiz)) + unsafe_write(out, pointer(DIGITS), min(lng,bufsiz)) return (false, ()) end diff --git a/base/serialize.jl b/base/serialize.jl index b2459c0bcc9aea..f608b724b80ad5 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -143,7 +143,7 @@ function serialize(s::SerializationState, x::Symbol) writetag(s.io, LONGSYMBOL_TAG) write(s.io, Int32(ln)) end - write(s.io, pname, ln) + unsafe_write(s.io, pname, ln) end function serialize_array_data(s::IO, a) diff --git a/base/stream.jl b/base/stream.jl index d49da0e39c936b..ce8838bb758c64 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -960,8 +960,8 @@ function readuntil(this::LibuvStream, c::UInt8) readuntil(buf, c) end -uv_write(s::LibuvStream, p::Vector{UInt8}) = uv_write(s, pointer(p), UInt(length(p))) -function uv_write(s::LibuvStream, p::Ptr, n::UInt) +uv_write(s::LibuvStream, p::Vector{UInt8}) = uv_write(s, pointer(p), UInt(sizeof(p))) +function uv_write(s::LibuvStream, p::Ptr{UInt8}, n::UInt) check_open(s) uvw = Libc.malloc(_sizeof_uv_write) uv_req_set_data(uvw,C_NULL) @@ -984,7 +984,7 @@ end # - smaller writes are buffered, final uv write on flush or when buffer full # - large isbits arrays are unbuffered and written directly -function buffer_or_write(s::LibuvStream, p::Ptr, n::Integer) +function unsafe_write(s::LibuvStream, p::Ptr{UInt8}, n::UInt) if isnull(s.sendbuf) return uv_write(s, p, UInt(n)) end @@ -992,13 +992,13 @@ function buffer_or_write(s::LibuvStream, p::Ptr, n::Integer) buf = get(s.sendbuf) totb = nb_available(buf) + n if totb < buf.maxsize - nb = write(buf, p, n) + nb = unsafe_write(buf, p, n) else flush(s) if n > buf.maxsize nb = uv_write(s, p, n) else - nb = write(buf, p, n) + nb = unsafe_write(buf, p, n) end end return nb @@ -1013,26 +1013,14 @@ function flush(s::LibuvStream) arr = takebuf_array(buf) # Array of UInt8s uv_write(s, arr) end - s + return s end buffer_writes(s::LibuvStream, bufsize) = (s.sendbuf=PipeBuffer(bufsize); s) ## low-level calls to libuv ## -write(s::LibuvStream, b::UInt8) = write(s, [b]) -write(s::LibuvStream, c::Char) = write(s, string(c)) -function write{T}(s::LibuvStream, a::Array{T}) - if isbits(T) - n = UInt(length(a) * sizeof(T)) - return buffer_or_write(s, pointer(a), n) - else - check_open(s) - invoke(write, Tuple{IO, typeof(a)}, s, a) - end -end - -write(s::LibuvStream, p::Ptr, n::Integer) = buffer_or_write(s, p, n) +write(s::LibuvStream, b::UInt8) = write(s, Ref{UInt8}(b)) function uv_writecb_task(req::Ptr{Void}, status::Cint) d = uv_req_data(req) @@ -1224,25 +1212,18 @@ function wait_readbyte(s::BufferStream, c::UInt8) end end -wait_close(s::BufferStream) = if isopen(s) wait(s.close_c); end +wait_close(s::BufferStream) = if isopen(s); wait(s.close_c); end start_reading(s::BufferStream) = nothing -write(s::BufferStream, b::UInt8) = write(s, [b]) -write(s::BufferStream, c::Char) = write(s, string(c)) - -function write{T}(s::BufferStream, a::Array{T}) - rv=write(s.buffer, a) - !(s.buffer_writes) && notify(s.r_c; all=true); - return rv -end -function write(s::BufferStream, p::Ptr, nb::Integer) - rv=write(s.buffer, p, nb) - !(s.buffer_writes) && notify(s.r_c; all=true); +write(s::BufferStream, b::UInt8) = write(s, Ref{UInt8}(b)) +function unsafe_write(s::BufferStream, p::Ptr{UInt8}, nb::UInt) + rv = unsafe_write(s.buffer, p, nb) + !(s.buffer_writes) && notify(s.r_c; all=true) return rv end function eof(s::BufferStream) - wait_readnb(s,1) + wait_readnb(s, 1) return !isopen(s) && nb_available(s)<=0 end diff --git a/base/sysimg.jl b/base/sysimg.jl index dd06024bf8efa8..7a8126d6c9471c 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -86,10 +86,14 @@ include(UTF8String(vcat(length(Core.ARGS)>=2?Core.ARGS[2].data:"".data, "version include("c.jl") include("osutils.jl") +# Core I/O +include("io.jl") +include("iostream.jl") +include("iobuffer.jl") + # strings & printing include("char.jl") include("ascii.jl") -include("iobuffer.jl") include("string.jl") include("unicode.jl") include("parse.jl") @@ -98,10 +102,6 @@ include("regex.jl") include("base64.jl") importall .Base64 -# Core I/O -include("io.jl") -include("iostream.jl") - # system & environment include("libc.jl") using .Libc: getpid, gethostname, time