encode method

  1. @override
PhoneticEncoding? encode(
  1. String input
)
override

Encodes a string using the Double Metaphone algorithm as configured.

Per specification, the encoding always contains two values. If there is no alternate, the primary and the alternate encodings will be the same.

Returns a PhoneticEncoding for the input String or null if the input is empty (after cleaning up).

Implementation

@override
PhoneticEncoding? encode(String input) {
  // clean up the input and convert to uppercase
  input = PhoneticUtils.clean(input);
  if (input.isEmpty) {
    return null;
  }

  final encoding = _DoubleMetaphoneEncoding(maxLength);

  final slavoGermanic = _isSlavoGermanic(input);
  final silentStart = _isSilentStart(input);

  // using an iterator allows us to iterate through the characters when
  // possible and avoid using more expensive operations except when needed.
  final iterator = input.codeUnits.iterator;

  var index = 0;
  if (silentStart) {
    // skip the first character if it's a silent start
    iterator.moveNext();
    index++;
  } else if (PhoneticUtils.isVowelAt(input, 0)) {
    encoding.appendBoth($A);
    iterator.moveNext();
    index++;
  }

  while (iterator.moveNext() && !encoding.isMaxedOut()) {
    final currentChar = iterator.current;

    var advance = 1;
    switch (currentChar) {
      case $B:
        encoding.appendBoth($P);
        advance = PhoneticUtils.codeUnitAt(input, index + 1) == $B ? 2 : 1;
        break;
      case $Ccedil:
        encoding.appendBoth($S);
        break;
      case $C:
        advance = _encodeC(encoding, input, index);
        break;
      case $D:
        advance = _encodeD(encoding, input, index);
        break;
      case $F:
        encoding.appendBoth($F);
        advance = PhoneticUtils.codeUnitAt(input, index + 1) == $F ? 2 : 1;
        break;
      case $G:
        advance = _encodeG(encoding, input, index, slavoGermanic);
        break;
      case $H:
        advance = _encodeH(encoding, input, index);
        break;
      case $J:
        advance = _encodeJ(encoding, input, index, slavoGermanic);
        break;
      case $K:
        encoding.appendBoth($K);
        advance = PhoneticUtils.codeUnitAt(input, index + 1) == $K ? 2 : 1;
        break;
      case $L:
        advance = _encodeL(encoding, input, index);
        break;
      case $M:
        advance = _encodeM(encoding, input, index);
        break;
      case $N:
        encoding.appendBoth($N);
        advance = PhoneticUtils.codeUnitAt(input, index + 1) == $N ? 2 : 1;
        break;
      case $Ntilde:
        encoding.appendBoth($N);
        break;
      case $P:
        advance = _encodeP(encoding, input, index);
        break;
      case $Q:
        encoding.appendBoth($K);
        advance = PhoneticUtils.codeUnitAt(input, index + 1) == $Q ? 2 : 1;
        break;
      case $R:
        advance = _encodeR(encoding, input, index, slavoGermanic);
        break;
      case $S:
        advance = _encodeS(encoding, input, index, slavoGermanic);
        break;
      case $T:
        advance = _encodeT(encoding, input, index);
        break;
      case $V:
        encoding.appendBoth($F);
        advance = PhoneticUtils.codeUnitAt(input, index + 1) == $V ? 2 : 1;
        break;
      case $W:
        advance = _encodeW(encoding, input, index);
        break;
      case $X:
        advance = _encodeX(encoding, input, index);
        break;
      case $Z:
        advance = _encodeZ(encoding, input, index, slavoGermanic);
        break;
      default:
        break;
    }

    // move through more until we're at a standard advance
    while (advance-- > 1) {
      iterator.moveNext();
      index++;
    }

    index++;
  }

  final primary = encoding.primary;
  final alternate = encoding.alternate;
  return PhoneticEncoding(primary, {alternate});
}