Skip to content

Commit 5de0d4c

Browse files
committed
Add ROOTIOBuffer
1 parent 88b05cb commit 5de0d4c

File tree

2 files changed

+133
-0
lines changed

2 files changed

+133
-0
lines changed

src/UpROOT.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ uproot = PyNULL()
1414

1515
include("testdata.jl")
1616
include("pywrappers.jl")
17+
include("rootio.jl")
1718
include("opaque.jl")
1819
include("pyjlconv.jl")
1920
include("tdirectory.jl")

src/rootio.jl

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# This file is a part of UpROOT.jl, licensed under the MIT License (MIT).
2+
3+
const kByteCountMask = UInt32(0x40000000)
4+
const kByteCountMask_UInt16 = UInt16(kByteCountMask >> 16)
5+
6+
7+
struct ROOTIOBuffer{T}
8+
buffer::Base.GenericIOBuffer{T}
9+
end
10+
11+
ROOTIOBuffer(data::AbstractVector{UInt8}) = ROOTIOBuffer(IOBuffer(data))
12+
13+
14+
Base.eof(io::ROOTIOBuffer) = eof(io.buffer)
15+
16+
17+
function Base.read(io::ROOTIOBuffer, ::Type{String})
18+
short_len = read(io.buffer, UInt8)
19+
len = (short_len < 0xff) ? UInt32(short_len) : read(io.buffer, UInt32)
20+
String(read(io.buffer, len))
21+
end
22+
23+
24+
function Base.read(io::ROOTIOBuffer, ::Type{T}) where {T<:Real}
25+
x::T = read(io.buffer, T)
26+
if sizeof(T) > 1
27+
x = ntoh(x)
28+
end
29+
x
30+
end
31+
32+
33+
function Base.read(io::ROOTIOBuffer, ::Type{Vector{T}}) where {T<:Real}
34+
len = read(io, UInt32)
35+
A = Vector{T}(undef, len)
36+
read!(io.buffer, A)
37+
if sizeof(T) > 1
38+
A .= ntoh.(A)
39+
end
40+
A
41+
end
42+
43+
44+
45+
struct ROOTClassHeader
46+
classname::String
47+
end
48+
49+
function Base.read(io::ROOTIOBuffer, ::Type{ROOTClassHeader})
50+
classname = read(io, String)
51+
padding = read(io, UInt8)
52+
ROOTClassHeader(classname)
53+
end
54+
55+
56+
57+
struct ROOTClassVersion
58+
nbytes::UInt32
59+
version::Int16
60+
end
61+
62+
function Base.read(io::ROOTIOBuffer, ::Type{ROOTClassVersion})
63+
a = read(io, UInt16)
64+
65+
if a & kByteCountMask_UInt16 > 0
66+
# byte count available
67+
b = read(io, UInt32)
68+
cnt = (UInt32(a & ~kByteCountMask_UInt16) << 16 | b >> 16)
69+
version = b % Int16
70+
bytecount = cnt - sizeof(version)
71+
ROOTClassVersion(bytecount, version)
72+
else
73+
ROOTClassVersion(0, signed(a))
74+
end
75+
end
76+
77+
78+
79+
struct TObjectContent
80+
fUniqueID::UInt32
81+
fBits::UInt32
82+
end
83+
84+
function Base.read(io::ROOTIOBuffer, ::Type{TObjectContent})
85+
ver = read(io, ROOTClassVersion)
86+
@assert ver.nbytes == 0
87+
@assert ver.version == 1
88+
fUniqueID = read(io, UInt32)
89+
fBits = read(io, UInt32)
90+
TObjectContent(fUniqueID, fBits)
91+
end
92+
93+
94+
95+
struct TNamedContent{S<:AbstractString}
96+
tobject::TObjectContent
97+
fName::S
98+
fTitle::S
99+
end
100+
101+
function Base.read(io::ROOTIOBuffer, ::Type{TNamedContent})
102+
ver = read(io, ROOTClassVersion)
103+
@assert ver.version == 1
104+
tobject = read(io, TObjectContent)
105+
fName = read(io, String)
106+
fTitle = read(io, String)
107+
TNamedContent(tobject, fName, fTitle)
108+
end
109+
110+
111+
112+
struct TClonesArrayHeader{S<:AbstractString}
113+
tobject::TObjectContent
114+
fName::S
115+
fClass::S
116+
nobjects::Int
117+
fLowerBound::Int
118+
end
119+
120+
function Base.read(io::ROOTIOBuffer, ::Type{TClonesArrayHeader})
121+
ver = read(io, ROOTClassVersion)
122+
@assert ver.version == 4
123+
tobject = read(io, TObjectContent)
124+
fName = read(io, String)
125+
fClass = read(io, String)
126+
nobjects = read(io, Int32)
127+
fLowerBound = read(io, Int32)
128+
129+
# assuming CanBypassStreamer() is false:
130+
nch = read(io, Int8)
131+
TClonesArrayHeader(tobject, fName, fClass, Int(nobjects), Int(fLowerBound))
132+
end

0 commit comments

Comments
 (0)