为了提供一些背景信息,我正在解析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实现这一目标?
最佳答案
简短答案
目前,只有用命令式语言编写的plugging in the code才能将Python代码准确地转录为KS本身。
但是,由于您提供了其他信息,因此可以使用一种替代方法,请参见下面的解决方案。
更长的答案
Kaitai Struct强调无状态解析,因此我们解析的所有内容实际上都是不可变的(只读),即在解析过程中存在可以更改其值的变量。因此,在解析周期之间传播is_u4
并非易事。例如,我们对MIDI running status有类似的问题。
人们建议的一些解决方案有时是递归类型定义+使用_parent
语法传播实例(请参见issue #70),但是:
当前,这是由于缺少递归定义的实例值的类型定义+缺少初始值种子
这将生成一个值的链接列表,而不是一个数组(即大多数人不满意的列表)
这会给调用堆栈造成沉重的损失(即,长的结构很可能会在堆栈耗尽时失败)
考虑到您提供的其他信息,其他方法可能是可行的。实际上,事实证明,整个元素流可以分为3组:
(0x0002,0x0101)之前的元素-它们都使用u2-u2格式
(0x0002,0x0101)元素本身-请注意,首次遇到该元素时也始终为u2-u2
(0x0002,0x0101)之后的元素-它们都使用u2-u4格式;即使之后遇到其他(0x0002,0x0101),根据您提供的算法,也应将其读为u2-u4,这样就可以了。
因此有可能摆脱:
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
请告诉我我是否正确,这对您的项目有用吗?
关于python - 根据之前的元素解析项目,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43631711/