sanitizeForLog function
Rewrites U+FFFD (the replacement character) and unpaired UTF-16 surrogates
to the literal text U+FFFD.
Both encode to the bytes 0xEF 0xBF 0xBD on stdout, which flutter run's
reader treats as malformed output and aborts on (issue #306). A lone
surrogate appears when a substring/chunk boundary splits an emoji or other
astral character mid-pair.
Implementation
String sanitizeForLog(String text) {
var needsWork = false;
for (var i = 0; i < text.length; i++) {
final u = text.codeUnitAt(i);
if (u == 0xFFFD || (u >= 0xD800 && u <= 0xDFFF)) {
needsWork = true;
break;
}
}
if (!needsWork) return text;
final out = StringBuffer();
for (var i = 0; i < text.length; i++) {
final u = text.codeUnitAt(i);
if (u == 0xFFFD) {
out.write('U+FFFD');
} else if (u >= 0xD800 && u <= 0xDBFF) {
final hasLow = i + 1 < text.length &&
text.codeUnitAt(i + 1) >= 0xDC00 &&
text.codeUnitAt(i + 1) <= 0xDFFF;
if (hasLow) {
out.writeCharCode(u);
out.writeCharCode(text.codeUnitAt(i + 1));
i++;
} else {
out.write('U+FFFD');
}
} else if (u >= 0xDC00 && u <= 0xDFFF) {
out.write('U+FFFD');
} else {
out.writeCharCode(u);
}
}
return out.toString();
}