From 5fba88cfeb4f63d3bf9efc59d8e0f6893c4ca86a Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sun, 3 Apr 2022 12:50:51 +0800 Subject: [PATCH] OpenCC // Swift Clang-Format. --- Packages/SwiftyOpenCC/Package.swift | 158 +++++++-------- .../Sources/OpenCC/ChineseConverter.swift | 126 ++++++------ .../Sources/OpenCC/ConversionDictionary.swift | 36 ++-- .../Sources/OpenCC/ConversionError.swift | 50 ++--- .../Sources/OpenCC/DictionaryLoader.swift | 84 ++++---- .../Sources/OpenCC/DictionaryName.swift | 184 +++++++++--------- .../Sources/OpenCC/WeakValueCache.swift | 56 +++--- .../Tests/OpenCCTests/OpenCCTests.swift | 115 +++++------ 8 files changed, 408 insertions(+), 401 deletions(-) diff --git a/Packages/SwiftyOpenCC/Package.swift b/Packages/SwiftyOpenCC/Package.swift index af2c4e23..115ce9e0 100644 --- a/Packages/SwiftyOpenCC/Package.swift +++ b/Packages/SwiftyOpenCC/Package.swift @@ -3,83 +3,83 @@ import PackageDescription let package = Package( - name: "SwiftyOpenCC", - products: [ - .library( - name: "OpenCC", - targets: ["OpenCC"]), - ], - targets: [ - .target( - name: "OpenCC", - dependencies: ["copencc"], - resources: [ - .copy("Dictionary") - ]), - .testTarget( - name: "OpenCCTests", - dependencies: ["OpenCC"], - resources: [ - .copy("benchmark"), - .copy("testcases"), - ]), - .target( - name: "copencc", - exclude: [ - "src/benchmark", - "src/tools", - "src/BinaryDictTest.cpp", - "src/Config.cpp", - "src/ConfigTest.cpp", - "src/ConversionChainTest.cpp", - "src/ConversionTest.cpp", - "src/DartsDictTest.cpp", - "src/DictGroupTest.cpp", - "src/MarisaDictTest.cpp", - "src/MaxMatchSegmentationTest.cpp", - "src/PhraseExtractTest.cpp", - "src/SerializedValuesTest.cpp", - "src/SimpleConverter.cpp", - "src/SimpleConverterTest.cpp", - "src/TextDictTest.cpp", - "src/UTF8StringSliceTest.cpp", - "src/UTF8UtilTest.cpp", - "deps/google-benchmark", - "deps/gtest-1.11.0", - "deps/pybind11-2.5.0", - "deps/rapidjson-1.1.0", - "deps/tclap-1.2.2", - - "src/CmdLineOutput.hpp", - "src/Config.hpp", - "src/ConfigTestBase.hpp", - "src/DictGroupTestBase.hpp", - "src/SimpleConverter.hpp", - "src/TestUtils.hpp", - "src/TestUtilsUTF8.hpp", - "src/TextDictTestBase.hpp", - "src/py_opencc.cpp", - - // ??? - "src/README.md", - "src/CMakeLists.txt", - "deps/marisa-0.2.6/AUTHORS", - "deps/marisa-0.2.6/CMakeLists.txt", - "deps/marisa-0.2.6/COPYING.md", - "deps/marisa-0.2.6/README.md", - ], - sources: [ - "source.cpp", - "src", - "deps/marisa-0.2.6", - ], - cxxSettings: [ - .headerSearchPath("src"), - .headerSearchPath("deps/darts-clone"), - .headerSearchPath("deps/marisa-0.2.6/include"), - .headerSearchPath("deps/marisa-0.2.6/lib"), - .define("ENABLE_DARTS"), - ]), - ], - cxxLanguageStandard: .cxx14 + name: "SwiftyOpenCC", + products: [ + .library( + name: "OpenCC", + targets: ["OpenCC"]) + ], + targets: [ + .target( + name: "OpenCC", + dependencies: ["copencc"], + resources: [ + .copy("Dictionary") + ]), + .testTarget( + name: "OpenCCTests", + dependencies: ["OpenCC"], + resources: [ + .copy("benchmark"), + .copy("testcases"), + ]), + .target( + name: "copencc", + exclude: [ + "src/benchmark", + "src/tools", + "src/BinaryDictTest.cpp", + "src/Config.cpp", + "src/ConfigTest.cpp", + "src/ConversionChainTest.cpp", + "src/ConversionTest.cpp", + "src/DartsDictTest.cpp", + "src/DictGroupTest.cpp", + "src/MarisaDictTest.cpp", + "src/MaxMatchSegmentationTest.cpp", + "src/PhraseExtractTest.cpp", + "src/SerializedValuesTest.cpp", + "src/SimpleConverter.cpp", + "src/SimpleConverterTest.cpp", + "src/TextDictTest.cpp", + "src/UTF8StringSliceTest.cpp", + "src/UTF8UtilTest.cpp", + "deps/google-benchmark", + "deps/gtest-1.11.0", + "deps/pybind11-2.5.0", + "deps/rapidjson-1.1.0", + "deps/tclap-1.2.2", + + "src/CmdLineOutput.hpp", + "src/Config.hpp", + "src/ConfigTestBase.hpp", + "src/DictGroupTestBase.hpp", + "src/SimpleConverter.hpp", + "src/TestUtils.hpp", + "src/TestUtilsUTF8.hpp", + "src/TextDictTestBase.hpp", + "src/py_opencc.cpp", + + // ??? + "src/README.md", + "src/CMakeLists.txt", + "deps/marisa-0.2.6/AUTHORS", + "deps/marisa-0.2.6/CMakeLists.txt", + "deps/marisa-0.2.6/COPYING.md", + "deps/marisa-0.2.6/README.md", + ], + sources: [ + "source.cpp", + "src", + "deps/marisa-0.2.6", + ], + cxxSettings: [ + .headerSearchPath("src"), + .headerSearchPath("deps/darts-clone"), + .headerSearchPath("deps/marisa-0.2.6/include"), + .headerSearchPath("deps/marisa-0.2.6/lib"), + .define("ENABLE_DARTS"), + ]), + ], + cxxLanguageStandard: .cxx14 ) diff --git a/Packages/SwiftyOpenCC/Sources/OpenCC/ChineseConverter.swift b/Packages/SwiftyOpenCC/Sources/OpenCC/ChineseConverter.swift index 259ed968..10cea288 100644 --- a/Packages/SwiftyOpenCC/Sources/OpenCC/ChineseConverter.swift +++ b/Packages/SwiftyOpenCC/Sources/OpenCC/ChineseConverter.swift @@ -22,68 +22,68 @@ import copencc /// However, the string on which it is operating should not be mutated /// during the course of a conversion. public class ChineseConverter { - - /// These constants define the ChineseConverter options. - public struct Options: OptionSet { - - public let rawValue: Int - - public init(rawValue: Int) { - self.rawValue = rawValue - } - - /// Convert to Traditional Chinese. (default) - public static let traditionalize = Options(rawValue: 1 << 0) - - /// Convert to Simplified Chinese. - public static let simplify = Options(rawValue: 1 << 1) - - /// Use Taiwan standard. - public static let twStandard = Options(rawValue: 1 << 5) - - /// Use HongKong standard. - public static let hkStandard = Options(rawValue: 1 << 6) - - /// Cancel Taiwan standard. - public static let twStandardRev = Options(rawValue: 1 << 15) - - /// Cancel HongKong standard. - public static let hkStandardRev = Options(rawValue: 1 << 16) - /// Taiwanese idiom conversion. - public static let twIdiom = Options(rawValue: 1 << 10) - } - - private let seg: ConversionDictionary - private let chain: [ConversionDictionary] - - private let converter: CCConverterRef - - private init(loader: DictionaryLoader, options: Options) throws { - seg = try loader.segmentation(options: options) - chain = try loader.conversionChain(options: options) - var rawChain = chain.map { $0.dict } - converter = CCConverterCreate("SwiftyOpenCC", seg.dict, &rawChain, rawChain.count) - } - - /// Returns an initialized `ChineseConverter` instance with the specified - /// conversion options. - /// - /// - Parameter options: The convert’s options. - /// - Throws: Throws `ConversionError` if failed. - public convenience init(options: Options) throws { - let loader = DictionaryLoader(bundle: .module) - try self.init(loader: loader, options: options) - } - - /// Return a converted string using the convert’s current option. - /// - /// - Parameter text: The string to convert. - /// - Returns: A converted string using the convert’s current option. - public func convert(_ text: String) -> String { - let stlStr = CCConverterCreateConvertedStringFromString(converter, text)! - defer { STLStringDestroy(stlStr) } - return String(utf8String: STLStringGetUTF8String(stlStr))! - } - + /// These constants define the ChineseConverter options. + public struct Options: OptionSet { + + public let rawValue: Int + + public init(rawValue: Int) { + self.rawValue = rawValue + } + + /// Convert to Traditional Chinese. (default) + public static let traditionalize = Options(rawValue: 1 << 0) + + /// Convert to Simplified Chinese. + public static let simplify = Options(rawValue: 1 << 1) + + /// Use Taiwan standard. + public static let twStandard = Options(rawValue: 1 << 5) + + /// Use HongKong standard. + public static let hkStandard = Options(rawValue: 1 << 6) + + /// Cancel Taiwan standard. + public static let twStandardRev = Options(rawValue: 1 << 15) + + /// Cancel HongKong standard. + public static let hkStandardRev = Options(rawValue: 1 << 16) + + /// Taiwanese idiom conversion. + public static let twIdiom = Options(rawValue: 1 << 10) + } + + private let seg: ConversionDictionary + private let chain: [ConversionDictionary] + + private let converter: CCConverterRef + + private init(loader: DictionaryLoader, options: Options) throws { + seg = try loader.segmentation(options: options) + chain = try loader.conversionChain(options: options) + var rawChain = chain.map { $0.dict } + converter = CCConverterCreate("SwiftyOpenCC", seg.dict, &rawChain, rawChain.count) + } + + /// Returns an initialized `ChineseConverter` instance with the specified + /// conversion options. + /// + /// - Parameter options: The convert’s options. + /// - Throws: Throws `ConversionError` if failed. + public convenience init(options: Options) throws { + let loader = DictionaryLoader(bundle: .module) + try self.init(loader: loader, options: options) + } + + /// Return a converted string using the convert’s current option. + /// + /// - Parameter text: The string to convert. + /// - Returns: A converted string using the convert’s current option. + public func convert(_ text: String) -> String { + let stlStr = CCConverterCreateConvertedStringFromString(converter, text)! + defer { STLStringDestroy(stlStr) } + return String(utf8String: STLStringGetUTF8String(stlStr))! + } + } diff --git a/Packages/SwiftyOpenCC/Sources/OpenCC/ConversionDictionary.swift b/Packages/SwiftyOpenCC/Sources/OpenCC/ConversionDictionary.swift index c91d515f..df7755ff 100644 --- a/Packages/SwiftyOpenCC/Sources/OpenCC/ConversionDictionary.swift +++ b/Packages/SwiftyOpenCC/Sources/OpenCC/ConversionDictionary.swift @@ -9,22 +9,22 @@ import Foundation import copencc class ConversionDictionary { - - let group: [ConversionDictionary] - - let dict: CCDictRef - - init(path: String) throws { - guard let dict = CCDictCreateMarisaWithPath(path) else { - throw ConversionError(ccErrorno) - } - self.group = [] - self.dict = dict - } - - init(group: [ConversionDictionary]) { - var rawGroup = group.map { $0.dict } - self.group = group - self.dict = CCDictCreateWithGroup(&rawGroup, rawGroup.count) - } + + let group: [ConversionDictionary] + + let dict: CCDictRef + + init(path: String) throws { + guard let dict = CCDictCreateMarisaWithPath(path) else { + throw ConversionError(ccErrorno) + } + self.group = [] + self.dict = dict + } + + init(group: [ConversionDictionary]) { + var rawGroup = group.map { $0.dict } + self.group = group + self.dict = CCDictCreateWithGroup(&rawGroup, rawGroup.count) + } } diff --git a/Packages/SwiftyOpenCC/Sources/OpenCC/ConversionError.swift b/Packages/SwiftyOpenCC/Sources/OpenCC/ConversionError.swift index d0114359..d24f1f21 100644 --- a/Packages/SwiftyOpenCC/Sources/OpenCC/ConversionError.swift +++ b/Packages/SwiftyOpenCC/Sources/OpenCC/ConversionError.swift @@ -9,29 +9,29 @@ import Foundation import copencc public enum ConversionError: Error { - - case fileNotFound - - case invalidFormat - - case invalidTextDictionary - - case invalidUTF8 - - case unknown - - init(_ code: CCErrorCode) { - switch code { - case .fileNotFound: - self = .fileNotFound - case .invalidFormat: - self = .invalidFormat - case .invalidTextDictionary: - self = .invalidTextDictionary - case .invalidUTF8: - self = .invalidUTF8 - case .unknown, _: - self = .unknown - } - } + + case fileNotFound + + case invalidFormat + + case invalidTextDictionary + + case invalidUTF8 + + case unknown + + init(_ code: CCErrorCode) { + switch code { + case .fileNotFound: + self = .fileNotFound + case .invalidFormat: + self = .invalidFormat + case .invalidTextDictionary: + self = .invalidTextDictionary + case .invalidUTF8: + self = .invalidUTF8 + case .unknown, _: + self = .unknown + } + } } diff --git a/Packages/SwiftyOpenCC/Sources/OpenCC/DictionaryLoader.swift b/Packages/SwiftyOpenCC/Sources/OpenCC/DictionaryLoader.swift index d97b11ef..83dcc9db 100644 --- a/Packages/SwiftyOpenCC/Sources/OpenCC/DictionaryLoader.swift +++ b/Packages/SwiftyOpenCC/Sources/OpenCC/DictionaryLoader.swift @@ -9,47 +9,51 @@ import Foundation import copencc extension ChineseConverter { - - struct DictionaryLoader { - - private static let subdirectory = "Dictionary" - private static let dictCache = WeakValueCache() - - private let bundle: Bundle - - init(bundle: Bundle) { - self.bundle = bundle - } - - func dict(_ name: ChineseConverter.DictionaryName) throws -> ConversionDictionary { - guard let path = bundle.path(forResource: name.description, ofType: "ocd2", inDirectory: DictionaryLoader.subdirectory) else { - throw ConversionError.fileNotFound - } - return try DictionaryLoader.dictCache.value(for: path) { - return try ConversionDictionary(path: path) - } - } - } + + struct DictionaryLoader { + + private static let subdirectory = "Dictionary" + private static let dictCache = WeakValueCache() + + private let bundle: Bundle + + init(bundle: Bundle) { + self.bundle = bundle + } + + func dict(_ name: ChineseConverter.DictionaryName) throws -> ConversionDictionary { + guard + let path = bundle.path( + forResource: name.description, ofType: "ocd2", + inDirectory: DictionaryLoader.subdirectory) + else { + throw ConversionError.fileNotFound + } + return try DictionaryLoader.dictCache.value(for: path) { + return try ConversionDictionary(path: path) + } + } + } } extension ChineseConverter.DictionaryLoader { - - func segmentation(options: ChineseConverter.Options) throws -> ConversionDictionary { - let dictName = options.segmentationDictName - return try dict(dictName) - } - - func conversionChain(options: ChineseConverter.Options) throws -> [ConversionDictionary] { - return try options.conversionChain.compactMap { names in - switch names.count { - case 0: - return nil - case 1: - return try dict(names.first!) - case _: - let dicts = try names.map(dict) - return ConversionDictionary(group: dicts) - } - } - } + + func segmentation(options: ChineseConverter.Options) throws -> ConversionDictionary { + let dictName = options.segmentationDictName + return try dict(dictName) + } + + func conversionChain(options: ChineseConverter.Options) throws -> [ConversionDictionary] { + return try options.conversionChain.compactMap { names in + switch names.count { + case 0: + return nil + case 1: + return try dict(names.first!) + case _: + let dicts = try names.map(dict) + return ConversionDictionary(group: dicts) + } + } + } } diff --git a/Packages/SwiftyOpenCC/Sources/OpenCC/DictionaryName.swift b/Packages/SwiftyOpenCC/Sources/OpenCC/DictionaryName.swift index 6e7f2e4d..3629bbcc 100644 --- a/Packages/SwiftyOpenCC/Sources/OpenCC/DictionaryName.swift +++ b/Packages/SwiftyOpenCC/Sources/OpenCC/DictionaryName.swift @@ -8,99 +8,99 @@ import Foundation extension ChineseConverter { - - enum DictionaryName: CustomStringConvertible { - - case hkVariants - case hkVariantsRev - case hkVariantsRevPhrases - case jpVariants - case stCharacters - case stPhrases - case tsCharacters - case tsPhrases - case twPhrases - case twPhrasesRev - case twVariants - case twVariantsRev - case twVariantsRevPhrases - - var description: String { - switch self { - case .hkVariants: return "HKVariants" - case .hkVariantsRev: return "HKVariantsRev" - case .hkVariantsRevPhrases: return "HKVariantsRevPhrases" - case .jpVariants: return "JPVariants" - case .stCharacters: return "STCharacters" - case .stPhrases: return "STPhrases" - case .tsCharacters: return "TSCharacters" - case .tsPhrases: return "TSPhrases" - case .twPhrases: return "TWPhrases" - case .twPhrasesRev: return "TWPhrasesRev" - case .twVariants: return "TWVariants" - case .twVariantsRev: return "TWVariantsRev" - case .twVariantsRevPhrases: return "TWVariantsRevPhrases" - } - } - } + + enum DictionaryName: CustomStringConvertible { + + case hkVariants + case hkVariantsRev + case hkVariantsRevPhrases + case jpVariants + case stCharacters + case stPhrases + case tsCharacters + case tsPhrases + case twPhrases + case twPhrasesRev + case twVariants + case twVariantsRev + case twVariantsRevPhrases + + var description: String { + switch self { + case .hkVariants: return "HKVariants" + case .hkVariantsRev: return "HKVariantsRev" + case .hkVariantsRevPhrases: return "HKVariantsRevPhrases" + case .jpVariants: return "JPVariants" + case .stCharacters: return "STCharacters" + case .stPhrases: return "STPhrases" + case .tsCharacters: return "TSCharacters" + case .tsPhrases: return "TSPhrases" + case .twPhrases: return "TWPhrases" + case .twPhrasesRev: return "TWPhrasesRev" + case .twVariants: return "TWVariants" + case .twVariantsRev: return "TWVariantsRev" + case .twVariantsRevPhrases: return "TWVariantsRevPhrases" + } + } + } } extension ChineseConverter.Options { - - var segmentationDictName: ChineseConverter.DictionaryName { - if contains(.traditionalize) { - return .stPhrases - } else if contains(.simplify) { - return .tsPhrases - } else if contains(.hkStandard) { - return .hkVariants - } else if contains(.twStandard) { - return .twVariants - } else if contains(.hkStandardRev) { - return .hkVariantsRev - } else if contains(.twStandardRev) { - return .twVariantsRev - } else { - return .stPhrases - } - } - - var conversionChain: [[ChineseConverter.DictionaryName]] { - var result: [[ChineseConverter.DictionaryName]] = [] - if contains(.traditionalize) { - result.append([.stPhrases, .stCharacters]) - if contains(.twIdiom) { - result.append([.twPhrases]) - } - if contains(.hkStandard) { - result.append([.hkVariants]) - } else if contains(.twStandard) { - result.append([.twVariants]) - } - } else if contains(.simplify) { - if contains(.hkStandard) { - result.append([.hkVariantsRevPhrases, .hkVariantsRev]) - } else if contains(.twStandard) { - result.append([.twVariantsRevPhrases, .twVariantsRev]) - } - if contains(.twIdiom) { - result.append([.twPhrasesRev]) - } - result.append([.tsPhrases, .tsCharacters]) - } else { - if contains(.hkStandard) { - result.append([.hkVariants]) - } else if contains(.twStandard) { - result.append([.twVariants]) - } else if contains(.hkStandardRev) { - result.append([.hkVariantsRev]) - } else if contains(.twStandardRev) { - result.append([.twVariantsRev]) - } - } - if result.isEmpty { - return [[.stPhrases, .stCharacters]] - } - return result - } + + var segmentationDictName: ChineseConverter.DictionaryName { + if contains(.traditionalize) { + return .stPhrases + } else if contains(.simplify) { + return .tsPhrases + } else if contains(.hkStandard) { + return .hkVariants + } else if contains(.twStandard) { + return .twVariants + } else if contains(.hkStandardRev) { + return .hkVariantsRev + } else if contains(.twStandardRev) { + return .twVariantsRev + } else { + return .stPhrases + } + } + + var conversionChain: [[ChineseConverter.DictionaryName]] { + var result: [[ChineseConverter.DictionaryName]] = [] + if contains(.traditionalize) { + result.append([.stPhrases, .stCharacters]) + if contains(.twIdiom) { + result.append([.twPhrases]) + } + if contains(.hkStandard) { + result.append([.hkVariants]) + } else if contains(.twStandard) { + result.append([.twVariants]) + } + } else if contains(.simplify) { + if contains(.hkStandard) { + result.append([.hkVariantsRevPhrases, .hkVariantsRev]) + } else if contains(.twStandard) { + result.append([.twVariantsRevPhrases, .twVariantsRev]) + } + if contains(.twIdiom) { + result.append([.twPhrasesRev]) + } + result.append([.tsPhrases, .tsCharacters]) + } else { + if contains(.hkStandard) { + result.append([.hkVariants]) + } else if contains(.twStandard) { + result.append([.twVariants]) + } else if contains(.hkStandardRev) { + result.append([.hkVariantsRev]) + } else if contains(.twStandardRev) { + result.append([.twVariantsRev]) + } + } + if result.isEmpty { + return [[.stPhrases, .stCharacters]] + } + return result + } } diff --git a/Packages/SwiftyOpenCC/Sources/OpenCC/WeakValueCache.swift b/Packages/SwiftyOpenCC/Sources/OpenCC/WeakValueCache.swift index 648361fc..d945a371 100644 --- a/Packages/SwiftyOpenCC/Sources/OpenCC/WeakValueCache.swift +++ b/Packages/SwiftyOpenCC/Sources/OpenCC/WeakValueCache.swift @@ -8,35 +8,35 @@ import Foundation class WeakBox { - - private(set) weak var value: Value? - - init(_ value: Value) { - self.value = value - } + + private(set) weak var value: Value? + + init(_ value: Value) { + self.value = value + } } class WeakValueCache { - - private var storage: [Key: WeakBox] = [:] - - private var lock = NSLock() - - func value(for key: Key) -> Value? { - return storage[key]?.value - } - - func value(for key: Key, make: () throws -> Value) rethrows -> Value { - if let value = storage[key]?.value { - return value - } - lock.lock() - defer { lock.unlock() } - if let value = storage[key]?.value { - return value - } - let value = try make() - storage[key] = WeakBox(value) - return value - } + + private var storage: [Key: WeakBox] = [:] + + private var lock = NSLock() + + func value(for key: Key) -> Value? { + return storage[key]?.value + } + + func value(for key: Key, make: () throws -> Value) rethrows -> Value { + if let value = storage[key]?.value { + return value + } + lock.lock() + defer { lock.unlock() } + if let value = storage[key]?.value { + return value + } + let value = try make() + storage[key] = WeakBox(value) + return value + } } diff --git a/Packages/SwiftyOpenCC/Tests/OpenCCTests/OpenCCTests.swift b/Packages/SwiftyOpenCC/Tests/OpenCCTests/OpenCCTests.swift index 03c7d093..6ce821cc 100644 --- a/Packages/SwiftyOpenCC/Tests/OpenCCTests/OpenCCTests.swift +++ b/Packages/SwiftyOpenCC/Tests/OpenCCTests/OpenCCTests.swift @@ -1,64 +1,67 @@ import XCTest + @testable import OpenCC let testCases: [(String, ChineseConverter.Options)] = [ - ("s2t", [.traditionalize]), - ("t2s", [.simplify]), - ("s2hk", [.traditionalize, .hkStandard]), - ("hk2s", [.simplify, .hkStandard]), - ("s2tw", [.traditionalize, .twStandard]), - ("tw2s", [.simplify, .twStandard]), - ("s2twp", [.traditionalize, .twStandard, .twIdiom]), - ("tw2sp", [.simplify, .twStandard, .twIdiom]), + ("s2t", [.traditionalize]), + ("t2s", [.simplify]), + ("s2hk", [.traditionalize, .hkStandard]), + ("hk2s", [.simplify, .hkStandard]), + ("s2tw", [.traditionalize, .twStandard]), + ("tw2s", [.simplify, .twStandard]), + ("s2twp", [.traditionalize, .twStandard, .twIdiom]), + ("tw2sp", [.simplify, .twStandard, .twIdiom]), ] class OpenCCTests: XCTestCase { - - func converter(option: ChineseConverter.Options) throws -> ChineseConverter { - return try ChineseConverter(options: option) - } - - func testConversion() throws { - func testCase(name: String, ext: String) -> String { - let url = Bundle.module.url(forResource: name, withExtension: ext, subdirectory: "testcases")! - return try! String(contentsOf: url) - } - for (name, opt) in testCases { - let coverter = try ChineseConverter(options: opt) - let input = testCase(name: name, ext: "in") - let converted = coverter.convert(input) - let output = testCase(name: name, ext: "ans") - XCTAssertEqual(converted, output, "Conversion \(name) fails") - } - } - - func testConverterCreationPerformance() { - let options: ChineseConverter.Options = [.traditionalize, .twStandard, .twIdiom] - measure { - for _ in 0..<10 { - _ = try! ChineseConverter(options: options) - } - } - } - - func testDictionaryCache() { - let options: ChineseConverter.Options = [.traditionalize, .twStandard, .twIdiom] - let holder = try! ChineseConverter(options: options) - measure { - for _ in 0..<1_000 { - _ = try! ChineseConverter(options: options) - } - } - _ = holder.convert("foo") - } - - func testConversionPerformance() throws { - let cov = try converter(option: [.traditionalize, .twStandard, .twIdiom]) - let url = Bundle.module.url(forResource: "zuozhuan", withExtension: "txt", subdirectory: "benchmark")! - // 1.9 MB, 624k word - let str = try String(contentsOf: url) - measure { - _ = cov.convert(str) - } - } + + func converter(option: ChineseConverter.Options) throws -> ChineseConverter { + return try ChineseConverter(options: option) + } + + func testConversion() throws { + func testCase(name: String, ext: String) -> String { + let url = Bundle.module.url( + forResource: name, withExtension: ext, subdirectory: "testcases")! + return try! String(contentsOf: url) + } + for (name, opt) in testCases { + let coverter = try ChineseConverter(options: opt) + let input = testCase(name: name, ext: "in") + let converted = coverter.convert(input) + let output = testCase(name: name, ext: "ans") + XCTAssertEqual(converted, output, "Conversion \(name) fails") + } + } + + func testConverterCreationPerformance() { + let options: ChineseConverter.Options = [.traditionalize, .twStandard, .twIdiom] + measure { + for _ in 0..<10 { + _ = try! ChineseConverter(options: options) + } + } + } + + func testDictionaryCache() { + let options: ChineseConverter.Options = [.traditionalize, .twStandard, .twIdiom] + let holder = try! ChineseConverter(options: options) + measure { + for _ in 0..<1_000 { + _ = try! ChineseConverter(options: options) + } + } + _ = holder.convert("foo") + } + + func testConversionPerformance() throws { + let cov = try converter(option: [.traditionalize, .twStandard, .twIdiom]) + let url = Bundle.module.url( + forResource: "zuozhuan", withExtension: "txt", subdirectory: "benchmark")! + // 1.9 MB, 624k word + let str = try String(contentsOf: url) + measure { + _ = cov.convert(str) + } + } }