|
| 1 | +# -*- coding: UTF-8 -*- |
| 2 | +"""BCD Codec - Binary Coded Decimal content encoding. |
| 3 | +
|
| 4 | +This codec: |
| 5 | +- en/decodes strings from str to str |
| 6 | +- en/decodes strings from bytes to bytes |
| 7 | +- decodes file content to str (read) |
| 8 | +- encodes file content from str to bytes (write) |
| 9 | +""" |
| 10 | +from ..__common__ import * |
| 11 | + |
| 12 | + |
| 13 | +__examples1__ = { |
| 14 | + 'enc(bcd|binary-coded-decimal|binary_coded_decimal)': { |
| 15 | + 'This is a test!': "\x08A\x04\x10Q\x15\x03!\x05\x11P2\tp2\x11a\x01\x11Q\x16\x030", |
| 16 | + }, |
| 17 | + 'dec(binary-coded-decimal)': { |
| 18 | + '\xaf': None, |
| 19 | + '\xff': None, |
| 20 | + '\x08A\x04\x10Q\x15\x03!\x05\x11P2\tp2\x11a\x01\x11Q\x16\x030': "This is a test!", |
| 21 | + }, |
| 22 | +} |
| 23 | +__examples2__ = { |
| 24 | + 'enc(bcd-ext0|bcd_extended_zeros)': { |
| 25 | + 'This is a test': "\x00\x08\x04\x01\x00\x04\x01\x00\x05\x01\x01\x05\x00\x03\x02\x01\x00\x05\x01\x01\x05\x00" |
| 26 | + "\x03\x02\x00\t\x07\x00\x03\x02\x01\x01\x06\x01\x00\x01\x01\x01\x05\x01\x01\x06\x00", |
| 27 | + }, |
| 28 | +} |
| 29 | +__examples3__ = { |
| 30 | + 'enc(bcd-ext1|bcd_extended_ones)': { |
| 31 | + 'This is a test': "\xf0\xf8\xf4\xf1\xf0\xf4\xf1\xf0\xf5\xf1\xf1\xf5\xf0\xf3\xf2\xf1\xf0\xf5\xf1\xf1\xf5\xf0" |
| 32 | + "\xf3\xf2\xf0\xf9\xf7\xf0\xf3\xf2\xf1\xf1\xf6\xf1\xf0\xf1\xf1\xf1\xf5\xf1\xf1\xf6\xf0", |
| 33 | + }, |
| 34 | +} |
| 35 | + |
| 36 | + |
| 37 | +CODE = {str(i): bin(i)[2:].zfill(4) for i in range(10)} |
| 38 | + |
| 39 | + |
| 40 | +class BCDDecodeError(ValueError): |
| 41 | + pass |
| 42 | + |
| 43 | + |
| 44 | +def bcd_encode(prefix=""): |
| 45 | + def encode(text, errors="strict"): |
| 46 | + r, bits = "", prefix |
| 47 | + for c in text: |
| 48 | + for i in str(ord(c)).zfill(3): |
| 49 | + bits += CODE[i] |
| 50 | + if len(bits) == 8: |
| 51 | + r += chr(int(bits, 2)) |
| 52 | + bits = prefix |
| 53 | + if len(bits) > 0: |
| 54 | + r += chr(int(bits + "0000", 2)) |
| 55 | + return r, len(b(text)) |
| 56 | + return encode |
| 57 | + |
| 58 | + |
| 59 | +def bcd_decode(prefix=""): |
| 60 | + def decode(text, errors="strict"): |
| 61 | + code = {v: k for k, v in CODE.items()} |
| 62 | + r, d = "", "" |
| 63 | + for i, c in enumerate(text): |
| 64 | + bin_c = bin(ord(c))[2:].zfill(8) |
| 65 | + for k in range(len(prefix), 8, 4): |
| 66 | + hb = bin_c[k:k+4] |
| 67 | + try: |
| 68 | + d += code[hb] |
| 69 | + except KeyError: |
| 70 | + d += handle_error("bcd", errors, BCDDecodeError, decode=True)(hb, i) |
| 71 | + if len(d) == 3: |
| 72 | + r += chr(int(d)) |
| 73 | + d = "" |
| 74 | + return r, len(b(text)) |
| 75 | + return decode |
| 76 | + |
| 77 | + |
| 78 | +add("bcd", bcd_encode(), bcd_decode(), pattern=r"^(?:bcd|binary[-_]coded[-_]decimals?)$", examples=__examples1__) |
| 79 | +add("bcd-extended0", bcd_encode("0000"), bcd_decode("0000"), examples=__examples2__, |
| 80 | + pattern=r"^(?:bcd|binary[-_]coded[-_]decimals?)[-_]ext(?:ended)?(?:[-_]?0|[-_]zeros?)$") |
| 81 | +add("bcd-extended1", bcd_encode("1111"), bcd_decode("1111"), examples=__examples3__, |
| 82 | + pattern=r"^(?:bcd|binary[-_]coded[-_]decimals?)[-_]ext(?:ended)?(?:[-_]?1|[-_]ones?)$") |
| 83 | + |
0 commit comments