Skip to content

Commit

Permalink
Merge pull request #3633 from simonbyrne/byteorder
Browse files Browse the repository at this point in the history
RFC: ByteOrder types for io
  • Loading branch information
timholy committed Jul 24, 2013
2 parents 159203b + dba7023 commit 900478c
Show file tree
Hide file tree
Showing 6 changed files with 1,316 additions and 203 deletions.
10 changes: 0 additions & 10 deletions base/complex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,6 @@ end
show(io::IO, z::Complex) = complex_show(io, z, false)
showcompact(io::IO, z::Complex) = complex_show(io, z, true)

function read{T<:Real}(s::IO, ::Type{Complex{T}})
r = read(s,T)
i = read(s,T)
Complex{T}(r,i)
end
function write(s::IO, z::Complex)
write(s,real(z))
write(s,imag(z))
end


## singleton type for imaginary unit constant ##

Expand Down
6 changes: 5 additions & 1 deletion base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,10 @@ export
hton,
ltoh,
ntoh,
HostByteOrder,
ReverseByteOrder,
LittleByteOrder,
NetworkByteOrder,
mmap,
mmap_array,
mmap_bitarray,
Expand Down Expand Up @@ -1263,4 +1267,4 @@ export
@sprintf,
@deprecate,
@boundscheck,
@inbounds
@inbounds
100 changes: 77 additions & 23 deletions base/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,26 @@

## byte-order mark, ntoh & hton ##

abstract ByteOrder

type HostByteOrder <: ByteOrder
end

type ReverseByteOrder <: ByteOrder
end

const ENDIAN_BOM = reinterpret(Uint32,uint8([1:4]))[1]

if ENDIAN_BOM == 0x01020304
typealias NetworkByteOrder HostByteOrder
typealias LittleByteOrder ReverseByteOrder
ntoh(x) = identity(x)
hton(x) = identity(x)
ltoh(x) = bswap(x)
htol(x) = bswap(x)
elseif ENDIAN_BOM == 0x04030201
typealias NetworkByteOrder ReverseByteOrder
typealias LittleByteOrder HostByteOrder
ntoh(x) = bswap(x)
hton(x) = bswap(x)
ltoh(x) = identity(x)
Expand All @@ -30,28 +42,31 @@ 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
function write(s::IO, x::Integer,::Type{NetworkByteOrder})
sz = sizeof(x)
for n = sz:-1:1
write(s, uint8((x>>>((n-1)<<3))))
end
else
function write(s::IO, x::Integer)
sz = sizeof(x)
for n = 1:sz
write(s, uint8((x>>>((n-1)<<3))))
end
sz
sz
end
function write(s::IO, x::Integer,::Type{LittleByteOrder})
sz = sizeof(x)
for n = 1:sz
write(s, uint8((x>>>((n-1)<<3))))
end
sz
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(s::IO, x::Bool) = write(s, uint8(x))
#write{O<:ByteOrder}(s::IO, x::Float16, ::Type{O}) = write(s, reinterpret(Int16,x), O)
write{O<:ByteOrder}(s::IO, x::Float32, ::Type{O}) = write(s, reinterpret(Int32,x), O)
write{O<:ByteOrder}(s::IO, x::Float64, ::Type{O}) = write(s, reinterpret(Int64,x), O)
function write{O<:ByteOrder}(s::IO, z::Complex, ::Type{O})
write(s,real(z),O)
write(s,imag(z),O)
end

write(s::IO, x::Number) = write(s, x, HostByteOrder)

function write(s::IO, a::AbstractArray)
nb = 0
Expand All @@ -60,6 +75,14 @@ function write(s::IO, a::AbstractArray)
end
nb
end
function write{O<:ByteOrder}(s::IO, a::AbstractArray, ::Type{O})
nb = 0
for i = 1:length(a)
nb += write(s, a[i],O)
end
nb
end


function write(s::IO, c::Char)
if c < 0x80
Expand Down Expand Up @@ -88,32 +111,61 @@ 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})
function read{T <: Integer}(s::IO, ::Type{T},::Type{LittleByteOrder})
x = zero(T)
for n = 1:sizeof(x)
x |= (convert(T,read(s,Uint8))<<((n-1)<<3))
end
return x
end

function read{T <: Integer}(s::IO, ::Type{T},::Type{NetworkByteOrder})
x = zero(T)
for n = sizeof(x):-1:1
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{Float32}) = box(Float32,unbox(Int32,read(s,Int32)))
read(s::IO, ::Type{Float64}) = box(Float64,unbox(Int64,read(s,Int64)))
read{O<:ByteOrder}(s::IO, ::Type{Float32}, ::Type{O}) = reinterpret(Float32,read(s,Int32,O))
read{O<:ByteOrder}(s::IO, ::Type{Float64}, ::Type{O}) = reinterpret(Float64,read(s,Int64,O))
function read{T<:Real,O<:ByteOrder}(s::IO, ::Type{Complex{T}}, ::Type{O})
r = read(s,T,O)
i = read(s,T,O)
Complex{T}(r,i)
end

read{N<:Number}(s::IO, ::Type{N}) = read(s,N,HostByteOrder)


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

read{T,O<:ByteOrder}(s::IO, t::Type{T}, ::Type{O}, d1::Int, dims::Int...) =
read(s, t, O, tuple(d1,dims...))
read{T,O<:ByteOrder}(s::IO, t::Type{T}, ::Type{O}, d1::Integer, dims::Integer...) =
read(s, t, O, map(int,tuple(d1,dims...)))
read{T,O<:ByteOrder}(s::IO, ::Type{T}, ::Type{O}, dims::Dims) = read(s, Array(T, dims), O)

function read{T,O<:ByteOrder}(s::IO, a::Array{T}, ::Type{O})
for i = 1:length(a)
a[i] = read(s, T, O)
end
return a
end



function read(s::IO, ::Type{Char})
ch = read(s, Uint8)
if ch < 0x80
Expand Down Expand Up @@ -495,4 +547,6 @@ end
# BitArray I/O

write(s::IO, B::BitArray) = write(s, B.chunks)
write{O<:ByteOrder}(s::IO, B::BitArray, ::Type{O}) = write(s, B.chunks, O)
read(s::IO, B::BitArray) = read(s, B.chunks)
read{O<:ByteOrder}(s::IO, B::BitArray, ::Type{O}) = read(s, B.chunks, O)
Loading

0 comments on commit 900478c

Please sign in to comment.