fixOcrBeforeNatOnly function

String fixOcrBeforeNatOnly(
  1. String input,
  2. String natOnly
)

Implementation

String fixOcrBeforeNatOnly(String input, String natOnly) {
  if (natOnly.isEmpty) return input;

  const Map<String, String> map = {'O': '0', 'Q': '0', 'D': '0', 'I': '1', 'L': '1', 'Z': '2', 'S': '5', 'B': '8', 'G': '6', 'T': '7'};

  bool isTokenChar(int codeUnit) {
    final c = String.fromCharCode(codeUnit);
    final isAZ = codeUnit >= 65 && codeUnit <= 90;
    final is09 = codeUnit >= 48 && codeUnit <= 57;
    return isAZ || is09 || c == '<';
  }

  String replaceInToken(String token) {
    final sb = StringBuffer();
    for (var i = 0; i < token.length; i++) {
      final ch = token[i];
      sb.write(map[ch] ?? ch);
    }
    return sb.toString();
  }

  final upper = input.toUpperCase();
  final sb = StringBuffer();

  int searchFrom = 0;
  while (true) {
    final idx = upper.indexOf(natOnly, searchFrom);
    if (idx == -1) {
      sb.write(upper.substring(searchFrom));
      break;
    }

    int tokenEnd = idx;
    int tokenStart = tokenEnd;
    while (tokenStart > 0 && isTokenChar(upper.codeUnitAt(tokenStart - 1))) {
      tokenStart--;
    }

    sb.write(upper.substring(searchFrom, tokenStart));
    final token = upper.substring(tokenStart, tokenEnd);
    sb.write(replaceInToken(token));
    sb.write(natOnly);

    searchFrom = idx + natOnly.length;
  }

  return sb.toString();
}