2

To give some context, I am parsing a DICOM file, and having difficulties using the Transfer Syntax entry to determine whether to use implicit or explicit parsing. But let me define a simplified syntax, so no dicom knowledge is required.

We have a sequence of entries, each entry has a group number , and a data part. The group number is always represented as u2, but the data can be of different types, lets say u2 or u4. The order of the entries can be arbitrary, except that all the entries with group number == 2 must be at the top. All entries with group number == 2 has a data type of u2, but subsequent data parts can differ.

And here comes the hard part: all the items with group number != 2 have data type u4 if and only if an entry exactly like this was present previously:

(group, data) == (0x0002, 0x0101)

In python for example, I would parse it like this:

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)

Is there a way to achieve this using kaitai-struct?

4

1 回答 1

3

简短的回答

仅通过插入以命令式语言编写的代码,目前不可能将 Python 代码准确转录为 KS 本身。

但是,由于您的附加信息,可以使用另一种方法,请参阅下面的解决方案。

更长的答案

Kaitai Struct 强调无状态解析,因此我们解析的所有内容实际上都是不可变的(只读),即存在可以在解析过程中改变其值的变量。因此,在解析周期之间进行传播is_u4并非易事。例如,我们在MIDI 运行状态方面也有类似的问题。

_parent人们有时建议的一些解决方案是递归类型定义 + 使用语法传播实例(参见问题 #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

请告诉我我是否做对了,这对你的项目有用吗?

于 2017-04-26T12:02:24.727 回答