Change behavior of function based on program state?

I’m reading a binary file that stores a UInt16 that tells me if the rest of the section of the file is little-endian or big-endian. If the result of the read is 0x4d4d, it is little endian, and if it is 0x4949 it is big-endian (there are no other possible values). I had considered handling it like this:

f_read = read

function swapped_read(s, typ)
    ntoh(read(s, typ))
end

function handle_endianness(io)
    if read(io, UInt16) == 0x4d4d
        global f_read = swapped_read
    end
end

# ... rest of program

… but handling this with a global variable feels icky … surely there is a better way?
Especially since it looks like the global variable has to be untyped …

Maybe something like this

function swapped_read(s, typ)
    ntoh(read(s, typ))
end

function handle_endianness(io)
    if read(io, UInt16) == 0x4d4d
        return swapped_read
    else
        return read
    end
end

open(filename, "r") do file
    f_read = handle_endianness(io)
    # proceed with f_read
end

This is type-unstable.

Why not just write your own read function that takes an endian-ness flag? Something like:

function myread(io, ::Type{T}, swap::Bool) where {T}
   x = read(io, T)
   return swap ? bswap(x) : x
end

Or, if you don’t want to pass a swap flag around everywhere, you can stash it in the io object by using an IOContext wrapper, i.e. replace io with IOContext(io, :byteswap=>swap) and then call get(io, :byteswap, false) anyplace you need to know whether to swap the byte order.

(Even fancier would be to define your own IO type that includes a byteswap flag, and then override standard functions like read for your IO subtype. Then you wouldn’t even have to touch most of your I/O code to explicitly call your myread function.)

Is there a way to determine the endianness of a system? I know that Python had sys.byteorder … ?

Also, the IO subtype that understands swapping sounds very fun.

ENDIAN_BOM

1 Like

It’s little. Julia doesn’t run on any computers that are big endian and isn’t likely to in the near future.

1 Like