Загрузка структур двоичного кода C из файла в структуры Swift - PullRequest
0 голосов
/ 13 сентября 2018

Мне выдан двоичный файл, сгенерированный системой, предназначенной для поддержки встроенного оборудования.Файл был сгенерирован с использованием C. У меня есть электронная таблица, в которой указан формат указанного файла.

Возможно, я смогу загрузить этот файл с помощью C, хотя прошло довольно много времени с тех пор, как мне пришлось прикоснутьсяC, но я действительно хотел бы придерживаться чистого Swift (4) и загружать этот файл в правильные соответствующие структуры Swift, используя современное соглашение и методы Swift.

Я нашел несколько руководств по работе с "«Небезопасные» указатели и различные другие возможные решения, но я не смог собрать все это вместе так, чтобы это работало со сложностью этого файла.

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

Базовый заголовок файла

struct FileHeader {
  let index: Int32
  let id: UInt16
  let headerCRC: UInt16
}

Структура со множеством типов значений

struct MiscRecord {
  let lengthOfRecordData: UInt16
  let crcOfRecordData: UInt16
  let resetCause: UInt8
  let disable: Bool
  let ratio: Float
}

Структура с массивами

struct AccessoryRecord {
  struct AccessoryConfiguration {
    let type: UInt8
    let startupTime: UInt32
    let shutoffTime: UInt32
  }

  let lengthOfRecordData: UInt16
  let crcOfRecordData: UInt16
  // Not even sure if ContiguousArray is the right thing or necessary.
  // I know that there will be a static number of 5 records present in the file.
  let accessoryConfigurations: ContiguousArray<AccessoryConfiguration>
}

Компоновка

struct ConfigLayout {
  let fileHeader: FileHeader
  let miscRecord: MiscRecord
  let accessoryRecord: AccessoryRecord
}

В общем, есть актуальныеу этого файла всего около 12 структур.Я знаю смещение, где начинается каждая структура.Я могу загрузить файл с диска и получить объект данных.

Является ли объект данных правильным?Должен ли я использовать UnsafeMutableRawPointer как-то?Как?

Я могу себе представить, что если я знаю длину данных, я смогу сделать что-то похожее на memcpy в структуре и сохранить его простым, но я не знаю, какой лучший способсделать это.

Я застрял с использованием данных [offset..length], что глупо, потому что он создает копию данных, и я получаю странные исключения, которые заставили меня сделать копиюзатем еще одна копия: data.advanced (by: 0) [offset..length].(Примечание: значение «offset..length» в этом абзаце должно быть [точка-точка меньше-меньше], но символ меньше-чем испортил отображение текста.)

Подводя итогвозникает вопрос:

Каков наилучший способ загрузки двоичного файла, записанного из структур C, в серию соответствующих структур Swift?

Редактировать:

Вот что я пытался сделать:

init(withData: Data) {
    // fileHeader
    var offset = 0
    var length = MemoryLayout<FileHeader>.size + offset
    fileHeader = FileHeader(withData: withData[offset..<length])

    // miscRecord
    offset = length
    length = MemoryLayout<MiscRecord>.size + offset
    miscRecord = MiscRecord(withData: withData[offset..<length])

    // accessoryRecord
    offset = length
    length = MemoryLayout<AccessoryRecord>.size + offset
    accessoryRecord = AccessoryRecord(withData: withData[offset..<length])
}

... НО, я видел сбои во время выполнения в withData[offset..<length] (EXC_BAD_INSTRUCTION).

Мне удалось обойти это, выполнив следующее:

    init(withData: Data) {
      let unneccessaryDataCopy = withData.advanced(by: 0)

      // fileHeader
      var offset = 0
      var length = MemoryLayout<FileHeader>.size + offset
      fileHeader = FileHeader(withData: unneccessaryDataCopy[offset..<length])

      // miscRecord
      offset = length
      length = MemoryLayout<MiscRecord>.size + offset
      miscRecord = MiscRecord(withData: unneccessaryDataCopy[offset..<length])

      // accessoryRecord
      offset = length
      length = MemoryLayout<AccessoryRecord>.size + offset
      accessoryRecord = AccessoryRecord(withData: unneccessaryDataCopy[offset..<length])
    }

.. но это плохо, потому что данные копируются дважды.(Один раз с subset и один раз с advanced(by:).Должен быть лучший способ, и зачем мне все это делать?Я знаю, что данные находятся в байтах, которые я пытаюсь установить в подмножество.

...