interleaveWithECBytes static method

BitArray interleaveWithECBytes(
  1. BitArray bits,
  2. int numTotalBytes,
  3. int numDataBytes,
  4. int numRSBlocks,
)

Interleave "bits" with corresponding error correction bytes. On success, store the result in "result". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details.

Implementation

static BitArray interleaveWithECBytes(
  BitArray bits,
  int numTotalBytes,
  int numDataBytes,
  int numRSBlocks,
) {
  // "bits" must have "getNumDataBytes" bytes of data.
  if (bits.sizeInBytes != numDataBytes) {
    throw WriterException('Number of bits and data bytes does not match');
  }

  // Step 1.  Divide data bytes into blocks and generate error correction bytes for them. We'll
  // store the divided data bytes blocks and error correction bytes blocks into "blocks".
  int dataBytesOffset = 0;
  int maxNumDataBytes = 0;
  int maxNumEcBytes = 0;

  // Since, we know the number of reedsolmon blocks, we can initialize the vector with the number.
  final blocks = <BlockPair>[]; //numRSBlocks

  for (int i = 0; i < numRSBlocks; ++i) {
    final numDataBytesInBlock = [0];
    final numEcBytesInBlock = [0];
    getNumDataBytesAndNumECBytesForBlockID(
      numTotalBytes,
      numDataBytes,
      numRSBlocks,
      i,
      numDataBytesInBlock,
      numEcBytesInBlock,
    );

    final size = numDataBytesInBlock[0];
    final dataBytes = Uint8List(size);
    bits.toBytes(8 * dataBytesOffset, dataBytes, 0, size);
    final ecBytes = generateECBytes(dataBytes, numEcBytesInBlock[0]);
    blocks.add(BlockPair(dataBytes, ecBytes));

    maxNumDataBytes = math.max(maxNumDataBytes, size);
    maxNumEcBytes = math.max(maxNumEcBytes, ecBytes.length);
    dataBytesOffset += numDataBytesInBlock[0];
  }
  if (numDataBytes != dataBytesOffset) {
    throw WriterException('Data bytes does not match offset');
  }

  final result = BitArray();

  // First, place data blocks.
  for (int i = 0; i < maxNumDataBytes; ++i) {
    for (BlockPair block in blocks) {
      final dataBytes = block.dataBytes;
      if (i < dataBytes.length) {
        result.appendBits(dataBytes[i], 8);
      }
    }
  }
  // Then, place error correction blocks.
  for (int i = 0; i < maxNumEcBytes; ++i) {
    for (BlockPair block in blocks) {
      final ecBytes = block.errorCorrectionBytes;
      if (i < ecBytes.length) {
        result.appendBits(ecBytes[i], 8);
      }
    }
  }
  if (numTotalBytes != result.sizeInBytes) {
    // Should be same.
    throw WriterException(
      'Interleaving error: $numTotalBytes and ${result.sizeInBytes} differ.',
    );
  }

  return result;
}