значение экземпляра kaitai троичное: не может комбинировать типы вывода - PullRequest
1 голос
/ 06 мая 2019

Я создал Kaitai Struct .ksy для двух очень похожих форматов файлов журнала Digilent. Второй формат (openlogger) является расширением первого (openscope) с двумя дополнительными полями в структуре. Область действия в основном одноканальный регистратор; дополнительные поля регистратора описывают количество активных каналов (a u1, макс. 8) и карту порядка каналов для выборки (a u1 x 8).

Я пытаюсь согласовать интерфейс для двух форматов, синтезируя всегда присутствующие поля для num_channels и channel_map; это отлично работает для экземпляра num_channels. Однако я не могу понять, как создать подходящее значение для карты канала, .ksy ниже сообщает об ошибке: /types/body/types/header/instances/channel_order/value: can't combine output types: ArrayType(Int1Type(false)) vs CalcBytesType

Я не могу понять, как я могу представить часть if_false ([0]) как ArrayType.

Есть ли лучший способ подойти к этому?

meta:
  id: dlog
  file-extension: dlog
seq:
  - id: endianness
    type: u1
    doc: 0 - little endian 1 - big endian
  - id: body
    type: body
types:
  body:
    meta:
      endian:
        switch-on: _root.endianness
        cases:
          0: le
          1: be
    seq:
      - id: header
        type: header
    instances:
      data:
        pos: header.start_of_data
        type: data
    types:
      header:
        seq:
        - id: sample_size
          type: u1
        - id: header_size
          type: u2
        - id: start_of_data
          type: u2
        - id: dlog_format
          type: u2
          enum: dlog_formats
        - id: dlog_version
          type: u4

        - id: voltage_units
          type: u8
        - id: stop_reason
          type: u4
          enum: stop_reasons
          #...

        - id: num_openlogger_channels
          type: u4
          if: dlog_format == dlog_formats::openlogger
          doc: number of channels per sample
        - id: openlogger_channel_map
          type: u1
          repeat: expr
          repeat-expr: 8
          if: dlog_format == dlog_formats::openlogger
          doc: channel order

        instances:
          num_channels:
            value: 'dlog_format == dlog_formats::openlogger ? num_openlogger_channels : 1'
          channel_map:
            value: 'dlog_format == dlog_formats::openlogger ? openlogger_channel_map : [0]'

      data:
        seq:
        - id: samples
          type: sample
          repeat: eos
        types:
          sample:
            seq:
              - id: channel
                type:
                  switch-on: _root.body.header.sample_size
                  cases:
                    1: s1
                    2: s2
                    4: s4
                repeat: expr
                repeat-expr: _root.body.header.num_channels

enums:
  dlog_formats:
    1: openscope
    3: openlogger
  stop_reasons:
    0: normal
    1: forced
    2: error
    3: overflow
    4: unknown

1 Ответ

1 голос
/ 06 мая 2019

Литерал [0] анализируется как байтовый массив: это поведение по умолчанию, от которого люди обычно зависят, поэтому синтаксический анализатор эвристического массива обрабатывает все массивы, значения которых соответствуют образцу 0..255, как байтовые массивы, а не как истинные массивы.

Вы все еще можете сделать настоящий литерал массива, если захотите, принудительно применив его к типу:

[0].as<u1[]>

Обратите внимание, что это может вызвать проблемы с C ++ 98, в котором отсутствуетоднострочные инициализаторы для истинных массивов (std :: vector).

...