From de1710b85691836c0ad0a7310e70fcb6169721d2 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 10 Dec 2022 12:25:54 +0800 Subject: [PATCH] LMAssembly // Introduce LMRevLookup. - This module is not supposed to be binded to LMInstantiator. Instead, use it when calling the reverse lookup window, and throw it after the window closes. --- .../SubLMs/lmRevLookup.swift | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/SubLMs/lmRevLookup.swift diff --git a/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/SubLMs/lmRevLookup.swift b/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/SubLMs/lmRevLookup.swift new file mode 100644 index 00000000..86642375 --- /dev/null +++ b/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/SubLMs/lmRevLookup.swift @@ -0,0 +1,68 @@ +// (c) 2021 and onwards The vChewing Project (MIT-NTL License). +// ==================== +// This code is released under the MIT license (SPDX-License-Identifier: MIT) +// ... with NTL restriction stating that: +// No trademark license is granted to use the trade names, trademarks, service +// marks, or product names of Contributor, except as required to fulfill notice +// requirements defined in MIT License. + +import Foundation +import Shared + +extension vChewingLM { + @frozen public struct LMRevLookup { + public private(set) var dataMap: [String: [Data]] = [:] + public private(set) var filePath: String = "" + + public init(dataMap: [String: [Data]]) { + self.dataMap = dataMap + } + + public init(path: String) { + if path.isEmpty { return } + do { + let rawData = try Data(contentsOf: URL(fileURLWithPath: path)) + let rawPlist: [String: [Data]] = + try PropertyListSerialization.propertyList(from: rawData, format: nil) as? [String: [Data]] ?? .init() + dataMap = rawPlist + } catch { + vCLog("↑ Exception happened when reading plist file at: \(path).") + return + } + filePath = path + } + + public func query(with kanji: String) -> [String]? { + guard let resultData = dataMap[kanji] else { return nil } + let resultArray = resultData.compactMap { + let result = restorePhonabetFromASCII(String(decoding: $0, as: UTF8.self)) + return result.isEmpty ? nil : result + } + return resultArray.isEmpty ? nil : resultArray + } + + /// 內部函式,用以將被加密的注音讀音索引鍵進行解密。 + /// + /// 如果傳入的字串當中包含 ASCII 下畫線符號的話,則表明該字串並非注音讀音字串,會被忽略處理。 + /// - parameters: + /// - incoming: 傳入的已加密注音讀音字串。 + func restorePhonabetFromASCII(_ incoming: String) -> String { + var strOutput = incoming + if !strOutput.contains("_") { + for entry in Self.dicPhonabet4ASCII { + strOutput = strOutput.replacingOccurrences(of: entry.key, with: entry.value) + } + } + return strOutput + } + + // MARK: - Constants + + static let dicPhonabet4ASCII: [String: String] = [ + "b": "ㄅ", "p": "ㄆ", "m": "ㄇ", "f": "ㄈ", "d": "ㄉ", "t": "ㄊ", "n": "ㄋ", "l": "ㄌ", "g": "ㄍ", "k": "ㄎ", "h": "ㄏ", + "j": "ㄐ", "q": "ㄑ", "x": "ㄒ", "Z": "ㄓ", "C": "ㄔ", "S": "ㄕ", "r": "ㄖ", "z": "ㄗ", "c": "ㄘ", "s": "ㄙ", "i": "ㄧ", + "u": "ㄨ", "v": "ㄩ", "a": "ㄚ", "o": "ㄛ", "e": "ㄜ", "E": "ㄝ", "B": "ㄞ", "P": "ㄟ", "M": "ㄠ", "F": "ㄡ", "D": "ㄢ", + "T": "ㄣ", "N": "ㄤ", "L": "ㄥ", "R": "ㄦ", "2": "ˊ", "3": "ˇ", "4": "ˋ", "5": "˙", + ] + } +}