SpkFile.fromSource constructor

SpkFile.fromSource(
  1. 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;
}