mgrLM // Complete Swiftification.

This commit is contained in:
ShikiSuen 2022-04-27 00:10:47 +08:00
parent 887907fb11
commit a29d1635e9
4 changed files with 153 additions and 280 deletions

View File

@ -1,53 +1 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
/*
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
1. The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
2. 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 above.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import "KeyHandler.h"
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface mgrLangModel : NSObject
+ (void)loadDataModel:(InputMode)mode;
+ (void)loadUserPhrases;
+ (void)loadUserAssociatedPhrases;
+ (void)loadUserPhraseReplacement;
+ (BOOL)checkIfUserPhraseExist:(NSString *)userPhrase
inputMode:(InputMode)mode
key:(NSString *)key NS_SWIFT_NAME(checkIfUserPhraseExist(userPhrase:mode:key:));
+ (void)setPhraseReplacementEnabled:(BOOL)phraseReplacementEnabled;
+ (void)setCNSEnabled:(BOOL)cnsEnabled;
+ (void)setSymbolEnabled:(BOOL)symbolEnabled;
@end
/// The following methods are merely for testing.
@interface mgrLangModel ()
+ (void)loadDataModels;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,189 +1 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
/*
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
1. The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
2. 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 above.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import "mgrLangModel.h"
#import "LMConsolidator.h"
#import "mgrLangModel_Privates.h"
#import "vChewing-Swift.h"
static const int kUserOverrideModelCapacity = 500;
static const double kObservedOverrideHalflife = 5400.0;
static vChewing::LMInstantiator gLangModelCHT;
static vChewing::LMInstantiator gLangModelCHS;
static vChewing::UserOverrideModel gUserOverrideModelCHT(kUserOverrideModelCapacity, kObservedOverrideHalflife);
static vChewing::UserOverrideModel gUserOverrideModelCHS(kUserOverrideModelCapacity, kObservedOverrideHalflife);
@implementation mgrLangModel
// 這個函數無法遷移至 Swift
static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing::LMInstantiator &lm)
{
NSString *dataPath = [mgrLangModel getBundleDataPath:filenameWithoutExtension];
lm.loadLanguageModel([dataPath UTF8String]);
}
// 這個函數無法遷移至 Swift
+ (void)loadDataModels
{
if (!gLangModelCHT.isDataModelLoaded())
LTLoadLanguageModelFile(@"data-cht", gLangModelCHT);
if (!gLangModelCHT.isMiscDataLoaded())
gLangModelCHT.loadMiscData([[self getBundleDataPath:@"data-zhuyinwen"] UTF8String]);
if (!gLangModelCHT.isSymbolDataLoaded())
gLangModelCHT.loadSymbolData([[self getBundleDataPath:@"data-symbols"] UTF8String]);
if (!gLangModelCHT.isCNSDataLoaded())
gLangModelCHT.loadCNSData([[self getBundleDataPath:@"char-kanji-cns"] UTF8String]);
// -----------------
if (!gLangModelCHS.isDataModelLoaded())
LTLoadLanguageModelFile(@"data-chs", gLangModelCHS);
if (!gLangModelCHS.isMiscDataLoaded())
gLangModelCHS.loadMiscData([[self getBundleDataPath:@"data-zhuyinwen"] UTF8String]);
if (!gLangModelCHS.isSymbolDataLoaded())
gLangModelCHS.loadSymbolData([[self getBundleDataPath:@"data-symbols"] UTF8String]);
if (!gLangModelCHS.isCNSDataLoaded())
gLangModelCHS.loadCNSData([[self getBundleDataPath:@"char-kanji-cns"] UTF8String]);
}
// 這個函數無法遷移至 Swift
+ (void)loadDataModel:(InputMode)mode
{
if ([mode isEqualToString:imeModeCHT])
{
if (!gLangModelCHT.isDataModelLoaded())
LTLoadLanguageModelFile(@"data-cht", gLangModelCHT);
if (!gLangModelCHT.isMiscDataLoaded())
gLangModelCHT.loadMiscData([[self getBundleDataPath:@"data-zhuyinwen"] UTF8String]);
if (!gLangModelCHT.isSymbolDataLoaded())
gLangModelCHT.loadSymbolData([[self getBundleDataPath:@"data-symbols"] UTF8String]);
if (!gLangModelCHT.isCNSDataLoaded())
gLangModelCHT.loadCNSData([[self getBundleDataPath:@"char-kanji-cns"] UTF8String]);
}
if ([mode isEqualToString:imeModeCHS])
{
if (!gLangModelCHS.isDataModelLoaded())
LTLoadLanguageModelFile(@"data-chs", gLangModelCHS);
if (!gLangModelCHS.isMiscDataLoaded())
gLangModelCHS.loadMiscData([[self getBundleDataPath:@"data-zhuyinwen"] UTF8String]);
if (!gLangModelCHS.isSymbolDataLoaded())
gLangModelCHS.loadSymbolData([[self getBundleDataPath:@"data-symbols"] UTF8String]);
if (!gLangModelCHS.isCNSDataLoaded())
gLangModelCHS.loadCNSData([[self getBundleDataPath:@"char-kanji-cns"] UTF8String]);
}
}
// 這個函數無法遷移至 Swift
+ (void)loadUserPhrases
{
gLangModelCHT.loadUserPhrases([[self userPhrasesDataPath:imeModeCHT] UTF8String],
[[self excludedPhrasesDataPath:imeModeCHT] UTF8String]);
gLangModelCHS.loadUserPhrases([[self userPhrasesDataPath:imeModeCHS] UTF8String],
[[self excludedPhrasesDataPath:imeModeCHS] UTF8String]);
gLangModelCHT.loadUserSymbolData([[self userSymbolDataPath:imeModeCHT] UTF8String]);
gLangModelCHS.loadUserSymbolData([[self userSymbolDataPath:imeModeCHS] UTF8String]);
}
// 這個函數無法遷移至 Swift
+ (void)loadUserAssociatedPhrases
{
gLangModelCHT.loadUserAssociatedPhrases([[self userAssociatedPhrasesDataPath:imeModeCHT] UTF8String]);
gLangModelCHS.loadUserAssociatedPhrases([[self userAssociatedPhrasesDataPath:imeModeCHS] UTF8String]);
}
// 這個函數無法遷移至 Swift
+ (void)loadUserPhraseReplacement
{
gLangModelCHT.loadPhraseReplacementMap([[self phraseReplacementDataPath:imeModeCHT] UTF8String]);
gLangModelCHS.loadPhraseReplacementMap([[self phraseReplacementDataPath:imeModeCHS] UTF8String]);
}
// 這個函數無法遷移至 Swift
+ (BOOL)checkIfUserPhraseExist:(NSString *)userPhrase
inputMode:(InputMode)mode
key:(NSString *)key NS_SWIFT_NAME(checkIfUserPhraseExist(userPhrase:mode:key:))
{
string unigramKey = string(key.UTF8String);
vector<vChewing::Unigram> unigrams = [mode isEqualToString:imeModeCHT] ? gLangModelCHT.unigramsForKey(unigramKey)
: gLangModelCHS.unigramsForKey(unigramKey);
string userPhraseString = string(userPhrase.UTF8String);
for (auto unigram : unigrams)
{
if (unigram.keyValue.value == userPhraseString)
{
return YES;
}
}
return NO;
}
// 這個函數無法遷移至 Swift
+ (vChewing::LMInstantiator *)lmCHT
{
return &gLangModelCHT;
}
// 這個函數無法遷移至 Swift
+ (vChewing::LMInstantiator *)lmCHS
{
return &gLangModelCHS;
}
// 這個函數無法遷移至 Swift
+ (vChewing::UserOverrideModel *)userOverrideModelCHT
{
return &gUserOverrideModelCHT;
}
// 這個函數無法遷移至 Swift
+ (vChewing::UserOverrideModel *)userOverrideModelCHS
{
return &gUserOverrideModelCHS;
}
// 這個函數無法遷移至 Swift
+ (void)setPhraseReplacementEnabled:(BOOL)phraseReplacementEnabled
{
gLangModelCHT.setPhraseReplacementEnabled(phraseReplacementEnabled);
gLangModelCHS.setPhraseReplacementEnabled(phraseReplacementEnabled);
}
// 這個函數無法遷移至 Swift
+ (void)setCNSEnabled:(BOOL)cnsEnabled
{
gLangModelCHT.setCNSEnabled(cnsEnabled);
gLangModelCHS.setCNSEnabled(cnsEnabled);
}
// 這個函數無法遷移至 Swift
+ (void)setSymbolEnabled:(BOOL)symbolEnabled
{
gLangModelCHT.setSymbolEnabled(symbolEnabled);
gLangModelCHS.setSymbolEnabled(symbolEnabled);
}
@end

View File

@ -25,8 +25,160 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
import Cocoa import Cocoa
import Megrez
/// mgrLangModel
/// mgrLangModel
///
/// mgrLangModel
private let kUserOverrideModelCapacity: Int = 500
private let kObservedOverrideHalflife: Double = 5400.0
private var gLangModelCHS = vChewing.LMInstantiator()
private var gLangModelCHT = vChewing.LMInstantiator()
private var gUserOverrideModelCHS = vChewing.LMUserOverride(
capacity: kUserOverrideModelCapacity, decayExponent: kObservedOverrideHalflife
)
private var gUserOverrideModelCHT = vChewing.LMUserOverride(
capacity: kUserOverrideModelCapacity, decayExponent: kObservedOverrideHalflife
)
@objc class mgrLangModel: NSObject {
/// fileprivate
public static var lmCHS: vChewing.LMInstantiator { gLangModelCHS }
public static var lmCHT: vChewing.LMInstantiator { gLangModelCHT }
public static var uomCHS: vChewing.LMUserOverride { gUserOverrideModelCHS }
public static var uomCHT: vChewing.LMUserOverride { gUserOverrideModelCHT }
// MARK: - Functions reacting directly with language models.
static func loadCoreLanguageModelFile(filenameSansExtension: String, langModel lm: inout vChewing.LMInstantiator) {
let dataPath: String = mgrLangModel.getBundleDataPath(filenameSansExtension)
lm.loadLanguageModel(path: dataPath)
}
public static func loadDataModels() {
if !gLangModelCHT.isDataModelLoaded() {
loadCoreLanguageModelFile(filenameSansExtension: "data-cht", langModel: &gLangModelCHT)
}
if !gLangModelCHT.isMiscDataLoaded() {
gLangModelCHT.loadMiscData(path: getBundleDataPath("data-zhuyinwen"))
}
if !gLangModelCHT.isSymbolDataLoaded() {
gLangModelCHT.loadSymbolData(path: getBundleDataPath("data-symbols"))
}
if !gLangModelCHT.isCNSDataLoaded() {
gLangModelCHT.loadCNSData(path: getBundleDataPath("char-kanji-cns"))
}
// -----------------
if !gLangModelCHS.isDataModelLoaded() {
loadCoreLanguageModelFile(filenameSansExtension: "data-chs", langModel: &gLangModelCHS)
}
if !gLangModelCHS.isMiscDataLoaded() {
gLangModelCHS.loadMiscData(path: getBundleDataPath("data-zhuyinwen"))
}
if !gLangModelCHS.isSymbolDataLoaded() {
gLangModelCHS.loadSymbolData(path: getBundleDataPath("data-symbols"))
}
if !gLangModelCHS.isCNSDataLoaded() {
gLangModelCHS.loadCNSData(path: getBundleDataPath("char-kanji-cns"))
}
}
public static func loadDataModel(_ mode: InputMode) {
if mode == InputMode.imeModeCHS {
if !gLangModelCHS.isDataModelLoaded() {
loadCoreLanguageModelFile(filenameSansExtension: "data-chs", langModel: &gLangModelCHS)
}
if !gLangModelCHS.isMiscDataLoaded() {
gLangModelCHS.loadMiscData(path: getBundleDataPath("data-zhuyinwen"))
}
if !gLangModelCHS.isSymbolDataLoaded() {
gLangModelCHS.loadSymbolData(path: getBundleDataPath("data-symbols"))
}
if !gLangModelCHS.isCNSDataLoaded() {
gLangModelCHS.loadCNSData(path: getBundleDataPath("char-kanji-cns"))
}
} else if mode == InputMode.imeModeCHT {
if !gLangModelCHT.isDataModelLoaded() {
loadCoreLanguageModelFile(filenameSansExtension: "data-cht", langModel: &gLangModelCHT)
}
if !gLangModelCHT.isMiscDataLoaded() {
gLangModelCHT.loadMiscData(path: getBundleDataPath("data-zhuyinwen"))
}
if !gLangModelCHT.isSymbolDataLoaded() {
gLangModelCHT.loadSymbolData(path: getBundleDataPath("data-symbols"))
}
if !gLangModelCHT.isCNSDataLoaded() {
gLangModelCHT.loadCNSData(path: getBundleDataPath("char-kanji-cns"))
}
}
}
public static func loadUserPhrases() {
gLangModelCHT.loadUserPhrases(
path: userSymbolDataPath(InputMode.imeModeCHT),
filterPath: excludedPhrasesDataPath(InputMode.imeModeCHT)
)
gLangModelCHS.loadUserPhrases(
path: userPhrasesDataPath(InputMode.imeModeCHS),
filterPath: excludedPhrasesDataPath(InputMode.imeModeCHS)
)
gLangModelCHT.loadUserSymbolData(path: userSymbolDataPath(InputMode.imeModeCHT))
gLangModelCHS.loadUserSymbolData(path: userSymbolDataPath(InputMode.imeModeCHS))
}
public static func loadUserAssociatedPhrases() {
gLangModelCHT.loadUserAssociatedPhrases(
path: mgrLangModel.userAssociatedPhrasesDataPath(InputMode.imeModeCHT)
)
gLangModelCHT.loadUserAssociatedPhrases(
path: mgrLangModel.userAssociatedPhrasesDataPath(InputMode.imeModeCHS)
)
}
public static func loadUserPhraseReplacement() {
gLangModelCHT.loadPhraseReplacementMap(
path: mgrLangModel.phraseReplacementDataPath(InputMode.imeModeCHT)
)
gLangModelCHT.loadPhraseReplacementMap(
path: mgrLangModel.phraseReplacementDataPath(InputMode.imeModeCHS)
)
}
public static func checkIfUserPhraseExist(
userPhrase: String,
mode: InputMode,
key unigramKey: String
) -> Bool {
let unigrams: [Megrez.Unigram] =
(mode == InputMode.imeModeCHT)
? gLangModelCHT.unigramsFor(key: unigramKey) : gLangModelCHS.unigramsFor(key: unigramKey)
for unigram in unigrams {
if unigram.keyValue.value == userPhrase {
return true
}
}
return false
}
public static func setPhraseReplacementEnabled(_ state: Bool) {
gLangModelCHT.isPhraseReplacementEnabled = state
gLangModelCHS.isPhraseReplacementEnabled = state
}
public static func setCNSEnabled(_ state: Bool) {
gLangModelCHT.isCNSEnabled = state
gLangModelCHS.isCNSEnabled = state
}
public static func setSymbolEnabled(_ state: Bool) {
gLangModelCHT.isSymbolEnabled = state
gLangModelCHS.isSymbolEnabled = state
}
@objc extension mgrLangModel {
// MARK: - // MARK: -
static func getBundleDataPath(_ filenameSansExt: String) -> String { static func getBundleDataPath(_ filenameSansExt: String) -> String {

View File

@ -1,40 +1 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
/*
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
1. The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
2. 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 above.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import "LMInstantiator.h"
#import "UserOverrideModel.h"
#import "mgrLangModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface mgrLangModel ()
@property(class, readonly, nonatomic) vChewing::LMInstantiator *lmCHT;
@property(class, readonly, nonatomic) vChewing::LMInstantiator *lmCHS;
@property(class, readonly, nonatomic) vChewing::UserOverrideModel *userOverrideModelCHS;
@property(class, readonly, nonatomic) vChewing::UserOverrideModel *userOverrideModelCHT;
@end
NS_ASSUME_NONNULL_END