Skip to content

Commit

Permalink
Merge pull request #22941 from JuliaLang/jb/fix6466
Browse files Browse the repository at this point in the history
fix #6466, deprecate `write` on non-isbits arrays
  • Loading branch information
JeffBezanson authored Jul 28, 2017
2 parents 100a6fc + 4f7c072 commit fc10c8b
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 25 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ Deprecated or removed
* The function `showall` is deprecated. Showing entire values is the default, unless an
`IOContext` specifying `:limit=>true` is in use ([#22847]).

* Calling `write` on non-isbits arrays is deprecated in favor of explicit loops or
`serialize` ([#6466]).


Julia v0.6.0 Release Notes
==========================
Expand Down
3 changes: 3 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1596,6 +1596,9 @@ end

@deprecate momenttype(::Type{T}) where {T} typeof((zero(T)*zero(T) + zero(T)*zero(T))/2) false

# issue #6466
# `write` on non-isbits arrays is deprecated in io.jl.

# END 0.7 deprecations

# BEGIN 1.0 deprecations
Expand Down
33 changes: 27 additions & 6 deletions base/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -314,21 +314,21 @@ 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)
if !isbits(eltype(A))
depwarn("Calling `write` on non-isbits arrays is deprecated. Use a loop or `serialize` instead.", :write)
end
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(s::IO, a::Array{T}) where T # mark noinline to ensure the array is gc-rooted somewhere (by the caller)
if isbits(T)
@noinline function write(s::IO, a::Array) # mark noinline to ensure the array is gc-rooted somewhere (by the caller)
if isbits(eltype(a))
return unsafe_write(s, pointer(a), sizeof(a))
else
depwarn("Calling `write` on non-isbits arrays is deprecated. Use a loop or `serialize` instead.", :write)
nb = 0
for b in a
nb += write(s, b)
Expand All @@ -337,6 +337,27 @@ end
end
end

function write(s::IO, a::SubArray{T,N,<:Array}) where {T,N}
if !isbits(T)
return invoke(write, Tuple{IO, AbstractArray}, s, a)
end
elsz = sizeof(T)
colsz = size(a,1) * elsz
if stride(a,1) != 1
for idxs in CartesianRange(size(a))
unsafe_write(s, pointer(a, idxs.I), elsz)
end
return elsz * length(a)
elseif N <= 1
return unsafe_write(s, pointer(a, 1), colsz)
else
for idxs in CartesianRange((1, size(a)[2:end]...))
unsafe_write(s, pointer(a, idxs.I), colsz)
end
return colsz * trailingsize(a,2)
end
end


function write(s::IO, ch::Char)
c = reinterpret(UInt32, ch)
Expand Down
15 changes: 0 additions & 15 deletions base/iostream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -169,21 +169,6 @@ function unsafe_write(s::IOStream, p::Ptr{UInt8}, nb::UInt)
return Int(ccall(:ios_write, Csize_t, (Ptr{Void}, Ptr{Void}, Csize_t), s.ios, p, nb))
end

function write(s::IOStream, a::SubArray{T,N,<:Array}) where {T,N}
if !isbits(T) || stride(a,1)!=1
return invoke(write, Tuple{Any, AbstractArray}, s, a)
end
colsz = size(a,1)*sizeof(T)
if N<=1
return unsafe_write(s, pointer(a, 1), colsz)
else
for idxs in CartesianRange((1, size(a)[2:end]...))
unsafe_write(s, pointer(a, idxs.I), colsz)
end
return colsz*trailingsize(a,2)
end
end

# num bytes available without blocking
nb_available(s::IOStream) = ccall(:jl_nb_available, Int32, (Ptr{Void},), s.ios)

Expand Down
10 changes: 6 additions & 4 deletions test/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,13 @@ end
@test_throws ArgumentError gensym("ab\0")

# issue #6949
let f =IOBuffer(),
let f = IOBuffer(),
x = split("1 2 3")
@test write(f, x) == 3
@test String(take!(f)) == "123"
@test invoke(write, Tuple{IO, AbstractArray}, f, x) == 3
local nb = 0
for c in x
nb += write(f, c)
end
@test nb == 3
@test String(take!(f)) == "123"
end

Expand Down

0 comments on commit fc10c8b

Please sign in to comment.