Мне выдан двоичный файл, сгенерированный системой, предназначенной для поддержки встроенного оборудования.Файл был сгенерирован с использованием 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:
).Должен быть лучший способ, и зачем мне все это делать?Я знаю, что данные находятся в байтах, которые я пытаюсь установить в подмножество.