import 'dart:convert'; import 'dart:math'; import 'shift_jis_table.dart'; class ShiftJISDecoder extends Converter, String> { final bool _allowMalformed; const ShiftJISDecoder({bool allowMalformed = false}) : _allowMalformed = allowMalformed; @override convert(input) { List result = []; for (int i = 0; i < input.length; i++) { final c1 = input[i]; List? c2; if (c1 <= 0x7F) { // ASCII Compatible (partially) c2 = JIS_TABLE[c1]; } else if (c1 >= 0xa1 && c1 <= 0xdf) { // Half-width Hiragana c2 = JIS_TABLE[c1]; } else if (c1 >= 0x81 && c1 <= 0x9f) { // JIS X 0208 c2 = JIS_TABLE[(c1 << 8) + input[++i]]; } else if (c1 >= 0xe0 && c1 <= 0xef) { // JIS X 0208 c2 = JIS_TABLE[(c1 << 8) + input[++i]]; } else { // Unknown } if (c2 != null) { result.addAll(c2); } else if (_allowMalformed) { result.add(unicodeReplacementCharacterRune); } else { throw FormatException('Unfinished Shift-JIS octet sequence', input, i); } } return utf8.decode(result, allowMalformed: _allowMalformed); } } class ShiftJISEncoder extends Converter> { const ShiftJISEncoder(); @override List convert(String input) { List result = []; for (int i = 0; i < input.length; i++) { var bytes = utf8.encode(input[i]); var value = 0; for (var i = 0, length = bytes.length; i < length; i++) { value += bytes[i] * (pow(256, (bytes.length - i - 1)) as int); } result.addAll(UTF_TABLE[value] ?? [0xFFFD]); } return result; } } class ShiftJISCodec extends Encoding { final bool _allowMalformed; const ShiftJISCodec({bool allowMalformed = false}) : _allowMalformed = allowMalformed; @override Converter, String> get decoder => _allowMalformed ? const ShiftJISDecoder(allowMalformed: true) : const ShiftJISDecoder(allowMalformed: false); @override Converter> get encoder => const ShiftJISEncoder(); @override String get name => 'shift-jis'; } const shiftJis = ShiftJISCodec();