# -*- coding: utf-8 -*- # j2.py # # Copyright 2011-2021 Hiroshi Miura import functools import pickle import threading from typing import Tuple from .properties import Configurations class JConv: def __init__(self): self._kanwa = Kanwa() self._itaiji = Itaiji() def isRegion(self, c: str): return 0x3400 <= ord(c[0]) < 0xE000 or self._itaiji.haskey(ord(c[0])) @functools.lru_cache(maxsize=512) def convert(self, itext: str, btext: str) -> Tuple[str, int]: max_len = 0 Hstr = "" text = self._itaiji.convert(itext) num_vs = len(itext) - len(text) table = self._kanwa.load(text[0]) if table is None: return "", 0 for k, v in table.items(): length = len(k) if len(text) >= length: if text.startswith(k): for yomi, con in v: if con is None or btext in con: if max_len < length: Hstr = yomi max_len = length for _ in range(num_vs): # when converting string with kanji wit variation selector, calculate max_len again if max_len > len(itext): break elif text[max_len - 1] != itext[max_len - 1]: max_len += 1 elif max_len < num_vs + len(text) and max_len <= len(itext) and self._is_vschr(itext[max_len]): max_len += 1 else: pass return (Hstr, max_len) def _isCletter(self, literal: str, c: str) -> bool: if (0x3041 <= ord(c) <= 0x309F) and (literal in self._cl_table[ord(c) - 0x3040]): # ぁ:= u\3041 return True return False def _is_vschr(self, ch): return 0x0E0100 <= ord(ch) <= 0x0E1EF or 0xFE00 <= ord(ch) <= 0xFE02 class Itaiji: # this class is Borg/Singleton _shared_state = {"_itaijidict": None, "_lock": threading.Lock()} def __new__(cls, *p, **k): self = object.__new__(cls, *p, **k) self.__dict__ = cls._shared_state return self def __init__(self): if self._itaijidict is None: with self._lock: if self._itaijidict is None: itaijipath = Configurations.dictpath(Configurations.jisyo_itaiji) with open(itaijipath, "rb") as d: self._itaijidict = pickle.load(d) def haskey(self, c): return c in self._itaijidict def convert(self, text: str) -> str: return text.translate(self._itaijidict) # This class is Borg/Singleton # It provides same results becase lookup from a static dictionary. # There is no state rather dictionary dbm. class Kanwa: _shared_state = {"_lock": threading.Lock(), "_jisyo_table": None} def __new__(cls, *p, **k): self = object.__new__(cls, *p, **k) self.__dict__ = cls._shared_state return self def __init__(self): if self._jisyo_table is None: with self._lock: if self._jisyo_table is None: dictpath = Configurations.dictpath(Configurations.jisyo_kanwa) with open(dictpath, "rb") as d: self._jisyo_table = pickle.load(d) def load(self, char: str): key = ord(char[0]) return self._jisyo_table.get(key, None)