Skip to content

Commit 61e3d2f

Browse files
authored
fix: parsing CDFv2 attributes (#17)
1 parent 038d8ba commit 61e3d2f

File tree

7 files changed

+40
-26
lines changed

7 files changed

+40
-26
lines changed

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,4 @@ Manifest*.toml
66
/docs/build/
77
ref/
88
.claude/
9-
data/
10-
!data/a_*.cdf
9+
data/.*

data/ac_h2_sis_20101105_v06.cdf

95.1 KB
Binary file not shown.

src/loading/attribute.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,17 @@ function vattrib(cdf, varnum, name)
109109
return nothing
110110
end
111111

112-
function _search_aedr_entries(source, aedr_head::Int64, RecordSizeType, cdf_encoding::Int32, target_varnum::Integer)
112+
function _search_aedr_entries(source, aedr_head, RecordSizeType, cdf_encoding::Int32, target_varnum::Integer)
113113
aedr_head == 0 && return nothing
114-
offset = aedr_head
114+
offset = Int(aedr_head)
115+
_num_offset = 13 + 2 * sizeof(RecordSizeType)
116+
_next_offset = 5 + sizeof(RecordSizeType)
115117
while offset != 0
116-
num = read_be(source, offset + 29, Int32)
118+
num = read_be(source, offset + _num_offset, Int32)
117119
if num == target_varnum
118120
return load_aedr_data(source, offset, RecordSizeType, cdf_encoding)
119121
end
120-
offset = read_be(source, offset + 13, Int64)
122+
offset = Int(read_be(source, offset + _next_offset, RecordSizeType))
121123
end
122124
return nothing
123125
end

src/parsing.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,21 +125,23 @@ function readname(buf::Vector{UInt8}, offset::Int)
125125
return @views buf[offset:(offset + 255)]
126126
end
127127

128-
@resumable function get_offsets_lazy(buffer::Vector{UInt8}, pos::Int64, ::Type{RecordSizeType}) where {RecordSizeType}
128+
@resumable function get_offsets_lazy(buffer::Vector{UInt8}, pos, ::Type{RecordSizeType}) where {RecordSizeType}
129+
pos = Int(pos)
129130
while pos != 0
130131
@yield pos
131-
pos = read_be(buffer, pos + 1 + sizeof(RecordSizeType) + 4, RecordSizeType)
132+
pos = Int(read_be(buffer, pos + 1 + sizeof(RecordSizeType) + 4, RecordSizeType))
132133
end
133134
end
134135

135-
function get_offsets!(offsets, buffer::Vector{UInt8}, pos::Int64, RecordSizeType)
136+
function get_offsets!(offsets, buffer::Vector{UInt8}, pos, FieldSizeType)
137+
pos = Int(pos)
136138
while pos != 0
137139
push!(offsets, pos)
138-
pos = read_be(buffer, pos + 1 + sizeof(RecordSizeType) + 4, Int64)
140+
pos = Int(read_be(buffer, pos + 1 + sizeof(FieldSizeType) + 4, FieldSizeType))
139141
end
140142
return offsets
141143
end
142-
get_offsets(args...) = get_offsets!(Int64[], args...)
144+
get_offsets(args...) = get_offsets!(Int[], args...)
143145

144146

145147
# Big-endian readers (CDF uses big-endian for most fields)

src/records/aedr.jl

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,33 @@
66
Attribute g/r Entry Descriptor Record.
77
Describes a global entry (for global attributes) or rVariable entry (for variable attributes).
88
"""
9-
struct AEDR{A}
10-
header::Header
11-
AEDRnext::Int64 # Offset to next AEDR in chain
9+
struct AEDR{FST, A}
10+
# header::Header
11+
AEDRnext::FST # Offset to next AEDR in chain
1212
AttrNum::Int32 # Attribute number
1313
DataType::Int32 # CDF data type of the entry
1414
Num::Int32 # Entry number
1515
NumElems::Int32 # Number of elements in the entry
1616
NumStrings::Int32 # Number of strings (for string data)
17-
rfuB::Int32 # Reserved field B
18-
rfuC::Int32 # Reserved field C
19-
rfuD::Int32 # Reserved field D
20-
rfuE::Int32 # Reserved field E
17+
rfuB::RInt32 # Reserved field B
18+
rfuC::RInt32 # Reserved field C
19+
rfuD::RInt32 # Reserved field D
20+
rfuE::RInt32 # Reserved field E
2121
Value::A # This consists of the number of elements (specified by the NumElems field) of the data type (specified by the DataType field). This can be thought of as a 1-dimensional array of values (stored contiguously). The size of this field is the product of the number of elements and the size in bytes of each element.
2222
end
2323

2424
@inline function load_aedr_data(buffer::Vector{UInt8}, offset, RecordSizeType, cdf_encoding)
25-
datatype = read_be(buffer, offset + 25, Int32)
26-
NumElems = read_be(buffer, offset + 33, Int32)
25+
_datatype_offset = 9 + 2 * sizeof(RecordSizeType)
26+
_numelems_offset = 17 + 2 * sizeof(RecordSizeType)
27+
_data_offset = 41 + 2 * sizeof(RecordSizeType)
28+
datatype = read_be(buffer, offset + _datatype_offset, Int32)
29+
NumElems = read_be(buffer, offset + _numelems_offset, Int32)
2730
T = julia_type(datatype, NumElems)
2831
return if datatype in (CDF_CHAR, CDF_UCHAR)
29-
load_char_data(buffer, offset + 57, NumElems)
32+
load_char_data(buffer, offset + _data_offset, NumElems)
3033
else
3134
needs_byte_swap = is_big_endian_encoding(cdf_encoding)
32-
load_attribute_data(T, buffer, offset + 57, NumElems, needs_byte_swap)
35+
load_attribute_data(T, buffer, offset + _data_offset, NumElems, needs_byte_swap)
3336
end
3437
end
3538

test/cdf2_test.jl

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1+
using Test
12
using CommonDataFormat
23

3-
file = "/Users/zijin/.cdaweb/data/WI_H0_MFI/wi_h0_mfi_20210115_v05.cdf"
4-
ds = CDFDataset(file)
5-
keys(ds)
6-
ds["BGSE"]
4+
include("utils.jl")
5+
6+
@testset "CDFDataset" begin
7+
file = data_path("ac_h2_sis_20101105_v06.cdf")
8+
ds = CDFDataset(file)
9+
var = ds["flux_He"]
10+
@test "TITLE" in keys(ds.attrib)
11+
@test "CATDESC" in keys(var.attrib)
12+
@test CommonDataFormat.attrib(var, "FILLVAL")[1] == -1.0f31
13+
end

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import CommonDataFormat as CDF
55
include("utils.jl")
66
include("epochs_test.jl")
77
include("comprehensive_test.jl")
8+
include("cdf2_test.jl")
89
include("CommonDataModelExt_test.jl")
910

1011
@testset "Fill Value" begin

0 commit comments

Comments
 (0)