shortestCode method

Iterable<int> shortestCode(
  1. List<int> data
)

Find the shortest code using a mix of tables A B or C

Implementation

Iterable<int> shortestCode(List<int> data) {
  // table is defined as:
  //   0 = 000 no table set
  //   1 = 001 table A
  //   2 = 010 table B
  //   4 = 100 table C
  var table = 0;

  // the last table seen
  //   0 = none
  //   1 = table A
  //   2 = table B
  //   3 = table C
  var lastTable = 0;

  // the number of chars for the current table
  var length = 0;
  var digitCount = 0;
  // var fnc1Count = 0;

  final result = <int>[];

  void addFrom(List<int> data, int start) {
    Map<int, int>? t;
    if (table & 4 != 0 && digitCount & 1 == 0 /*&& digitCount > 0*/) {
      // New data from table C
      t = BarcodeMaps.code128C;
      if (lastTable == 1) {
        result.add(t[BarcodeMaps.code128CodeA]!);
      } else if (lastTable == 2) {
        result.add(t[BarcodeMaps.code128CodeB]!);
      }
      lastTable = 3;
    } else if (table & 1 != 0) {
      // New data from table A
      t = BarcodeMaps.code128A;
      if (lastTable == 2) {
        result.add(t[BarcodeMaps.code128CodeB]!);
      } else if (lastTable == 3) {
        result.add(t[BarcodeMaps.code128CodeC]!);
      }
      lastTable = 1;
    } else if (table & 2 != 0) {
      // New data from table B
      t = BarcodeMaps.code128B;
      if (lastTable == 1) {
        result.add(t[BarcodeMaps.code128CodeA]!);
      } else if (lastTable == 3) {
        result.add(t[BarcodeMaps.code128CodeC]!);
      }
      lastTable = 2;
    }

    if (t == null) {
      throw BarcodeException(
          'Unable to encode "${String.fromCharCodes(data)}" to $name Barcode');
    }

    // Add sublist(start, length + start)
    if (lastTable == 3) {
      // Encode Code 128C $digitCount
      for (var i = start + length - 1; i >= start; i--) {
        if (data[i] == BarcodeMaps.code128FNC1) {
          result.add(t[BarcodeMaps.code128FNC1]!);
        } else {
          final digit = data[i] - 0x30 + (data[i - 1] - 0x30) * 10;
          assert(t[digit] != null);
          result.add(t[digit]!);
          i--;
        }
      }
    } else {
      for (final c in data.sublist(start, start + length).reversed) {
        assert(t[c] != null);
        result.add(t[c]!);
      }
    }
  }

  for (var index = data.length - 1; index >= 0; index--) {
    final code = data[index];

    final codeA = useCode128A && BarcodeMaps.code128A.containsKey(code);
    final codeB = useCode128B && BarcodeMaps.code128B.containsKey(code);
    final isFnc1 = code == BarcodeMaps.code128FNC1;
    final codeC = useCode128C && (code >= 0x30 && code <= 0x39);

    var available = 0;
    if (codeA) {
      available = 1;
    }
    if (codeB) {
      available |= 2;
    }
    if (codeC || isFnc1) {
      available |= 4;
    }

    if (available == 0) {
      throw BarcodeException(
          'Unable to encode "${String.fromCharCode(code)}" to $name Barcode');
    }

    if (codeC) {
      // It's a digit
      digitCount++;
    } else if (isFnc1) {
      length++;
      addFrom(data, index);
      length = 0;
      digitCount = 0;
      continue;
    } else {
      if (digitCount >= 4) {
        // Use to CODE C to output 4 digits or more

        if (digitCount & 1 != 0) {
          // if Odd number, remove the first digit
          digitCount--;
        } else {
          // addFrom(data, index + 1);
        }
        if (length > digitCount) {
          length -= digitCount;
          // First: Add $length chars using one of the tables A or B
          table &= 3;
          if (table == 0) {
            throw BarcodeException(
                'Unable to encode "${String.fromCharCodes(data)}" to $name Barcode');
          }
          addFrom(data, index + digitCount + 1);
          length = digitCount;
        }
        // Then: Optimize $digitCount with table C');
        table = 4;
        addFrom(data, index + 1);
        table = 0;
        length = 0;
      }
      digitCount = 0;
      // fnc1Count = 0;
    }

    if (table == 0) {
      // Add first $code to table $available
      table = available;
      length++;
    } else {
      final newTable = table & available;
      if (newTable == 0) {
        // Change table to any of $table
        addFrom(data, index + 1);
        length = 0;
        table = available;
      } else {
        table = newTable;
      }
      length++;
    }
  }

  if (digitCount >= 2) {
    if (digitCount & 1 != 0) {
      // Odd number of digits, add the last one
      length -= digitCount - 1;
      addFrom(data, digitCount - 1);
      digitCount--;
    } else if (length > digitCount) {
      length -= digitCount;
      addFrom(data, digitCount);
    }
    table = 4;
    length = digitCount;
  }
  if (length > 0) {
    // Add remaining data
    addFrom(data, 0);
  }

  // Add the start code
  if (lastTable == 1) {
    result.add(BarcodeMaps.code128StartCodeA);
  } else if (lastTable == 2) {
    result.add(BarcodeMaps.code128StartCodeB);
  } else if (lastTable == 3) {
    result.add(BarcodeMaps.code128StartCodeC);
  }

  return result.reversed;
}