# Source code for fontTools.encodings.codecs

    """Extend the Python codecs module with a few encodings that are used in OpenType (name table)
    but missing from Python.  See https://github.com/fonttools/fonttools/issues/236 for details."""

    import codecs
    import encodings

    class ExtendCodec(codecs.Codec):
        def __init__(self, name, base_encoding, mapping):
            self.name = name
            self.base_encoding = base_encoding
            self.mapping = mapping
            self.reverse = {v: k for k, v in mapping.items()}
            self.max_len = max(len(v) for v in mapping.values())
            self.info = codecs.CodecInfo(
                name=self.name, encode=self.encode, decode=self.decode
            )
            codecs.register_error(name, self.error)

        def _map(self, mapper, output_type, exc_type, input, errors):
            base_error_handler = codecs.lookup_error(errors)
            length = len(input)
            out = output_type()
            while input:
                # first try to use self.error as the error handler
                try:
                    part = mapper(input, self.base_encoding, errors=self.name)
                    out += part
                    break  # All converted
                except exc_type as e:
                    # else convert the correct part, handle error as requested and continue
                    out += mapper(input[: e.start], self.base_encoding, self.name)
                    replacement, pos = base_error_handler(e)
                    out += replacement
                    input = input[pos:]
            return out, length

        def encode(self, input, errors="strict"):
            return self._map(codecs.encode, bytes, UnicodeEncodeError, input, errors)

        def decode(self, input, errors="strict"):
            return self._map(codecs.decode, str, UnicodeDecodeError, input, errors)

        def error(self, e):
            if isinstance(e, UnicodeDecodeError):
                for end in range(e.start + 1, e.end + 1):
                    s = e.object[e.start : end]
                    if s in self.mapping:
                        return self.mapping[s], end
            elif isinstance(e, UnicodeEncodeError):
                for end in range(e.start + 1, e.start + self.max_len + 1):
                    s = e.object[e.start : end]
                    if s in self.reverse:
                        return self.reverse[s], end
            e.encoding = self.name
            raise e

    _extended_encodings = {
        "x_mac_japanese_ttx": (
            "shift_jis",
            {
                b"\xFC": chr(0x007C),
                b"\x7E": chr(0x007E),
                b"\x80": chr(0x005C),
                b"\xA0": chr(0x00A0),
                b"\xFD": chr(0x00A9),
                b"\xFE": chr(0x2122),
                b"\xFF": chr(0x2026),
            },
        ),
        "x_mac_trad_chinese_ttx": (
            "big5",
            {
                b"\x80": chr(0x005C),
                b"\xA0": chr(0x00A0),
                b"\xFD": chr(0x00A9),
                b"\xFE": chr(0x2122),
                b"\xFF": chr(0x2026),
            },
        ),
        "x_mac_korean_ttx": (
            "euc_kr",
            {
                b"\x80": chr(0x00A0),
                b"\x81": chr(0x20A9),
                b"\x82": chr(0x2014),
                b"\x83": chr(0x00A9),
                b"\xFE": chr(0x2122),
                b"\xFF": chr(0x2026),
            },
        ),
        "x_mac_simp_chinese_ttx": (
            "gb2312",
            {
                b"\x80": chr(0x00FC),
                b"\xA0": chr(0x00A0),
                b"\xFD": chr(0x00A9),
                b"\xFE": chr(0x2122),
                b"\xFF": chr(0x2026),
            },
        ),
    }

    _cache = {}

    def search_function(name):
        name = encodings.normalize_encoding(name)  # Rather undocumented...
        if name in _extended_encodings:
            if name not in _cache:
                base_encoding, mapping = _extended_encodings[name]
                assert name[-4:] == "_ttx"
                # Python 2 didn't have any of the encodings that we are implementing
                # in this file.  Python 3 added aliases for the East Asian ones, mapping
                # them "temporarily" to the same base encoding as us, with a comment
                # suggesting that full implementation will appear some time later.
                # As such, try the Python version of the x_mac_... first, if that is found,
                # use *that* as our base encoding.  This would make our encoding upgrade
                # to the full encoding when and if Python finally implements that.
                # http://bugs.python.org/issue24041
                base_encodings = [name[:-4], base_encoding]
                for base_encoding in base_encodings:
                    try:
                        codecs.lookup(base_encoding)
                    except LookupError:
                        continue
                    _cache[name] = ExtendCodec(name, base_encoding, mapping)
                    break
            return _cache[name].info

        return None

    codecs.register(search_function)