Skip to content

Instantly share code, notes, and snippets.

@evetion
Created January 18, 2019 22:44
Show Gist options
  • Save evetion/b7f669df7684bb3df650c884d2649bd7 to your computer and use it in GitHub Desktop.
Save evetion/b7f669df7684bb3df650c884d2649bd7 to your computer and use it in GitHub Desktop.
using Base.Meta
using FixedPointNumbers
using Compat
"Generate read (unpack) method for structs."
function generate_read(T::Type)
fc = fieldcount(T)
types = [fieldtype(T, i) for i = 1:fc]
# Create unpack function expression
function_expression = :(function Base.read(io::IO, t::Type{$T}) end)
# Create Type call expression and add parameters
type_expression = :(($T)())
for t in types
read_expression = :(read(io, $t))
append!(type_expression.args, 0) # dummy with known length
type_expression.args[end] = read_expression
end
# Replace empty function body with Type call
function_expression.args[2] = type_expression
eval(function_expression)
end
function generate_io(T::Type)
generate_read(T)
end
"""Generate IO expressions macro."""
macro gen_io(typ::Expr)
T = typ.args[2]
if isexpr(T, :(<:))
T = T.args[1]
end
if isexpr(T, :curly)
T = T.args[1]
end
ret = Expr(:toplevel, :(Base.@__doc__ $(typ)))
push!(ret.args, :(generate_io($T)))
return esc(ret)
end
"ASPRS LAS point data record format 2"
@gen_io struct LasPoint0
x::Int32
y::Int32
z::Int32
intensity::UInt16
flag_byte::UInt8
raw_classification::UInt8
scan_angle::Int8
user_data::UInt8
pt_src_id::UInt16
end
function read_old(io::IO, ::Type{LasPoint0})
x = read(io, Int32)
y = read(io, Int32)
z = read(io, Int32)
intensity = read(io, UInt16)
flag_byte = read(io, UInt8)
raw_classification = read(io, UInt8)
scan_angle = read(io, UInt8)
user_data = read(io, UInt8)
pt_src_id = read(io, UInt16)
LasPoint0(
x,
y,
z,
intensity,
flag_byte,
raw_classification,
scan_angle,
user_data,
pt_src_id
)
end
# Extend base by enabling reading/writing relevant FixedPointNumbers from IO.
Base.read(io::IO, ::Type{N0f16}) = reinterpret(N0f16, read(io, UInt16))
Base.write(io::IO, t::N0f16) = write(io, reinterpret(UInt16, t))
@inline function test()
io = IOBuffer(read(open("test/libLAS_1.2.las")))
println("----")
seek(io, 227)
print("Old: ")
@time for _ in 1:497536
pp = read_old(io, LasPoint0)
end
seek(io, 227)
print("New: ")
@time for _ in 1:497536
p = read(io, LasPoint0)
end
end
test()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment