diff --git a/example/enough_convert_example.dart b/example/enough_convert_example.dart index d886925..4af8d62 100644 --- a/example/enough_convert_example.dart +++ b/example/enough_convert_example.dart @@ -20,6 +20,8 @@ void main() { windows1250(); windows1251(); windows1252(); + windows1253(); + windows1254(); gbk(); } @@ -102,6 +104,16 @@ void windows1252() { 'Il faut être bête quand même.'); } +void windows1253() { + roundtrip( + const Windows1253Codec(allowInvalid: false), 'Χαίρομαι που σας γνωρίζω!'); +} + +void windows1254() { + roundtrip(const Windows1254Codec(allowInvalid: false), + 'Tanıştığımıza memnun oldum!'); +} + void gbk() { roundtrip(const GbkCodec(allowInvalid: false), '白日依山尽,黄河入海流'); } diff --git a/lib/enough_convert.dart b/lib/enough_convert.dart index 2636d63..cd7e43d 100644 --- a/lib/enough_convert.dart +++ b/lib/enough_convert.dart @@ -21,4 +21,6 @@ export 'windows/windows.dart'; export 'windows/windows1250.dart'; export 'windows/windows1251.dart'; export 'windows/windows1252.dart'; +export 'windows/windows1253.dart'; +export 'windows/windows1254.dart'; export 'gbk/gbk.dart'; diff --git a/lib/windows/windows1253.dart b/lib/windows/windows1253.dart new file mode 100644 index 0000000..18544a6 --- /dev/null +++ b/lib/windows/windows1253.dart @@ -0,0 +1,162 @@ +import 'dart:convert' as cnvrt; + +import 'package:enough_convert/windows/windows.dart'; + +const String _cp1253Symbols = + '€?‚ƒ„…†‡?‰?‹?????‘’“”•–—?™?›????\u{00A0}΅Ά£¤¥¦§¨©?«¬\u{00AD}®―°±²³΄µ¶·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ?ΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ?'; +const Map _cp1253Map = { + 8364: 128, + 8218: 130, + 402: 131, + 8222: 132, + 8230: 133, + 8224: 134, + 8225: 135, + 8240: 137, + 8249: 139, + 8216: 145, + 8217: 146, + 8220: 147, + 8221: 148, + 8226: 149, + 8211: 150, + 8212: 151, + 8482: 153, + 8250: 155, + 160: 160, + 901: 161, + 902: 162, + 163: 163, + 164: 164, + 165: 165, + 166: 166, + 167: 167, + 168: 168, + 169: 169, + 171: 171, + 172: 172, + 173: 173, + 174: 174, + 8213: 175, + 176: 176, + 177: 177, + 178: 178, + 179: 179, + 900: 180, + 181: 181, + 182: 182, + 183: 183, + 904: 184, + 905: 185, + 906: 186, + 187: 187, + 908: 188, + 189: 189, + 910: 190, + 911: 191, + 912: 192, + 913: 193, + 914: 194, + 915: 195, + 916: 196, + 917: 197, + 918: 198, + 919: 199, + 920: 200, + 921: 201, + 922: 202, + 923: 203, + 924: 204, + 925: 205, + 926: 206, + 927: 207, + 928: 208, + 929: 209, + 931: 211, + 932: 212, + 933: 213, + 934: 214, + 935: 215, + 936: 216, + 937: 217, + 938: 218, + 939: 219, + 940: 220, + 941: 221, + 942: 222, + 943: 223, + 944: 224, + 945: 225, + 946: 226, + 947: 227, + 948: 228, + 949: 229, + 950: 230, + 951: 231, + 952: 232, + 953: 233, + 954: 234, + 955: 235, + 956: 236, + 957: 237, + 958: 238, + 959: 239, + 960: 240, + 961: 241, + 962: 242, + 963: 243, + 964: 244, + 965: 245, + 966: 246, + 967: 247, + 968: 248, + 969: 249, + 970: 250, + 971: 251, + 972: 252, + 973: 253, + 974: 254, +}; + +/// Provides a windows 1253 / cp1253 codec for easy encoding and decoding. +class Windows1253Codec extends cnvrt.Encoding { + final bool allowInvalid; + + /// Creates a new codec + const Windows1253Codec({ + /// set [allowInvalid] to `true` for ignoring invalid data. + /// When invalid data is allowed it will be encoded to ? and decoded to � + this.allowInvalid = false, + }); + + @override + Windows1253Decoder get decoder => allowInvalid + ? const Windows1253Decoder(allowInvalid: true) + : const Windows1253Decoder(allowInvalid: false); + + @override + Windows1253Encoder get encoder => allowInvalid + ? const Windows1253Encoder(allowInvalid: true) + : const Windows1253Encoder(allowInvalid: false); + + @override + String get name => 'windows-1253'; +} + +/// Decodes windows 1253 / cp1253 data. +class Windows1253Decoder extends WindowsDecoder { + const Windows1253Decoder({ + /// set [allowInvalid] to `true` for ignoring invalid data. + /// When invalid data is allowed it will be decoded to � + bool allowInvalid = false, + }) : super(_cp1253Symbols, allowInvalid: allowInvalid); +} + +/// Encodes texts into windows 1253 data +class Windows1253Encoder extends WindowsEncoder { + const Windows1253Encoder({ + /// set [allowInvalid] to `true` for ignoring invalid data. + /// When invalid data is allowed it will be encoded to ? + bool allowInvalid = false, + }) : super(_cp1253Map, allowInvalid: allowInvalid); +} diff --git a/lib/windows/windows1254.dart b/lib/windows/windows1254.dart new file mode 100644 index 0000000..813d7a5 --- /dev/null +++ b/lib/windows/windows1254.dart @@ -0,0 +1,172 @@ +import 'dart:convert' as cnvrt; + +import 'package:enough_convert/windows/windows.dart'; + +const String _cp1254Symbols = + '€?‚ƒ„…†‡ˆ‰Š‹Œ????‘’“”•–—˜™š›œ??Ÿ\u{00A0}¡¢£¤¥¦§¨©ª«¬\u{00AD}®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖ×ØÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ'; +const Map _cp1254Map = { + 8364: 128, + 8218: 130, + 402: 131, + 8222: 132, + 8230: 133, + 8224: 134, + 8225: 135, + 710: 136, + 8240: 137, + 352: 138, + 8249: 139, + 338: 140, + 8216: 145, + 8217: 146, + 8220: 147, + 8221: 148, + 8226: 149, + 8211: 150, + 8212: 151, + 732: 152, + 8482: 153, + 353: 154, + 8250: 155, + 339: 156, + 376: 159, + 160: 160, + 161: 161, + 162: 162, + 163: 163, + 164: 164, + 165: 165, + 166: 166, + 167: 167, + 168: 168, + 169: 169, + 170: 170, + 171: 171, + 172: 172, + 173: 173, + 174: 174, + 175: 175, + 176: 176, + 177: 177, + 178: 178, + 179: 179, + 180: 180, + 181: 181, + 182: 182, + 183: 183, + 184: 184, + 185: 185, + 186: 186, + 187: 187, + 188: 188, + 189: 189, + 190: 190, + 191: 191, + 192: 192, + 193: 193, + 194: 194, + 195: 195, + 196: 196, + 197: 197, + 198: 198, + 199: 199, + 200: 200, + 201: 201, + 202: 202, + 203: 203, + 204: 204, + 205: 205, + 206: 206, + 207: 207, + 286: 208, + 209: 209, + 210: 210, + 211: 211, + 212: 212, + 213: 213, + 214: 214, + 215: 215, + 216: 216, + 217: 217, + 218: 218, + 219: 219, + 220: 220, + 304: 221, + 350: 222, + 223: 223, + 224: 224, + 225: 225, + 226: 226, + 227: 227, + 228: 228, + 229: 229, + 230: 230, + 231: 231, + 232: 232, + 233: 233, + 234: 234, + 235: 235, + 236: 236, + 237: 237, + 238: 238, + 239: 239, + 287: 240, + 241: 241, + 242: 242, + 243: 243, + 244: 244, + 245: 245, + 246: 246, + 247: 247, + 248: 248, + 249: 249, + 250: 250, + 251: 251, + 252: 252, + 305: 253, + 351: 254, + 255: 255, +}; + +/// Provides a windows 1254 / cp1254 codec for easy encoding and decoding. +class Windows1254Codec extends cnvrt.Encoding { + final bool allowInvalid; + + /// Creates a new codec + const Windows1254Codec({ + /// set [allowInvalid] to `true` for ignoring invalid data. + /// When invalid data is allowed it will be encoded to ? and decoded to � + this.allowInvalid = false, + }); + + @override + Windows1254Decoder get decoder => allowInvalid + ? const Windows1254Decoder(allowInvalid: true) + : const Windows1254Decoder(allowInvalid: false); + + @override + Windows1254Encoder get encoder => allowInvalid + ? const Windows1254Encoder(allowInvalid: true) + : const Windows1254Encoder(allowInvalid: false); + + @override + String get name => 'windows-1254'; +} + +/// Decodes windows 1254 / cp1254 data. +class Windows1254Decoder extends WindowsDecoder { + const Windows1254Decoder({ + /// set [allowInvalid] to `true` for ignoring invalid data. + /// When invalid data is allowed it will be decoded to � + bool allowInvalid = false, + }) : super(_cp1254Symbols, allowInvalid: allowInvalid); +} + +/// Encodes texts into windows 1254 data +class Windows1254Encoder extends WindowsEncoder { + const Windows1254Encoder({ + /// set [allowInvalid] to `true` for ignoring invalid data. + /// When invalid data is allowed it will be encoded to ? + bool allowInvalid = false, + }) : super(_cp1254Map, allowInvalid: allowInvalid); +} diff --git a/test/windows/windows1253_test.dart b/test/windows/windows1253_test.dart new file mode 100644 index 0000000..3388ae6 --- /dev/null +++ b/test/windows/windows1253_test.dart @@ -0,0 +1,87 @@ +import 'dart:convert' as convert; + +// import 'package:enough_convert/base.dart'; +import 'package:enough_convert/windows/windows1253.dart'; +import 'package:test/test.dart'; + +void main() { + group('Codec tests', () { + test('name', () { + expect(Windows1253Codec().name, 'windows-1253'); + // BaseEncoder.createEncodingMap(Windows1253Decoder().symbols, 0x7f); + }); + test('Decoder/encoder classes', () { + expect(Windows1253Codec().encoder, isA()); + expect(Windows1253Codec().decoder, isA()); + }); + }); + + group('Decoder tests', () { + test('Decode ascii', () { + final bytes = convert.ascii.encode('hello world'); + expect(Windows1253Decoder().convert(bytes), 'hello world'); + }); + + test('Decode Windows1253', () { + expect(Windows1253Decoder().convert([0xC4, 0xD6, 0xFC]), 'ΔΦό'); + final bytes = Windows1253Encoder().convert('Χαίρομαι που σας γνωρίζω!'); + expect(Windows1253Decoder().convert(bytes), 'Χαίρομαι που σας γνωρίζω!'); + }); + + test('Decode Windows1253 with invalid value when invalid input is allowed', + () { + expect( + Windows1253Decoder(allowInvalid: true) + .convert([0xC4, 0xD6, 0xFC, 0xFF1]), + 'ΔΦό�'); + }); + + test( + 'Decode Windows1253 with invalid value when invalid input is not allowed', + () { + expect(() => Windows1253Decoder().convert([0xC4, 0xD6, 0xFC, 0xFF1]), + throwsA(isA())); + }); + }); + + group('Encoder tests', () { + test('encode ascii', () { + final bytes = Windows1253Encoder().convert('hello world'); + expect(bytes, convert.latin1.encode('hello world')); + }); + + test('encode Windows1253', () { + var bytes = Windows1253Encoder().convert('ΔΦό'); + expect(bytes, [0xC4, 0xD6, 0xFC]); + bytes = Windows1253Encoder().convert('Χαίρομαι που σας γνωρίζω!'); + expect(bytes.any((element) => element > 0xFF), false); + }); + + test('encode more Windows1253', () { + final encoder = Windows1253Encoder(); + final decoder = Windows1253Decoder(); + var bytes = encoder.convert(decoder.symbols); + var expected = List.generate(0xFF - 0x7F, (index) => index + 0x80); + for (var i = 0; i < decoder.symbols.length; i++) { + if (decoder.symbols.codeUnitAt(i) == 0x3F) { + // ? + expected[i] = 0x3F; + } + } + expect(bytes, expected); + }); + + test('encode Windows1253 with invalid value when invalid input is allowed', + () { + var bytes = Windows1253Encoder(allowInvalid: true).convert('ΔΦό�'); + expect(Windows1253Decoder().convert(bytes), 'ΔΦό?'); + }); + + test( + 'encode Windows1253 with invalid value when invalid input is not allowed', + () { + expect(() => Windows1253Encoder().convert('ΔΦό�'), + throwsA(isA())); + }); + }); +} diff --git a/test/windows/windows1254_test.dart b/test/windows/windows1254_test.dart new file mode 100644 index 0000000..21a2b49 --- /dev/null +++ b/test/windows/windows1254_test.dart @@ -0,0 +1,88 @@ +import 'dart:convert' as convert; + +// import 'package:enough_convert/base.dart'; +import 'package:enough_convert/windows/windows1254.dart'; +import 'package:test/test.dart'; + +void main() { + group('Codec tests', () { + test('name', () { + expect(Windows1254Codec().name, 'windows-1254'); + // BaseEncoder.createEncodingMap(Windows1254Decoder().symbols, 0x7f); + }); + test('Decoder/encoder classes', () { + expect(Windows1254Codec().encoder, isA()); + expect(Windows1254Codec().decoder, isA()); + }); + }); + + group('Decoder tests', () { + test('Decode ascii', () { + final bytes = convert.ascii.encode('hello world'); + expect(Windows1254Decoder().convert(bytes), 'hello world'); + }); + + test('Decode Windows1254', () { + expect(Windows1254Decoder().convert([0xC4, 0xD6, 0xFC]), 'ÄÖü'); + final bytes = Windows1254Encoder().convert('Tanıştığımıza memnun oldum!'); + expect( + Windows1254Decoder().convert(bytes), 'Tanıştığımıza memnun oldum!'); + }); + + test('Decode Windows1254 with invalid value when invalid input is allowed', + () { + expect( + Windows1254Decoder(allowInvalid: true) + .convert([0xC4, 0xD6, 0xFC, 0xFF1]), + 'ÄÖü�'); + }); + + test( + 'Decode Windows1254 with invalid value when invalid input is not allowed', + () { + expect(() => Windows1254Decoder().convert([0xC4, 0xD6, 0xFC, 0xFF1]), + throwsA(isA())); + }); + }); + + group('Encoder tests', () { + test('encode ascii', () { + final bytes = Windows1254Encoder().convert('hello world'); + expect(bytes, convert.latin1.encode('hello world')); + }); + + test('encode Windows1254', () { + var bytes = Windows1254Encoder().convert('ÄÖü'); + expect(bytes, [0xC4, 0xD6, 0xFC]); + bytes = Windows1254Encoder().convert('Tanıştığımıza memnun oldum!'); + expect(bytes.any((element) => element > 0xFF), false); + }); + + test('encode more Windows1254 ', () { + final encoder = Windows1254Encoder(); + final decoder = Windows1254Decoder(); + var bytes = encoder.convert(decoder.symbols); + var expected = List.generate(0xFF - 0x7F, (index) => index + 0x80); + for (var i = 0; i < decoder.symbols.length; i++) { + if (decoder.symbols.codeUnitAt(i) == 0x3F) { + // ? + expected[i] = 0x3F; + } + } + expect(bytes, expected); + }); + + test('encode Windows1254 with invalid value when invalid input is allowed', + () { + var bytes = Windows1254Encoder(allowInvalid: true).convert('ÄÖü�'); + expect(Windows1254Decoder().convert(bytes), 'ÄÖü?'); + }); + + test( + 'encode Windows1254 with invalid value when invalid input is not allowed', + () { + expect(() => Windows1254Encoder().convert('ÄÖü�'), + throwsA(isA())); + }); + }); +}