SpkFile.fromSource constructor
- SpkSource source
Reads the file summaries from source; segment data is read only
when needed.
Throws FormatException if it is not an SPK file.
Implementation
factory SpkFile.fromSource(SpkSource source) {
if (source.length < _recordBytes) {
throw const FormatException('File too short for a DAF header');
}
final bytes = source.read(0, _recordBytes);
final data = ByteData.sublistView(bytes);
final id = _text(bytes, 0, 8);
if (id != 'DAF/SPK') {
throw FormatException('Not an SPK file (identifier "$id")');
}
final format = _text(bytes, 88, 8);
final endian = switch (format) {
'LTL-IEEE' => Endian.little,
'BIG-IEEE' => Endian.big,
_ => throw FormatException('Unknown number format "$format"'),
};
final nd = data.getInt32(8, endian);
final ni = data.getInt32(12, endian);
if (nd != 2 || ni != 6) {
throw FormatException('Unexpected SPK summary: ND=$nd, NI=$ni');
}
final internalName = _text(bytes, 16, 60);
final firstSummary = data.getInt32(76, endian);
final file = SpkFile._(internalName, [], source, endian);
// Rozmiar jednego wpisu spisu w słowach 8-bajtowych: ND liczb double
// i NI liczb int32 (po dwie na słowo).
const summaryWords = 2 + (6 + 1) ~/ 2;
var record = firstSummary;
while (record != 0) {
// Rekord spisu i tuż za nim rekord z nazwami segmentów.
final bytes = source.read((record - 1) * _recordBytes, 2 * _recordBytes);
final data = ByteData.sublistView(bytes);
final next = data.getFloat64(0, endian).toInt();
final count = data.getFloat64(16, endian).toInt();
for (var i = 0; i < count; i++) {
final at = 24 + i * summaryWords * 8;
int int32(int k) => data.getInt32(at + 16 + 4 * k, endian);
final nameAt = _recordBytes + i * summaryWords * 8;
file.segments.add(
SpkSegment._(
file,
name: _text(bytes, nameAt, summaryWords * 8),
startEt: data.getFloat64(at, endian),
endEt: data.getFloat64(at + 8, endian),
target: int32(0),
center: int32(1),
frame: int32(2),
dataType: int32(3),
beginWord: int32(4),
endWord: int32(5),
),
);
}
record = next;
}
return file;
}