为了给出一些上下文,我正在解析DICOM文件,并且难以使用传输语法条目来确定是使用隐式还是显式解析。但是,让我定义一个简化的语法,因此不需要dicom知识。
我们有一系列条目,每个条目都有一个group number
和一个data
部分。组号始终表示为u2
,但数据可以是不同类型,例如u2
或u4
。条目的顺序可以是任意的,除了group number == 2
的所有条目必须位于顶部。 group number == 2
的所有条目的数据类型均为u2
,但后续数据部分可能不同。
这里有困难的部分:group number != 2
的所有项目都有数据类型u4
当且仅当之前存在与此类似的条目时才会出现:
(group, data) == (0x0002, 0x0101)
在python中,我会像这样解析它:
def read_entries(stream):
is_u4 = False
while not stream.eos():
group = stream.read_u2()
if group != 2 and is_u4:
data = stream.read_u4()
else:
data = stream.read_u2()
if group == 2 and data == 0x0101:
is_u4 = True
yield (group, data)
有没有办法用kaitai-struct实现这个目标?
答案 0 :(得分:3)
现在不可能将Python代码精确转录到KS本身,只能用命令式语言编写plugging in the code。
但是,由于您的其他信息,可以使用其他方法,请参阅下面的解决方案。
Kaitai Struct强调无状态解析,因此我们解析的所有内容实际上都是不可变的(只读),即有些变量可以在解析过程中改变其值。因此,在解析周期之间传播is_u4
是非常重要的事情。例如,我们遇到与MIDI running status类似的问题。
人们建议的一些解决方案有时是使用_parent
语法的递归类型定义+实例传播(参见issue #70),但是:
替代方法,鉴于您提供的其他信息可能是可行的。实际上,事实证明,整个元素流可以分为3组:
因此可以逃脱:
types:
elements:
seq:
- id: elements_2
type: element_2
repeat-until: _.is_u4
- id: elements_4
type: element_4
repeat: eos
element_2:
seq:
- id: group
type: u2
- id: data
type: u2
instances:
is_u4:
value: group == 2 and data == 0x0101
element_4:
seq:
- id: group
type: u2
- id: data
type: u4
请告诉我,如果我做对了,那对你的项目有用吗?