diff --git a/Package.swift b/Package.swift index 5d6a60345..81c044166 100644 --- a/Package.swift +++ b/Package.swift @@ -145,9 +145,6 @@ let package = Package( "TestSupport", "FoundationEssentials" ], - resources: [ - .copy("Resources") - ], swiftSettings: availabilityMacros + concurrencyChecking ), @@ -175,15 +172,6 @@ let package = Package( ] + availabilityMacros + concurrencyChecking ), - .testTarget( - name: "FoundationInternationalizationTests", - dependencies: [ - "TestSupport", - "FoundationInternationalization", - ], - swiftSettings: availabilityMacros + concurrencyChecking - ), - // FoundationMacros .macro( name: "FoundationMacros", @@ -202,18 +190,3 @@ let package = Package( ), ] ) - -// https://github.com/apple/swift-package-manager/issues/7174 -// Test macro targets result in multiple definitions of `main` on Windows. -#if !os(Windows) -package.targets.append(contentsOf: [ - .testTarget( - name: "FoundationMacrosTests", - dependencies: [ - "FoundationMacros", - "TestSupport" - ], - swiftSettings: availabilityMacros + concurrencyChecking - ) -]) -#endif diff --git a/Sources/FoundationEssentials/JSON/JSONScanner.swift b/Sources/FoundationEssentials/JSON/JSONScanner.swift index f78c3637b..3ffe27324 100644 --- a/Sources/FoundationEssentials/JSON/JSONScanner.swift +++ b/Sources/FoundationEssentials/JSON/JSONScanner.swift @@ -261,6 +261,8 @@ extension JSONMap.Value { internal struct JSONScanner { + internal static let maximumRecursionDepth = JSONWriter.maximumRecursionDepth + let options: Options var reader: DocumentReader var depth: Int = 0 @@ -412,7 +414,7 @@ internal struct JSONScanner { mutating func scanArray() throws { let firstChar = reader.read() precondition(firstChar == ._openbracket) - guard self.depth < 512 else { + guard self.depth < Self.maximumRecursionDepth else { throw JSONError.tooManyNestedArraysOrDictionaries(location: reader.sourceLocation(atOffset: 1)) } self.depth &+= 1 @@ -470,7 +472,7 @@ internal struct JSONScanner { mutating func scanObject() throws { let firstChar = self.reader.read() precondition(firstChar == ._openbrace) - guard self.depth < 512 else { + guard self.depth < Self.maximumRecursionDepth else { throw JSONError.tooManyNestedArraysOrDictionaries(location: reader.sourceLocation(atOffset: -1)) } try scanObject(withoutBraces: false) diff --git a/Sources/FoundationEssentials/JSON/JSONWriter.swift b/Sources/FoundationEssentials/JSON/JSONWriter.swift index 2ecf8b7b5..3ab22c56f 100644 --- a/Sources/FoundationEssentials/JSON/JSONWriter.swift +++ b/Sources/FoundationEssentials/JSON/JSONWriter.swift @@ -13,7 +13,7 @@ internal struct JSONWriter { // Structures with container nesting deeper than this limit are not valid. - private static let maximumRecursionDepth = 512 + internal static let maximumRecursionDepth = 512 private var indent = 0 private let pretty: Bool diff --git a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringCOWTests.swift b/Tests/FoundationEssentialsTests/AttributedString/AttributedStringCOWTests.swift deleted file mode 100644 index 2f8fd4b52..000000000 --- a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringCOWTests.swift +++ /dev/null @@ -1,260 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2020 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#else -@testable import FoundationEssentials -#endif - -extension AttributedStringProtocol { - fileprivate mutating func genericSetAttribute() { - self.testInt = 3 - } -} - -/// Tests for `AttributedString` to confirm expected CoW behavior -final class TestAttributedStringCOW: XCTestCase { - - // MARK: - Utility Functions - - func createAttributedString() -> AttributedString { - var str = AttributedString("Hello", attributes: container) - str += AttributedString(" ") - str += AttributedString("World", attributes: containerB) - return str - } - - func assertCOWCopy(file: StaticString = #filePath, line: UInt = #line, _ operation: (inout AttributedString) -> Void) { - let str = createAttributedString() - var copy = str - operation(©) - XCTAssertNotEqual(str, copy, "Mutation operation did not copy when multiple references exist", file: file, line: line) - } - - func assertCOWCopyManual(file: StaticString = #filePath, line: UInt = #line, _ operation: (inout AttributedString) -> Void) { - var str = createAttributedString() - let gutsPtr = Unmanaged.passUnretained(str._guts) - operation(&str) - let newGutsPtr = Unmanaged.passUnretained(str._guts) - XCTAssertNotEqual(gutsPtr.toOpaque(), newGutsPtr.toOpaque(), "Mutation operation with manual copy did not perform copy", file: file, line: line) - } - - func assertCOWNoCopy(file: StaticString = #filePath, line: UInt = #line, _ operation: (inout AttributedString) -> Void) { - var str = createAttributedString() - let gutsPtr = Unmanaged.passUnretained(str._guts) - operation(&str) - let newGutsPtr = Unmanaged.passUnretained(str._guts) - XCTAssertEqual(gutsPtr.toOpaque(), newGutsPtr.toOpaque(), "Mutation operation copied when only one reference exists", file: file, line: line) - } - - func assertCOWBehavior(file: StaticString = #filePath, line: UInt = #line, _ operation: (inout AttributedString) -> Void) { - assertCOWCopy(file: file, line: line, operation) - assertCOWNoCopy(file: file, line: line, operation) - } - - func makeSubrange(_ str: AttributedString) -> Range { - return str.characters.index(str.startIndex, offsetBy: 2).. RangeSet { - let rangeA = str.characters.index(str.startIndex, offsetBy: 2)..( - string: AttributedString, - matches expected: [(String, K.Value?)], - for key: KeyPath, - file: StaticString = #filePath, line: UInt = #line - ) - where K.Value : Sendable - { - let runs = string.runs[key] - XCTAssertEqual(runs.count, expected.count, "Unexpected number of runs", file: file, line: line) - for ((val, range), expectation) in zip(runs, expected) { - let slice = String.UnicodeScalarView(string.unicodeScalars[range]) - XCTAssertTrue(slice.elementsEqual(expectation.0.unicodeScalars), "Unexpected range of run: \(slice.debugDescription) vs \(expectation.0.debugDescription)", file: file, line: line) - XCTAssertEqual(val, expectation.1, "Unexpected value of attribute \(K.self) for range \(expectation.0)", file: file, line: line) - } - for ((val, range), expectation) in zip(runs.reversed(), expected.reversed()) { - let slice = String.UnicodeScalarView(string.unicodeScalars[range]) - XCTAssertTrue(slice.elementsEqual(expectation.0.unicodeScalars), "Unexpected range of run while reverse iterating: \(slice.debugDescription) vs \(expectation.0.debugDescription)", file: file, line: line) - XCTAssertEqual(val, expectation.1, "Unexpected value of attribute \(K.self) for range \(expectation.0) while reverse iterating", file: file, line: line) - } - } - - func verify(string: AttributedString, matches expected: [(String, K.Value?, K2.Value?)], for key: KeyPath, _ key2: KeyPath, file: StaticString = #filePath, line: UInt = #line) - where K.Value : Sendable, K2.Value : Sendable - { - let runs = string.runs[key, key2] - XCTAssertEqual(runs.count, expected.count, "Unexpected number of runs", file: file, line: line) - for ((val1, val2, range), expectation) in zip(runs, expected) { - XCTAssertEqual(String(string.characters[range]),expectation.0, "Unexpected range of run", file: file, line: line) - XCTAssertEqual(val1, expectation.1, "Unexpected value of attribute \(K.self) for range \(expectation.0)", file: file, line: line) - XCTAssertEqual(val2, expectation.2, "Unexpected value of attribute \(K2.self) for range \(expectation.0)", file: file, line: line) - } - for ((val1, val2, range), expectation) in zip(runs.reversed(), expected.reversed()) { - XCTAssertEqual(String(string.characters[range]), expectation.0, "Unexpected range of run while reverse iterating", file: file, line: line) - XCTAssertEqual(val1, expectation.1, "Unexpected value of attribute \(K.self) for range \(expectation.0) while reverse iterating", file: file, line: line) - XCTAssertEqual(val2, expectation.2, "Unexpected value of attribute \(K2.self) for range \(expectation.0) while reverse iterating", file: file, line: line) - } - } - - func verify(string: AttributedString, matches expected: [(String, K.Value?, K2.Value?, K3.Value?)], for key: KeyPath, _ key2: KeyPath, _ key3: KeyPath, file: StaticString = #filePath, line: UInt = #line) - where K.Value : Sendable, K2.Value : Sendable, K3.Value : Sendable - { - let runs = string.runs[key, key2, key3] - XCTAssertEqual(runs.count, expected.count, "Unexpected number of runs", file: file, line: line) - for ((val1, val2, val3, range), expectation) in zip(runs, expected) { - XCTAssertEqual(String(string.characters[range]),expectation.0, "Unexpected range of run", file: file, line: line) - XCTAssertEqual(val1, expectation.1, "Unexpected value of attribute \(K.self) for range \(expectation.0)", file: file, line: line) - XCTAssertEqual(val2, expectation.2, "Unexpected value of attribute \(K2.self) for range \(expectation.0)", file: file, line: line) - XCTAssertEqual(val3, expectation.3, "Unexpected value of attribute \(K3.self) for range \(expectation.0)", file: file, line: line) - } - for ((val1, val2, val3, range), expectation) in zip(runs.reversed(), expected.reversed()) { - XCTAssertEqual(String(string.characters[range]), expectation.0, "Unexpected range of run while reverse iterating", file: file, line: line) - XCTAssertEqual(val1, expectation.1, "Unexpected value of attribute \(K.self) for range \(expectation.0) while reverse iterating", file: file, line: line) - XCTAssertEqual(val2, expectation.2, "Unexpected value of attribute \(K2.self) for range \(expectation.0) while reverse iterating", file: file, line: line) - XCTAssertEqual(val3, expectation.3, "Unexpected value of attribute \(K3.self) for range \(expectation.0) while reverse iterating", file: file, line: line) - } - } - - // MARK: Extending Run Tests - - func testExtendingRunAddCharacters() { - let str = AttributedString("Hello, world", attributes: .init().testInt(2).testNonExtended(1)) - - var result = str - result.characters.append(contentsOf: "ABC") - verify(string: result, matches: [("Hello, world", 2, 1), ("ABC", 2, nil)], for: \.testInt, \.testNonExtended) - - result = str - result.characters.insert(contentsOf: "ABC", at: result.index(result.startIndex, offsetByCharacters: 3)) - verify(string: result, matches: [("Hel", 2, 1), ("ABC", 2, nil), ("lo, world", 2, 1)], for: \.testInt, \.testNonExtended) - - result = str - result.characters.insert(contentsOf: "ABC", at: result.startIndex) - verify(string: result, matches: [("ABC", 2, nil), ("Hello, world", 2, 1)], for: \.testInt, \.testNonExtended) - - result = str - var subrange = result.index(result.startIndex, offsetByCharacters: 2) ..< result.index(result.startIndex, offsetByCharacters: 9) - result.characters.replaceSubrange(subrange, with: "ABC") - verify(string: result, matches: [("He", 2, 1), ("ABC", 2, nil), ("rld", 2, 1)], for: \.testInt, \.testNonExtended) - - result = str - subrange = result.index(result.startIndex, offsetByCharacters: 2) ..< result.index(result.startIndex, offsetByCharacters: 9) - let other = AttributedString("Hi!") - result.characters[subrange] = other.characters[other.startIndex ..< other.endIndex] - verify(string: result, matches: [("He", 2, 1), ("Hi!", 2, nil), ("rld", 2, 1)], for: \.testInt, \.testNonExtended) - } - - func testExtendingRunAddUnicodeScalars() { - let str = AttributedString("Hello, world", attributes: .init().testInt(2).testNonExtended(1)) - let scalarsStr = "A\u{0301}B" - - var result = str - result.unicodeScalars.append(contentsOf: scalarsStr.unicodeScalars) - verify(string: result, matches: [("Hello, world", 2, 1), (scalarsStr, 2, nil)], for: \.testInt, \.testNonExtended) - - result = str - result.unicodeScalars.insert(contentsOf: scalarsStr.unicodeScalars, at: result.index(result.startIndex, offsetByUnicodeScalars: 3)) - verify(string: result, matches: [("Hel", 2, 1), (scalarsStr, 2, nil), ("lo, world", 2, 1)], for: \.testInt, \.testNonExtended) - - result = str - result.unicodeScalars.insert(contentsOf: scalarsStr.unicodeScalars, at: result.startIndex) - verify(string: result, matches: [(scalarsStr, 2, nil), ("Hello, world", 2, 1)], for: \.testInt, \.testNonExtended) - - result = str - let subrange = result.index(result.startIndex, offsetByUnicodeScalars: 2) ..< result.index(result.startIndex, offsetByUnicodeScalars: 9) - result.unicodeScalars.replaceSubrange(subrange, with: scalarsStr.unicodeScalars) - verify(string: result, matches: [("He", 2, 1), (scalarsStr, 2, nil), ("rld", 2, 1)], for: \.testInt, \.testNonExtended) - } - - // MARK: - Paragraph Constrained Tests - - func testParagraphAttributeExpanding() { - var str = AttributedString("Hello, world\nNext Paragraph") - var range = str.index(afterCharacter: str.startIndex) ..< str.index(str.startIndex, offsetByCharacters: 3) - str[range].testParagraphConstrained = 2 - verify(string: str, matches: [("Hello, world\n", 2), ("Next Paragraph", nil)], for: \.testParagraphConstrained) - - range = str.index(beforeCharacter: str.endIndex) ..< str.endIndex - str[range].testParagraphConstrained = 3 - verify(string: str, matches: [("Hello, world\n", 2), ("Next Paragraph", 3)], for: \.testParagraphConstrained) - - str.testInt = 1 - verify(string: str, matches: [("Hello, world\n", 2, 1), ("Next Paragraph", 3, 1)], for: \.testParagraphConstrained, \.testInt) - - str[range].testParagraphConstrained = 4 - verify(string: str, matches: [("Hello, world\n", 2, 1), ("Next Paragraph", 4, 1)], for: \.testParagraphConstrained, \.testInt) - - range = str.index(str.startIndex, offsetByCharacters: 8) ..< str.index(str.startIndex, offsetByCharacters: 14) - str[range].testParagraphConstrained = 4 - verify(string: str, matches: [("Hello, world\n", 4), ("Next Paragraph", 4)], for: \.testParagraphConstrained) - } - - func testParagraphAttributeRemoval() { - var str = AttributedString("Hello, world\nNext Paragraph", attributes: .init().testParagraphConstrained(2)) - var range = str.index(afterCharacter: str.startIndex) ..< str.index(str.startIndex, offsetByCharacters: 3) - str[range].testParagraphConstrained = nil - verify(string: str, matches: [("Hello, world\n", nil), ("Next Paragraph", 2)], for: \.testParagraphConstrained) - - str.testInt = 1 - verify(string: str, matches: [("Hello, world\n", nil, 1), ("Next Paragraph", 2, 1)], for: \.testParagraphConstrained, \.testInt) - - range = str.index(beforeCharacter: str.endIndex) ..< str.endIndex - str[range].testParagraphConstrained = nil - verify(string: str, matches: [("Hello, world\n", nil, 1), ("Next Paragraph", nil, 1)], for: \.testParagraphConstrained, \.testInt) - - str = AttributedString("Hello, world\nNext Paragraph", attributes: .init().testParagraphConstrained(2)) - range = str.index(str.startIndex, offsetByCharacters: 8) ..< str.index(str.startIndex, offsetByCharacters: 14) - str[range].testParagraphConstrained = nil - verify(string: str, matches: [("Hello, world\n", nil), ("Next Paragraph", nil)], for: \.testParagraphConstrained) - } - - func testParagraphAttributeContainerApplying() { - var container = AttributeContainer.testParagraphConstrained(2).testString("Hello") - var str = AttributedString("Hello, world\nNext Paragraph") - var range = str.index(afterCharacter: str.startIndex) ..< str.index(str.startIndex, offsetByCharacters: 3) - str[range].setAttributes(container) - verify(string: str, matches: [("H", 2, nil), ("el", 2, "Hello"), ("lo, world\n", 2, nil), ("Next Paragraph", nil, nil)], for: \.testParagraphConstrained, \.testString) - - range = str.index(beforeCharacter: str.endIndex) ..< str.endIndex - container.testParagraphConstrained = 3 - str[range].setAttributes(container) - verify(string: str, matches: [("H", 2, nil), ("el", 2, "Hello"), ("lo, world\n", 2, nil), ("Next Paragrap", 3, nil), ("h", 3, "Hello")], for: \.testParagraphConstrained, \.testString) - - str.testInt = 1 - verify(string: str, matches: [("H", 2, nil, 1), ("el", 2, "Hello", 1), ("lo, world\n", 2, nil, 1), ("Next Paragrap", 3, nil, 1), ("h", 3, "Hello", 1)], for: \.testParagraphConstrained, \.testString, \.testInt) - - container.testInt = 2 - container.testParagraphConstrained = 4 - container.testString = nil - str[range].mergeAttributes(container, mergePolicy: .keepCurrent) - verify(string: str, matches: [("H", 2, nil, 1), ("el", 2, "Hello", 1), ("lo, world\n", 2, nil, 1), ("Next Paragrap", 3, nil, 1), ("h", 3, "Hello", 1)], for: \.testParagraphConstrained, \.testString, \.testInt) - str[range].mergeAttributes(container, mergePolicy: .keepNew) - verify(string: str, matches: [("H", 2, nil, 1), ("el", 2, "Hello", 1), ("lo, world\n", 2, nil, 1), ("Next Paragrap", 4, nil, 1), ("h", 4, "Hello", 2)], for: \.testParagraphConstrained, \.testString, \.testInt) - - range = str.index(str.startIndex, offsetByCharacters: 8) ..< str.index(str.startIndex, offsetByCharacters: 14) - str[range].mergeAttributes(container, mergePolicy: .keepNew) - verify(string: str, matches: [("H", 4, nil, 1), ("el", 4, "Hello", 1), ("lo, w", 4, nil, 1), ("orld\n", 4, nil, 2), ("N", 4, nil, 2), ("ext Paragrap", 4, nil, 1), ("h", 4, "Hello", 2)], for: \.testParagraphConstrained, \.testString, \.testInt) - } - - func testParagraphAttributeContainerReplacing() { - var str = AttributedString("Hello, world\nNext Paragraph") - let range = str.index(afterCharacter: str.startIndex) ..< str.index(str.startIndex, offsetByCharacters: 3) - str[range].testInt = 2 - - var result = str.transformingAttributes(\.testInt) { - if $0.value == 2 { - $0.replace(with: \.testParagraphConstrained, value: 3) - } - } - verify(string: result, matches: [("Hello, world\n", 3, nil), ("Next Paragraph", nil, nil)], for: \.testParagraphConstrained, \.testInt) - - result = str.replacingAttributes(.init().testInt(2), with: .init().testParagraphConstrained(3).testBool(true)) - verify(string: result, matches: [("H", 3, nil, nil), ("el", 3, nil, true), ("lo, world\n", 3, nil, nil), ("Next Paragraph", nil, nil, nil)], for: \.testParagraphConstrained, \.testInt, \.testBool) - - str.testInt = 2 - result = str - result[range].replaceAttributes(.init().testInt(2), with: .init().testParagraphConstrained(3).testBool(true)) - verify(string: result, matches: [("H", 3, 2, nil), ("el", 3, nil, true), ("lo, world\n", 3, 2, nil), ("Next Paragraph", nil, 2, nil)], for: \.testParagraphConstrained, \.testInt, \.testBool) - } - - func testParagraphTextMutation() { - let str = AttributedString("Hello, world\n", attributes: .init().testParagraphConstrained(1)) + AttributedString("Next Paragraph", attributes: .init().testParagraphConstrained(2)) - - var result = str - result.characters.insert(contentsOf: "Test", at: result.index(result.startIndex, offsetByCharacters: 2)) - verify(string: result, matches: [("HeTestllo, world\n", 1), ("Next Paragraph", 2)], for: \.testParagraphConstrained) - - result = str - result.characters.append(contentsOf: "Test") - verify(string: result, matches: [("Hello, world\n", 1), ("Next ParagraphTest", 2)], for: \.testParagraphConstrained) - - result = str - result.characters.insert(contentsOf: "Test", at: result.startIndex) - verify(string: result, matches: [("TestHello, world\n", 1), ("Next Paragraph", 2)], for: \.testParagraphConstrained) - - result = str - result.characters.insert(contentsOf: "Test\nInserted ", at: result.index(result.startIndex, offsetByCharacters: 2)) - verify(string: result, matches: [("HeTest\n", 1), ("Inserted llo, world\n", 1), ("Next Paragraph", 2)], for: \.testParagraphConstrained) - - result = str - result.characters.removeSubrange(result.index(result.startIndex, offsetByCharacters: 8) ..< result.index(result.startIndex, offsetByCharacters: 14)) - verify(string: result, matches: [("Hello, wext Paragraph", 1)], for: \.testParagraphConstrained) - - result = str - result.characters.removeSubrange(result.index(result.startIndex, offsetByCharacters: 14) ..< result.endIndex) - verify(string: result, matches: [("Hello, world\n", 1), ("N", 2)], for: \.testParagraphConstrained) - - result = str - result.characters.removeSubrange(result.startIndex ..< result.index(result.startIndex, offsetByCharacters: 8)) - verify(string: result, matches: [("orld\n", 1), ("Next Paragraph", 2)], for: \.testParagraphConstrained) - - result = str - result.characters.replaceSubrange(result.index(result.startIndex, offsetByCharacters: 3) ..< result.index(result.startIndex, offsetByCharacters: 5), with: "Test") - verify(string: result, matches: [("HelTest, world\n", 1), ("Next Paragraph", 2)], for: \.testParagraphConstrained) - - result = str - result.characters.replaceSubrange(result.index(result.startIndex, offsetByCharacters: 8) ..< result.index(result.startIndex, offsetByCharacters: 15), with: "Test") - verify(string: result, matches: [("Hello, wTestxt Paragraph", 1)], for: \.testParagraphConstrained) - - result = str - result.characters.replaceSubrange(result.index(result.startIndex, offsetByCharacters: 8) ..< result.index(result.startIndex, offsetByCharacters: 15), with: "Test\nReplacement") - verify(string: result, matches: [("Hello, wTest\n", 1), ("Replacementxt Paragraph", 1)], for: \.testParagraphConstrained) - } - - func testParagraphAttributedTextMutation() { - let str = AttributedString("Hello, world\n", attributes: .init().testParagraphConstrained(1)) + AttributedString("Next Paragraph", attributes: .init().testParagraphConstrained(2)) - let singleReplacement = AttributedString("Test", attributes: .init().testParagraphConstrained(5).testSecondParagraphConstrained(6).testBool(true)) - let multiReplacement = AttributedString("Test\nInserted", attributes: .init().testParagraphConstrained(5).testSecondParagraphConstrained(6).testBool(true)) - - var result = str - result.insert(singleReplacement, at: result.index(result.startIndex, offsetByCharacters: 2)) - verify(string: result, matches: [("He", 1, nil, nil), ("Test", 1, nil, true), ("llo, world\n", 1, nil, nil), ("Next Paragraph", 2, nil, nil)], for: \.testParagraphConstrained, \.testSecondParagraphConstrained, \.testBool) - - result = str - result.insert(multiReplacement, at: result.index(result.startIndex, offsetByCharacters: 2)) - verify(string: result, matches: [("He", 1, nil, nil), ("Test\n", 1, nil, true), ("Inserted", 5, 6, true), ("llo, world\n", 5, 6, nil), ("Next Paragraph", 2, nil, nil)], for: \.testParagraphConstrained, \.testSecondParagraphConstrained, \.testBool) - - result = str - result.append(singleReplacement) - verify(string: result, matches: [("Hello, world\n", 1, nil, nil), ("Next Paragraph", 2, nil, nil), ("Test", 2, nil, true)], for: \.testParagraphConstrained, \.testSecondParagraphConstrained, \.testBool) - - result = str - result.append(multiReplacement) - verify(string: result, matches: [("Hello, world\n", 1, nil, nil), ("Next Paragraph", 2, nil, nil), ("Test\n", 2, nil, true), ("Inserted", 5, 6, true)], for: \.testParagraphConstrained, \.testSecondParagraphConstrained, \.testBool) - - result = str - result.insert(singleReplacement, at: result.startIndex) - verify(string: result, matches: [("Test", 5, 6, true), ("Hello, world\n", 5, 6, nil), ("Next Paragraph", 2, nil, nil)], for: \.testParagraphConstrained, \.testSecondParagraphConstrained, \.testBool) - - result = str - result.insert(multiReplacement, at: result.startIndex) - verify(string: result, matches: [("Test\n", 5, 6, true), ("Inserted", 5, 6, true), ("Hello, world\n", 5, 6, nil), ("Next Paragraph", 2, nil, nil)], for: \.testParagraphConstrained, \.testSecondParagraphConstrained, \.testBool) - - result = str - result.replaceSubrange(result.index(result.startIndex, offsetByCharacters: 3) ..< result.index(result.startIndex, offsetByCharacters: 5), with: singleReplacement) - verify(string: result, matches: [("Hel", 1, nil, nil), ("Test", 1, nil, true), (", world\n", 1, nil, nil), ("Next Paragraph", 2, nil, nil)], for: \.testParagraphConstrained, \.testSecondParagraphConstrained, \.testBool) - - result = str - result.replaceSubrange(result.index(result.startIndex, offsetByCharacters: 3) ..< result.index(result.startIndex, offsetByCharacters: 5), with: AttributedString("Test", attributes: .init().testBool(true))) - verify(string: result, matches: [("Hel", 1, nil, nil), ("Test", 1, nil, true), (", world\n", 1, nil, nil), ("Next Paragraph", 2, nil, nil)], for: \.testParagraphConstrained, \.testSecondParagraphConstrained, \.testBool) - - result = str - result.replaceSubrange(result.index(result.startIndex, offsetByCharacters: 3) ..< result.index(result.startIndex, offsetByCharacters: 5), with: multiReplacement) - verify(string: result, matches: [("Hel", 1, nil, nil), ("Test\n", 1, nil, true), ("Inserted", 5, 6, true), (", world\n", 5, 6, nil), ("Next Paragraph", 2, nil, nil)], for: \.testParagraphConstrained, \.testSecondParagraphConstrained, \.testBool) - - result = str - result.replaceSubrange(result.index(result.startIndex, offsetByCharacters: 8) ..< result.index(result.startIndex, offsetByCharacters: 15), with: singleReplacement) - verify(string: result, matches: [("Hello, w", 1, nil, nil), ("Test", 1, nil, true), ("xt Paragraph", 1, nil, nil)], for: \.testParagraphConstrained, \.testSecondParagraphConstrained, \.testBool) - - result = str - result.replaceSubrange(result.index(result.startIndex, offsetByCharacters: 8) ..< result.index(result.startIndex, offsetByCharacters: 15), with: multiReplacement) - verify(string: result, matches: [("Hello, w", 1, nil, nil), ("Test\n", 1, nil, true), ("Inserted", 5, 6, true), ("xt Paragraph", 5, 6, nil)], for: \.testParagraphConstrained, \.testSecondParagraphConstrained, \.testBool) - } - -#if FOUNDATION_FRAMEWORK - func testParagraphFromUntrustedRuns() throws { - let str = NSMutableAttributedString(string: "Hello ", attributes: [.testParagraphConstrained : NSNumber(2)]) - str.append(NSAttributedString(string: "World", attributes: [.testParagraphConstrained : NSNumber(3), .testSecondParagraphConstrained : NSNumber(4)])) - - let attrStr = try AttributedString(str, including: \.test) - verify(string: attrStr, matches: [("Hello World", 2, nil)], for: \.testParagraphConstrained, \.testSecondParagraphConstrained) - } -#endif // FOUNDATION_FRAMEWORK - - func testParagraphFromReplacedSubrange() { - let str = AttributedString("Before\nHello, world\nNext Paragraph\nAfter", attributes: .init().testParagraphConstrained(1)) - - // Range of "world\nNext" - let range = str.index(str.startIndex, offsetByCharacters: 14) ..< str.index(str.startIndex, offsetByCharacters: 24) - - var copy = str - copy[range].testParagraphConstrained = 2 - verify(string: copy, matches: [("Before\n", 1), ("Hello, world\n", 2), ("Next Paragraph\n", 2), ("After", 1)], for: \.testParagraphConstrained) - - copy = str - var substr = copy[range] - substr.testParagraphConstrained = 2 - copy[range] = substr - verify(string: copy, matches: [("Before\n", 1), ("Hello, world\n", 2), ("Next Paragraph\n", 2), ("After", 1)], for: \.testParagraphConstrained) - - copy = str - copy.replaceSubrange(range, with: AttributedString("not world\nNext", attributes: .init().testParagraphConstrained(2))) - verify(string: copy, matches: [("Before\n", 1), ("Hello, not world\n", 1), ("Next Paragraph\n", 2), ("After", 1)], for: \.testParagraphConstrained) - - } - - // MARK: - Character Constrained Tests - - func testCharacterAttributeApply() { - let str = AttributedString("*__*__**__*") - - var result = str - result.testCharacterConstrained = 2 - verify(string: result, matches: [("*", 2), ("__", nil), ("*", 2), ("__", nil), ("*", 2), ("*", 2), ("__", nil), ("*", 2)], for: \.testCharacterConstrained) - - result[result.index(result.endIndex, offsetByCharacters: -2) ..< result.endIndex].testCharacterConstrained = nil - verify(string: result, matches: [("*", 2), ("__", nil), ("*", 2), ("__", nil), ("*", 2), ("*", 2), ("__", nil), ("*", nil)], for: \.testCharacterConstrained) - - result = str - result[result.index(result.endIndex, offsetByCharacters: -2) ..< result.endIndex].testCharacterConstrained = 3 - verify(string: result, matches: [("*", nil), ("__", nil), ("*", nil), ("__", nil), ("*", nil), ("*", nil), ("__", nil), ("*", 3)], for: \.testCharacterConstrained) - - result.testInt = 1 - verify(string: result, matches: [("*", nil, 1), ("__", nil, 1), ("*", nil, 1), ("__", nil, 1), ("*", nil, 1), ("*", nil, 1), ("__", nil, 1), ("*", 3, 1)], for: \.testCharacterConstrained, \.testInt) - } - - func testCharacterAttributeSubCharacterApply() { - let str = AttributedString("ABC \u{FFFD} DEF") - - var result = str - result.testUnicodeScalarConstrained = 2 - verify(string: result, matches: [("ABC ", nil), ("\u{FFFD}", 2), (" DEF", nil)], for: \.testUnicodeScalarConstrained) - - result = str - result[result.startIndex ..< result.unicodeScalars.index(result.startIndex, offsetBy: 5)].testUnicodeScalarConstrained = 2 - verify(string: result, matches: [("ABC ", nil), ("\u{FFFD}", 2), (" DEF", nil)], for: \.testUnicodeScalarConstrained) - - result = str - result[result.startIndex ..< result.unicodeScalars.index(result.startIndex, offsetBy: 4)].testUnicodeScalarConstrained = 2 - verify(string: result, matches: [("ABC ", nil), ("\u{FFFD}", nil), (" DEF", nil)], for: \.testUnicodeScalarConstrained) - - result = str - result.testUnicodeScalarConstrained = 2 - result[result.unicodeScalars.index(result.startIndex, offsetBy: 5) ..< result.endIndex].testUnicodeScalarConstrained = nil - verify(string: result, matches: [("ABC ", nil), ("\u{FFFD}", 2), (" DEF", nil)], for: \.testUnicodeScalarConstrained) - - result = str - result.testUnicodeScalarConstrained = 2 - result[result.unicodeScalars.index(result.startIndex, offsetBy: 4) ..< result.endIndex].testUnicodeScalarConstrained = nil - verify(string: result, matches: [("ABC ", nil), ("\u{FFFD}", nil), (" DEF", nil)], for: \.testUnicodeScalarConstrained) - - let str2 = AttributedString("ABC \u{FFFD}\u{301} DEF") // U+FFFD Replacement Character, U+301 Combining Acute Accent - result = str2 - result.testUnicodeScalarConstrained = 2 - verify(string: result, matches: [("ABC ", nil), ("\u{FFFD}", 2), ("\u{301} DEF", nil)], for: \.testUnicodeScalarConstrained) - - } - - func testCharacterAttributeContainerReplacing() { - var str = AttributedString("*__*__**__*") - let range = str.index(afterCharacter: str.startIndex) ..< str.index(str.startIndex, offsetByCharacters: 4) - str[range].testInt = 2 - - var result = str.transformingAttributes(\.testInt) { - if $0.value == 2 { - $0.replace(with: \.testCharacterConstrained, value: 3) - } - } - verify(string: result, matches: [("*", nil, nil), ("__", nil, nil), ("*", 3, nil), ("__", nil, nil), ("*", nil, nil), ("*", nil, nil), ("__", nil, nil), ("*", nil, nil)], for: \.testCharacterConstrained, \.testInt) - - result = str.replacingAttributes(.init().testInt(2), with: .init().testCharacterConstrained(3).testBool(true)) - verify(string: result, matches: [("*", nil, nil, nil), ("__", nil, nil, true), ("*", 3, nil, true), ("__", nil, nil, nil), ("*", nil, nil, nil), ("*", nil, nil, nil), ("__", nil, nil, nil), ("*", nil, nil, nil)], for: \.testCharacterConstrained, \.testInt, \.testBool) - - str.testInt = 2 - result = str - result[range].replaceAttributes(.init().testInt(2), with: .init().testCharacterConstrained(3).testBool(true)) - verify(string: result, matches: [("*", nil, 2, nil), ("__", nil, nil, true), ("*", 3, nil, true), ("__", nil, 2, nil), ("*", nil, 2, nil), ("*", nil, 2, nil), ("__", nil, 2, nil), ("*", nil, 2, nil)], for: \.testCharacterConstrained, \.testInt, \.testBool) - } - - func testCharacterTextMutation() { - let str = AttributedString("*__*__**__*", attributes: .init().testCharacterConstrained(2)) - - var result = str - result.characters.insert(contentsOf: "_", at: result.index(result.startIndex, offsetByCharacters: 1)) - verify(string: result, matches: [("*", 2), ("___", nil), ("*", 2), ("__", nil), ("*", 2), ("*", 2), ("__", nil), ("*", 2)], for: \.testCharacterConstrained) - - result = str - result.characters.insert(contentsOf: "*", at: result.index(result.startIndex, offsetByCharacters: 1)) - verify(string: result, matches: [("*", 2), ("*", 2), ("__", nil), ("*", 2), ("__", nil), ("*", 2), ("*", 2), ("__", nil), ("*", 2)], for: \.testCharacterConstrained) - - result = str - result.characters.append(contentsOf: "_") - verify(string: result, matches: [("*", 2), ("__", nil), ("*", 2), ("__", nil), ("*", 2), ("*", 2), ("__", nil), ("*", 2), ("_", nil)], for: \.testCharacterConstrained) - - result = str - result.characters.insert(contentsOf: "_", at: result.startIndex) - verify(string: result, matches: [("_", nil), ("*", 2), ("__", nil), ("*", 2), ("__", nil), ("*", 2), ("*", 2), ("__", nil), ("*", 2)], for: \.testCharacterConstrained) - - result = str - result.characters.replaceSubrange(result.index(result.startIndex, offsetByCharacters: 3) ..< result.index(result.startIndex, offsetByCharacters: 5), with: "Test") - verify(string: result, matches: [("*", 2), ("__Test_", nil), ("*", 2), ("*", 2), ("__", nil), ("*", 2)], for: \.testCharacterConstrained) - - result = str - result.characters[result.index(result.startIndex, offsetByCharacters: 3)] = "_" - verify(string: result, matches: [("*", 2), ("_____", nil), ("*", 2), ("*", 2), ("__", nil), ("*", 2)], for: \.testCharacterConstrained) - } - -#if FOUNDATION_FRAMEWORK - func testCharacterFromUntrustedRuns() throws { - let str = NSMutableAttributedString(string: "*__*__**__*", attributes: [.testCharacterConstrained : NSNumber(2)]) - str.append(NSAttributedString(string: "_*")) - - let attrStr = try AttributedString(str, including: \.test) - verify(string: attrStr, matches: [("*", 2), ("__", nil), ("*", 2), ("__", nil), ("*", 2), ("*", 2), ("__", nil), ("*", 2), ("_", nil), ("*", nil)], for: \.testCharacterConstrained) - } -#endif // FOUNDATION_FRAMEWORK - - // MARK: Invalidation Tests - - func testInvalidationAttributeChange() { - let str = AttributedString("Hello, world", attributes: .init().testInt(1).testAttributeDependent(2)) - - var result = str - result.testString = "Foundation" - verify(string: result, matches: [("Hello, world", 1, 2, "Foundation")], for: \.testInt, \.testAttributeDependent, \.testString) - - result = str - result.testInt = 1 - verify(string: result, matches: [("Hello, world", 1, 2)], for: \.testInt, \.testAttributeDependent) - - result = str - result.testInt = 2 - verify(string: result, matches: [("Hello, world", 2, nil)], for: \.testInt, \.testAttributeDependent) - - result = str - let range = str.index(afterCharacter: str.startIndex) ..< str.index(beforeCharacter: str.endIndex) - result[range].testInt = 2 - verify(string: result, matches: [("H", 1, 2), ("ello, worl", 2, nil), ("d", 1, 2)], for: \.testInt, \.testAttributeDependent) - - result = str - result[range].mergeAttributes(.init().testInt(2)) - verify(string: result, matches: [("H", 1, 2), ("ello, worl", 2, nil), ("d", 1, 2)], for: \.testInt, \.testAttributeDependent) - - result = str - result[range].replaceAttributes(.init().testInt(1), with: .init().testString("Foundation")) - verify(string: result, matches: [("H", 1, 2, nil), ("ello, worl", nil, nil, "Foundation"), ("d", 1, 2, nil)], for: \.testInt, \.testAttributeDependent, \.testString) - - result = str.transformingAttributes(\.testInt) { - $0.value = ($0.value ?? 0) + 1 - } - verify(string: result, matches: [("Hello, world", 2, nil)], for: \.testInt, \.testAttributeDependent) - } - - func testInvalidationCharacterChange() { - let str = AttributedString("Hello, world", attributes: .init().testInt(1).testCharacterDependent(2)) - - var result = str - result.testString = "Foundation" - verify(string: result, matches: [("Hello, world", 1, 2, "Foundation")], for: \.testInt, \.testCharacterDependent, \.testString) - - result = str - result.characters.replaceSubrange(result.startIndex ..< result.endIndex, with: "ABC") - verify(string: result, matches: [("ABC", 1, nil)], for: \.testInt, \.testCharacterDependent) - - result = str - result.characters.replaceSubrange(result.startIndex ..< result.index(afterCharacter: result.startIndex), with: "AB") - verify(string: result, matches: [("ABello, world", 1, nil)], for: \.testInt, \.testCharacterDependent) - - result = str - result.characters.append(contentsOf: "ABC") - verify(string: result, matches: [("Hello, world", 1, 2), ("ABC", 1, nil)], for: \.testInt, \.testCharacterDependent) - - result = str - result.characters.removeSubrange(result.index(afterCharacter: result.startIndex) ..< result.index(beforeCharacter: result.endIndex)) - verify(string: result, matches: [("Hd", 1, nil)], for: \.testInt, \.testCharacterDependent) - - // Replacing a character with an independent instance of the same character should still - // count as changing the character data, so it needs to invalidate character-dependent - // attributes. - result = str - result.characters[result.startIndex] = "H" - verify(string: result, matches: [("Hello, world", 1, nil)], for: \.testInt, \.testCharacterDependent) - - do { - // The same is true when assigning a sub-view back to itself. Even though this doesn't - // touch text data at all, and we can quickly determine that we're in this case, we still - // want the operation to treat this as an edit. (Unlike the similar operation on - // `AttributedString` itself.) - result = str - let range = result.startIndex ..< result.index(afterCharacter: result.startIndex) - result.characters[range] = result.characters[range] - verify(string: result, matches: [("Hello, world", 1, nil)], for: \.testInt, \.testCharacterDependent) - } - - result = str - result.unicodeScalars.replaceSubrange(result.startIndex ..< result.endIndex, with: ["A", "🎺", "C"]) - verify(string: result, matches: [("A🎺C", 1, nil)], for: \.testInt, \.testCharacterDependent) - - result = str - result.unicodeScalars.replaceSubrange(result.startIndex ..< result.index(afterCharacter: result.startIndex), with: ["A", "🎺"]) - verify(string: result, matches: [("A🎺ello, world", 1, nil)], for: \.testInt, \.testCharacterDependent) - - result = str - result.unicodeScalars.append(contentsOf: ["A", "🎺", "C"]) - verify(string: result, matches: [("Hello, world", 1, 2), ("A🎺C", 1, nil)], for: \.testInt, \.testCharacterDependent) - - result = str - result.unicodeScalars.removeSubrange(result.index(afterUnicodeScalar: result.startIndex) ..< result.index(beforeUnicodeScalar: result.endIndex)) - verify(string: result, matches: [("Hd", 1, nil)], for: \.testInt, \.testCharacterDependent) - - var replacement = AttributedString("ABC", attributes: .init().testString("Hello")) - result = str - result.replaceSubrange(result.startIndex ..< result.endIndex, with: replacement) - verify(string: result, matches: [("ABC", nil, nil, "Hello")], for: \.testInt, \.testCharacterDependent, \.testString) - - result = str - result.replaceSubrange(result.startIndex ..< result.index(afterCharacter: result.startIndex), with: replacement) - verify(string: result, matches: [("ABC", nil, nil, "Hello"), ("ello, world", 1, nil, nil)], for: \.testInt, \.testCharacterDependent, \.testString) - - result = str - result.append(replacement) - verify(string: result, matches: [("Hello, world", 1, 2, nil), ("ABC", nil, nil, "Hello")], for: \.testInt, \.testCharacterDependent, \.testString) - - // Replacing a substring with a different substring of the same contents - // still counts as a text change, so it should invalidate character-dependent attributes. - result = str - replacement = AttributedString("HBC", attributes: .init().testString("Hello")) - result[result.startIndex ..< result.index(afterCharacter: result.startIndex)] = replacement[replacement.startIndex ..< replacement.index(afterCharacter: str.startIndex)] - verify(string: result, matches: [("H", nil, nil, "Hello"), ("ello, world", 1, nil, nil)], for: \.testInt, \.testCharacterDependent, \.testString) - } - -} diff --git a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringDiscontiguousTests.swift b/Tests/FoundationEssentialsTests/AttributedString/AttributedStringDiscontiguousTests.swift deleted file mode 100644 index 79b7fa344..000000000 --- a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringDiscontiguousTests.swift +++ /dev/null @@ -1,340 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2020 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -final class AttributedStringDiscontiguousTests: XCTestCase { - func testEmptySlice() { - let str = AttributedString() - let slice = str[RangeSet()] - XCTAssertTrue(slice.runs.isEmpty) - XCTAssertTrue(slice.characters.isEmpty) - XCTAssertTrue(slice.unicodeScalars.isEmpty) - XCTAssertEqual(slice, slice) - XCTAssertEqual(slice.runs.startIndex, slice.runs.endIndex) - XCTAssertEqual(slice.characters.startIndex, slice.characters.endIndex) - XCTAssertEqual(slice.unicodeScalars.startIndex, slice.unicodeScalars.endIndex) - XCTAssertEqual(AttributedString("abc")[RangeSet()], AttributedString("def")[RangeSet()]) - - for r in slice.runs { - XCTFail("Enumerating empty runs should not have produced \(r)") - } - for c in slice.characters { - XCTFail("Enumerating empty characters should not have produced \(c)") - } - for s in slice.unicodeScalars { - XCTFail("Enumerating empty unicode scalars should not have produced \(s)") - } - } - - func testCharacters() { - let str = AttributedString("abcdefgabc") - let fullSlice = str[str.startIndex ..< str.endIndex].characters - let fullDiscontiguousSlice = str[RangeSet(str.startIndex ..< str.endIndex)].characters - XCTAssertTrue(fullSlice.elementsEqual(fullDiscontiguousSlice)) - - let rangeA = str.startIndex ..< str.index(str.startIndex, offsetByCharacters: 3) - let rangeB = str.index(str.endIndex, offsetByCharacters: -3) ..< str.endIndex - let rangeSet = RangeSet([rangeA, rangeB]) - let slice = str[rangeSet].characters - XCTAssertEqual(Array(slice), ["a", "b", "c", "a", "b", "c"]) - } - - func testUnicodeScalars() { - let str = AttributedString("abcdefgabc") - let fullSlice = str[str.startIndex ..< str.endIndex].unicodeScalars - let fullDiscontiguousSlice = str[RangeSet(str.startIndex ..< str.endIndex)].unicodeScalars - XCTAssertTrue(fullSlice.elementsEqual(fullDiscontiguousSlice)) - - let rangeA = str.startIndex ..< str.index(str.startIndex, offsetByUnicodeScalars: 3) - let rangeB = str.index(str.endIndex, offsetByUnicodeScalars: -3) ..< str.endIndex - let rangeSet = RangeSet([rangeA, rangeB]) - let slice = str[rangeSet].unicodeScalars - XCTAssertEqual(Array(slice), ["a", "b", "c", "a", "b", "c"]) - } - - func testAttributes() { - let str = AttributedString("abcdefg") - let rangeA = str.startIndex ..< str.index(str.startIndex, offsetByCharacters: 1) - let rangeB = str.index(str.startIndex, offsetByCharacters: 2) ..< str.index(str.startIndex, offsetByCharacters: 3) - let rangeC = str.index(str.startIndex, offsetByCharacters: 4) ..< str.index(str.startIndex, offsetByCharacters: 5) - let ranges = RangeSet([rangeA, rangeB, rangeC]) - - do { - var a = str - a[ranges].testInt = 2 - var b = str - for range in ranges.ranges { - b[range].testInt = 2 - } - XCTAssertEqual(a, b) - } - - do { - var a = str - a[ranges].test.testInt = 2 - var b = str - for range in ranges.ranges { - b[range].test.testInt = 2 - } - XCTAssertEqual(a, b) - } - - do { - var a = str - a[ranges][AttributeScopes.TestAttributes.TestIntAttribute.self] = 2 - var b = str - for range in ranges.ranges { - b[range][AttributeScopes.TestAttributes.TestIntAttribute.self] = 2 - } - XCTAssertEqual(a, b) - } - - do { - var a = str - a.testInt = 3 - a[ranges].testInt = nil - var b = str - b.testInt = 3 - for range in ranges.ranges { - b[range].testInt = nil - } - XCTAssertEqual(a, b) - } - - do { - var a = str - a.testInt = 2 - XCTAssertEqual(a[ranges].testInt, 2) - a[rangeA].testInt = 3 - XCTAssertEqual(a[ranges].testInt, nil) - } - - do { - var a = str - a.testString = "foo" - a[ranges].mergeAttributes(AttributeContainer.testInt(2)) - var b = str - b.testString = "foo" - for range in ranges.ranges { - b[range].mergeAttributes(AttributeContainer.testInt(2)) - } - XCTAssertEqual(a, b) - } - - do { - var a = str - a.testString = "foo" - a[ranges].setAttributes(AttributeContainer.testInt(2)) - var b = str - b.testString = "foo" - for range in ranges.ranges { - b[range].setAttributes(AttributeContainer.testInt(2)) - } - XCTAssertEqual(a, b) - } - - do { - var a = str - a.testString = "foo" - a[ranges].replaceAttributes(AttributeContainer(), with: AttributeContainer.testInt(2)) - var b = str - b.testString = "foo" - for range in ranges.ranges { - b[range].replaceAttributes(AttributeContainer(), with: AttributeContainer.testInt(2)) - } - XCTAssertEqual(a, b) - } - - do { - var a = str - a.testString = "foo" - a[ranges].replaceAttributes(AttributeContainer.testString("foo"), with: AttributeContainer.testInt(2)) - var b = str - b.testString = "foo" - for range in ranges.ranges { - b[range].replaceAttributes(AttributeContainer.testString("foo"), with: AttributeContainer.testInt(2)) - } - XCTAssertEqual(a, b) - } - } - - func testReinitialization() { - var str = AttributedString("abcdefg") - let rangeA = str.startIndex ..< str.index(str.startIndex, offsetByCharacters: 1) - let rangeB = str.index(str.startIndex, offsetByCharacters: 2) ..< str.index(str.startIndex, offsetByCharacters: 3) - let rangeC = str.index(str.startIndex, offsetByCharacters: 4) ..< str.index(str.startIndex, offsetByCharacters: 5) - let ranges = RangeSet([rangeA, rangeB, rangeC]) - str[ranges].testInt = 2 - - let reinitialized = AttributedString(str[ranges]) - XCTAssertEqual(reinitialized, AttributedString("ace", attributes: AttributeContainer.testInt(2))) - } - - func testReslicing() { - var str = AttributedString("abcdefg") - let rangeA = str.startIndex ..< str.index(str.startIndex, offsetByCharacters: 1) - let rangeB = str.index(str.startIndex, offsetByCharacters: 2) ..< str.index(str.startIndex, offsetByCharacters: 3) - let rangeC = str.index(str.startIndex, offsetByCharacters: 4) ..< str.index(str.startIndex, offsetByCharacters: 5) - let ranges = RangeSet([rangeA, rangeB, rangeC]) - str[ranges].testInt = 2 - - XCTAssertEqual(str[ranges], str[ranges][ranges]) - XCTAssertEqual(AttributedString(str[ranges][RangeSet([rangeA, rangeB])]), AttributedString("ac", attributes: AttributeContainer.testInt(2))) - XCTAssertEqual(AttributedString(str[ranges][rangeA.lowerBound ..< rangeB.upperBound]), AttributedString("ac", attributes: AttributeContainer.testInt(2))) - - XCTAssertEqual(str[RangeSet()][RangeSet()], str[RangeSet()]) - } - - func testRuns() { - var str = AttributedString("AAA", attributes: AttributeContainer.testInt(2)) - str += AttributedString("BBB", attributes: AttributeContainer.testInt(3).testString("foo")) - str += AttributedString("CC", attributes: AttributeContainer.testInt(3).testString("bar")) - str += AttributedString("D", attributes: AttributeContainer.testInt(3).testString("baz")) - str += AttributedString("EEEEEEEE") - - let rangeA = str.index(str.startIndex, offsetByCharacters: 1) ..< str.index(str.startIndex, offsetByCharacters: 2) // A - let rangeB = str.index(str.startIndex, offsetByCharacters: 4) ..< str.index(str.startIndex, offsetByCharacters: 7) // BBC (2 runs) - let rangeC = str.index(str.startIndex, offsetByCharacters: 8) ..< str.index(str.startIndex, offsetByCharacters: 9) // D - let rangeD = str.index(str.startIndex, offsetByCharacters: 10) ..< str.index(str.startIndex, offsetByCharacters: 11) // E - let rangeE = str.index(str.startIndex, offsetByCharacters: 12) ..< str.index(str.startIndex, offsetByCharacters: 13) // E - let rangeSet = RangeSet([rangeA, rangeB, rangeC, rangeD, rangeE]) - - let rangeB_first = str.index(str.startIndex, offsetByCharacters: 4) ..< str.index(str.startIndex, offsetByCharacters: 6) - let rangeB_second = str.index(str.startIndex, offsetByCharacters: 6) ..< str.index(str.startIndex, offsetByCharacters: 7) - - let runs = str[rangeSet].runs - let expectedRanges = [rangeA, rangeB_first, rangeB_second, rangeC, rangeD, rangeE] - XCTAssertEqual(runs.count, expectedRanges.count) - XCTAssertEqual(runs.reversed().count, expectedRanges.reversed().count) - XCTAssertEqual(runs.map(\.range), expectedRanges) - XCTAssertEqual(runs.reversed().map(\.range), expectedRanges.reversed()) - } - - func testCoalescedRuns() { - struct EquatableBox: Equatable, CustomStringConvertible { - let t: T - let u: U - - var description: String { - "(\(String(describing: t)), \(String(describing: u)))" - } - - init(_ values: (T, U)) { - self.t = values.0 - self.u = values.1 - } - - init(_ t: T, _ u: U) { - self.t = t - self.u = u - } - } - var str = AttributedString("AAA", attributes: AttributeContainer.testInt(2)) - str += AttributedString("BBB", attributes: AttributeContainer.testInt(3).testString("foo")) - str += AttributedString("CC", attributes: AttributeContainer.testInt(3).testString("bar")) - str += AttributedString("D", attributes: AttributeContainer.testInt(3).testString("baz")) - str += AttributedString("EEEEEEEE") - - let rangeA = str.index(str.startIndex, offsetByCharacters: 1) ..< str.index(str.startIndex, offsetByCharacters: 2) // A - let rangeB = str.index(str.startIndex, offsetByCharacters: 4) ..< str.index(str.startIndex, offsetByCharacters: 7) // BBC (2 runs) - let rangeC = str.index(str.startIndex, offsetByCharacters: 8) ..< str.index(str.startIndex, offsetByCharacters: 9) // D - let rangeD = str.index(str.startIndex, offsetByCharacters: 10) ..< str.index(str.startIndex, offsetByCharacters: 11) // E - let rangeE = str.index(str.startIndex, offsetByCharacters: 12) ..< str.index(str.startIndex, offsetByCharacters: 13) // E - let rangeSet = RangeSet([rangeA, rangeB, rangeC, rangeD, rangeE]) - - let rangeB_first = str.index(str.startIndex, offsetByCharacters: 4) ..< str.index(str.startIndex, offsetByCharacters: 6) - let rangeB_second = str.index(str.startIndex, offsetByCharacters: 6) ..< str.index(str.startIndex, offsetByCharacters: 7) - - let runs = str[rangeSet].runs - - let testIntExpectation = [EquatableBox(2, rangeA), EquatableBox(3, rangeB), EquatableBox(3, rangeC), EquatableBox(nil, rangeD), EquatableBox(nil, rangeE)] - XCTAssertEqual(runs[\.testInt].map(EquatableBox.init), testIntExpectation) - XCTAssertEqual(runs[\.testInt].reversed().map(EquatableBox.init), testIntExpectation.reversed()) - - let testStringExpectation = [EquatableBox(nil, rangeA), EquatableBox("foo", rangeB_first), EquatableBox("bar", rangeB_second), EquatableBox("baz", rangeC), EquatableBox(nil, rangeD), EquatableBox(nil, rangeE)] - XCTAssertEqual(runs[\.testString].map(EquatableBox.init), testStringExpectation) - XCTAssertEqual(runs[\.testString].reversed().map(EquatableBox.init), testStringExpectation.reversed()) - } - - func testRemoveSubranges() { - var str = AttributedString("abcdefg") - let rangeA = str.startIndex ..< str.index(str.startIndex, offsetByCharacters: 1) - let rangeB = str.index(str.startIndex, offsetByCharacters: 2) ..< str.index(str.startIndex, offsetByCharacters: 3) - let rangeC = str.index(str.startIndex, offsetByCharacters: 4) ..< str.index(str.startIndex, offsetByCharacters: 5) - let ranges = RangeSet([rangeA, rangeB, rangeC]) - str[ranges].testInt = 2 - str.testBool = true - str[rangeA].testString = "foo" - - str.removeSubranges(ranges) - let result = AttributedString("bdfg", attributes: AttributeContainer.testBool(true)) - XCTAssertEqual(str, result) - } - - func testSliceSetter() { - var str = AttributedString("abcdefg") - let rangeA = str.startIndex ..< str.index(str.startIndex, offsetByCharacters: 1) - let rangeB = str.index(str.startIndex, offsetByCharacters: 2) ..< str.index(str.startIndex, offsetByCharacters: 3) - let rangeC = str.index(str.startIndex, offsetByCharacters: 4) ..< str.index(str.startIndex, offsetByCharacters: 5) - let ranges = RangeSet([rangeA, rangeB, rangeC]) - str[ranges].testInt = 2 - str.testBool = true - str[rangeA].testString = "foo" - - do { - var copy = str - copy[ranges] = copy[ranges] - XCTAssertEqual(copy, str) - } - - do { - var copy = str - copy[ranges] = str[ranges] - XCTAssertEqual(copy, str) - } - - do { - let str2 = AttributedString("Z_Y_X__") - let rangeA2 = str2.startIndex ..< str2.index(str2.startIndex, offsetByCharacters: 1) - let rangeB2 = str2.index(str.startIndex, offsetByCharacters: 2) ..< str2.index(str2.startIndex, offsetByCharacters: 3) - let rangeC2 = str2.index(str.startIndex, offsetByCharacters: 4) ..< str2.index(str2.startIndex, offsetByCharacters: 5) - let ranges2 = RangeSet([rangeA2, rangeB2, rangeC2]) - var copy = str - copy[ranges] = str2[ranges2] - XCTAssertEqual(String(copy.characters), "ZbYdXfg") - } - } - - func testGraphemesAcrossDiscontiguousRanges() { - let str = "a\n\u{301}" - let attrStr = AttributedString(str) - let strRangeA = str.startIndex ..< str.index(after: str.startIndex) // Range of 'a' - let strRangeB = str.index(before: str.endIndex) ..< str.endIndex // Range of '\u{301}' - let attrStrRangeA = attrStr.startIndex ..< attrStr.index(afterCharacter: attrStr.startIndex) // Range of 'a' - let attrStrRangeB = attrStr.index(beforeCharacter: attrStr.endIndex) ..< attrStr.endIndex // Range of '\u{301}' - let strRanges = RangeSet([strRangeA, strRangeB]) - let attrStrRanges = RangeSet([attrStrRangeA, attrStrRangeB]) - - // These discontiguous slices represent subranges that include the scalar 'a' followed by \u{301} - // Unicode grapheme breaking rules dictate that these two unicode scalars form one grapheme cluster - // While it may be considered unexpected, DiscontiguousSlice nor DiscontiguousSlice today will not combine these together and instead produce two Character elements - // However, the important behavior that we are testing here is that: - // (1) Slicing in this manner does not crash - // (2) The behavior is consistent between String and AttributedString.CharacterView - let strSlice = str[strRanges] - let attrStrSlice = attrStr[attrStrRanges].characters - XCTAssert(strSlice.elementsEqual(attrStrSlice), "Characters \(Array(strSlice)) and \(Array(attrStrSlice)) do not match") - } -} diff --git a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringIndexTrackingTests.swift b/Tests/FoundationEssentialsTests/AttributedString/AttributedStringIndexTrackingTests.swift deleted file mode 100644 index 01f2c5bf1..000000000 --- a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringIndexTrackingTests.swift +++ /dev/null @@ -1,211 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2020 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -final class AttributedStringIndexTrackingTests: XCTestCase { - func testBasic() throws { - var text = AttributedString("ABC. Hello, world!") - let original = text - let helloRange = try XCTUnwrap(text.range(of: "Hello")) - let worldRange = try XCTUnwrap(text.range(of: "world")) - - let updatedRanges = try XCTUnwrap(text.transform(updating: [helloRange, worldRange]) { - $0.insert(AttributedString("Goodbye. "), at: $0.startIndex) - }) - - XCTAssertEqual(updatedRanges.count, 2) - XCTAssertEqual(text[updatedRanges[0]], original[helloRange]) - XCTAssertEqual(text[updatedRanges[1]], original[worldRange]) - } - - func testInsertionWithinRange() throws { - var text = AttributedString("Hello, world") - var helloRange = try XCTUnwrap(text.range(of: "Hello")) - - text.transform(updating: &helloRange) { - $0.insert(AttributedString("_Goodbye_"), at: $0.index($0.startIndex, offsetByCharacters: 3)) - } - - XCTAssertEqual(String(text[helloRange].characters), "Hel_Goodbye_lo") - } - - func testInsertionAtStartOfRange() throws { - var text = AttributedString("Hello, world") - let helloRange = try XCTUnwrap(text.range(of: "llo")) - - let updatedHelloRange = try XCTUnwrap(text.transform(updating: helloRange) { - $0.insert(AttributedString("_"), at: helloRange.lowerBound) - }) - - XCTAssertEqual(String(text[updatedHelloRange].characters), "llo") - } - - func testInsertionAtEndOfRange() throws { - var text = AttributedString("Hello, world") - let helloRange = try XCTUnwrap(text.range(of: "llo")) - - let updatedHelloRange = try XCTUnwrap(text.transform(updating: helloRange) { - $0.insert(AttributedString("_"), at: helloRange.upperBound) - }) - - XCTAssertEqual(String(text[updatedHelloRange].characters), "llo") - } - - func testInsertionAtEmptyRange() throws { - var text = AttributedString("ABCDE") - let idx = text.index(text.startIndex, offsetByCharacters: 3) - - let updatedRange = try XCTUnwrap(text.transform(updating: idx ..< idx) { - $0.insert(AttributedString("_"), at: idx) - }) - - XCTAssertEqual(updatedRange.lowerBound, updatedRange.upperBound) - XCTAssertEqual(text.characters[updatedRange.lowerBound], "D") - } - - func testRemovalWithinRange() throws { - var text = AttributedString("Hello, world") - var helloRange = try XCTUnwrap(text.range(of: "Hello")) - - try text.transform(updating: &helloRange) { - $0.removeSubrange(try XCTUnwrap($0.range(of: "ll"))) - } - - XCTAssertEqual(String(text[helloRange].characters), "Heo") - } - - func testFullCollapse() throws { - do { - var text = AttributedString("Hello, world") - var helloRange = try XCTUnwrap(text.range(of: "Hello")) - - text.transform(updating: &helloRange) { - $0.removeSubrange($0.startIndex ..< $0.endIndex) - } - - XCTAssertEqual(String(text[helloRange].characters), "") - } - - do { - var text = AttributedString("Hello, world") - let helloRange = try XCTUnwrap(text.range(of: "Hello")) - - let updatedHelloRange = try XCTUnwrap(text.transform(updating: helloRange) { - $0.removeSubrange(helloRange) - }) - - XCTAssertEqual(String(text[updatedHelloRange].characters), "") - } - - do { - var text = AttributedString("Hello, world") - var helloRange = try XCTUnwrap(text.range(of: ", ")) - - try text.transform(updating: &helloRange) { - $0.removeSubrange(try XCTUnwrap($0.range(of: "o, w"))) - } - - XCTAssertEqual(String(text[helloRange].characters), "") - let collapsedIdx = text.index(text.startIndex, offsetByCharacters: 4) - XCTAssertEqual(helloRange, collapsedIdx ..< collapsedIdx) - } - } - - func testCollapseLeft() throws { - var text = AttributedString("Hello, world") - var helloRange = try XCTUnwrap(text.range(of: "Hello")) - - try text.transform(updating: &helloRange) { - $0.removeSubrange(try XCTUnwrap($0.range(of: "llo, wo"))) - } - - XCTAssertEqual(String(text[helloRange].characters), "He") - } - - func testCollapseRight() throws { - var text = AttributedString("Hello, world") - var worldRange = try XCTUnwrap(text.range(of: "world")) - - try text.transform(updating: &worldRange) { - $0.removeSubrange(try XCTUnwrap($0.range(of: "llo, wo"))) - } - - XCTAssertEqual(String(text[worldRange].characters), "rld") - } - - func testNesting() throws { - var text = AttributedString("Hello, world") - var helloRange = try XCTUnwrap(text.range(of: "Hello")) - try text.transform(updating: &helloRange) { - var worldRange = try XCTUnwrap($0.range(of: "world")) - try $0.transform(updating: &worldRange) { - $0.removeSubrange(try XCTUnwrap($0.range(of: "llo, wo"))) - } - XCTAssertEqual(String($0[worldRange].characters), "rld") - } - XCTAssertEqual(String(text[helloRange].characters), "He") - } - - func testTrackingLost() throws { - let text = AttributedString("Hello, world") - let helloRange = try XCTUnwrap(text.range(of: "Hello")) - - do { - var copy = text - XCTAssertNil(copy.transform(updating: helloRange) { - $0 = AttributedString("Foo") - }) - } - - do { - var copy = text - XCTAssertNil(copy.transform(updating: helloRange) { - $0 = AttributedString("Hello world") - }) - } - - do { - var copy = text - XCTAssertNotNil(copy.transform(updating: helloRange) { - $0 = $0 - }) - } - - do { - var copy = text - XCTAssertNotNil(copy.transform(updating: helloRange) { - var reference = $0 - reference.testInt = 2 - $0 = $0 - }) - XCTAssertNil(copy.testInt) - } - } - - func testAttributeMutation() throws { - var text = AttributedString("Hello, world!") - let original = text - let helloRange = try XCTUnwrap(text.range(of: "Hello")) - let worldRange = try XCTUnwrap(text.range(of: "world")) - - let updatedRanges = try XCTUnwrap(text.transform(updating: [helloRange, worldRange]) { - $0.testInt = 2 - }) - - XCTAssertEqual(updatedRanges.count, 2) - XCTAssertEqual(AttributedString(text[updatedRanges[0]]), original[helloRange].settingAttributes(AttributeContainer.testInt(2))) - XCTAssertEqual(AttributedString(text[updatedRanges[1]]), original[worldRange].settingAttributes(AttributeContainer.testInt(2))) - } -} diff --git a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringIndexValidityTests.swift b/Tests/FoundationEssentialsTests/AttributedString/AttributedStringIndexValidityTests.swift deleted file mode 100644 index c9a10e600..000000000 --- a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringIndexValidityTests.swift +++ /dev/null @@ -1,213 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -final class AttributedStringIndexValidityTests: XCTestCase { - public func testStartEndRange() { - let str = AttributedString("Hello, world") - - XCTAssertTrue(str.startIndex.isValid(within: str)) - XCTAssertFalse(str.endIndex.isValid(within: str)) - XCTAssertTrue((str.startIndex ..< str.endIndex).isValid(within: str)) - XCTAssertTrue((str.startIndex ..< str.startIndex).isValid(within: str)) - XCTAssertTrue((str.endIndex ..< str.endIndex).isValid(within: str)) - - let subStart = str.index(afterCharacter: str.startIndex) - let subEnd = str.index(beforeCharacter: str.endIndex) - - do { - let substr = str[str.startIndex ..< str.endIndex] - XCTAssertTrue(substr.startIndex.isValid(within: substr)) - XCTAssertFalse(substr.endIndex.isValid(within: substr)) - XCTAssertTrue((substr.startIndex ..< substr.endIndex).isValid(within: substr)) - } - - do { - let substr = str[subStart ..< str.endIndex] - XCTAssertTrue(substr.startIndex.isValid(within: substr)) - XCTAssertFalse(substr.endIndex.isValid(within: substr)) - XCTAssertTrue((substr.startIndex ..< substr.endIndex).isValid(within: substr)) - } - - do { - let substr = str[str.startIndex ..< subEnd] - XCTAssertTrue(substr.startIndex.isValid(within: substr)) - XCTAssertFalse(substr.endIndex.isValid(within: substr)) - XCTAssertTrue((substr.startIndex ..< substr.endIndex).isValid(within: substr)) - } - - do { - let substr = str[subStart ..< subEnd] - XCTAssertTrue(substr.startIndex.isValid(within: substr)) - XCTAssertFalse(substr.endIndex.isValid(within: substr)) - XCTAssertTrue((substr.startIndex ..< substr.endIndex).isValid(within: substr)) - XCTAssertTrue((substr.startIndex ..< substr.startIndex).isValid(within: substr)) - XCTAssertTrue((substr.endIndex ..< substr.endIndex).isValid(within: substr)) - } - - do { - let substr = str[RangeSet(str.startIndex ..< str.endIndex)] - XCTAssertTrue(str.startIndex.isValid(within: substr)) - XCTAssertFalse(str.endIndex.isValid(within: substr)) - XCTAssertTrue((str.startIndex ..< str.endIndex).isValid(within: substr)) - } - - do { - let substr = str[RangeSet(subStart ..< str.endIndex)] - XCTAssertTrue(subStart.isValid(within: substr)) - XCTAssertFalse(str.endIndex.isValid(within: substr)) - XCTAssertTrue((subStart ..< str.endIndex).isValid(within: substr)) - } - - do { - let substr = str[RangeSet(str.startIndex ..< subEnd)] - XCTAssertTrue(str.startIndex.isValid(within: substr)) - XCTAssertFalse(subEnd.isValid(within: substr)) - XCTAssertTrue((str.startIndex ..< subEnd).isValid(within: substr)) - } - - do { - let substr = str[RangeSet(subStart ..< subEnd)] - XCTAssertTrue(subStart.isValid(within: substr)) - XCTAssertFalse(subEnd.isValid(within: substr)) - XCTAssertTrue((subStart ..< subEnd).isValid(within: substr)) - XCTAssertTrue((subStart ..< subStart).isValid(within: substr)) - XCTAssertTrue((subEnd ..< subEnd).isValid(within: substr)) - } - } - - public func testExhaustiveIndices() { - let str = AttributedString("Hello Cafe\u{301} ðŸ‘ðŸ»ðŸ‡ºðŸ‡¸ World") - for idx in str.characters.indices { - XCTAssertTrue(idx.isValid(within: str)) - } - for idx in str.unicodeScalars.indices { - XCTAssertTrue(idx.isValid(within: str)) - } - for idx in str.utf8.indices { - XCTAssertTrue(idx.isValid(within: str)) - } - for idx in str.utf16.indices { - XCTAssertTrue(idx.isValid(within: str)) - } - } - - public func testOutOfBoundsContiguous() { - let str = AttributedString("Hello, world") - let subStart = str.index(afterCharacter: str.startIndex) - let subEnd = str.index(beforeCharacter: str.endIndex) - let substr = str[subStart ..< subEnd] - - XCTAssertFalse(str.startIndex.isValid(within: substr)) - XCTAssertFalse(str.endIndex.isValid(within: substr)) - XCTAssertFalse((str.startIndex ..< str.endIndex).isValid(within: substr)) - XCTAssertFalse((str.startIndex ..< substr.startIndex).isValid(within: substr)) - XCTAssertFalse((substr.startIndex ..< str.endIndex).isValid(within: substr)) - XCTAssertFalse((str.startIndex ..< str.startIndex).isValid(within: substr)) - XCTAssertFalse((str.endIndex ..< str.endIndex).isValid(within: substr)) - } - - public func testOutOfBoundsDiscontiguous() { - let str = AttributedString("Hello, world") - let idxA = str.index(afterCharacter: str.startIndex) - let idxB = str.index(afterCharacter: idxA) - let idxD = str.index(beforeCharacter: str.endIndex) - let idxC = str.index(beforeCharacter: idxD) - let middleIdx = str.index(afterCharacter: idxB) - let substr = str[RangeSet([idxA ..< idxB, idxC ..< idxD])] - - XCTAssertFalse(str.startIndex.isValid(within: substr)) - XCTAssertFalse(str.endIndex.isValid(within: substr)) - XCTAssertFalse(idxD.isValid(within: substr)) - XCTAssertFalse(middleIdx.isValid(within: substr)) - XCTAssertFalse((str.startIndex ..< idxA).isValid(within: substr)) - XCTAssertFalse((idxA ..< middleIdx).isValid(within: substr)) - XCTAssertFalse((middleIdx ..< idxD).isValid(within: substr)) - XCTAssertFalse((str.startIndex ..< str.startIndex).isValid(within: substr)) - XCTAssertFalse((str.endIndex ..< str.endIndex).isValid(within: substr)) - } - - public func testMutationInvalidation() { - func checkInPlace(_ mutation: (inout AttributedString) -> (), file: StaticString = #file, line: UInt = #line) { - var str = AttributedString("Hello World") - let idxA = str.startIndex - let idxB = str.index(afterCharacter: idxA) - - XCTAssertTrue(idxA.isValid(within: str), "Initial index A was invalid in original", file: file, line: line) - XCTAssertTrue(idxB.isValid(within: str), "Initial index B was invalid in original", file: file, line: line) - XCTAssertTrue((idxA ..< idxB).isValid(within: str), "Initial range was invalid in original", file: file, line: line) - XCTAssertTrue(RangeSet(idxA ..< idxB).isValid(within: str), "Initial range set was invalid in original", file: file, line: line) - - mutation(&str) - - XCTAssertFalse(idxA.isValid(within: str), "Initial index A was valid in in-place mutated", file: file, line: line) - XCTAssertFalse(idxB.isValid(within: str), "Initial index B was valid in in-place mutated", file: file, line: line) - XCTAssertFalse((idxA ..< idxB).isValid(within: str), "Initial range was valid in in-place mutated", file: file, line: line) - XCTAssertFalse(RangeSet(idxA ..< idxB).isValid(within: str), "Initial range set was valid in in-place mutated", file: file, line: line) - } - - func checkCopy(_ mutation: (inout AttributedString) -> (), file: StaticString = #file, line: UInt = #line) { - let str = AttributedString("Hello World") - let idxA = str.startIndex - let idxB = str.index(afterCharacter: idxA) - - var copy = str - XCTAssertTrue(idxA.isValid(within: str), "Initial index A was invalid in original", file: file, line: line) - XCTAssertTrue(idxB.isValid(within: str), "Initial index B was invalid in original", file: file, line: line) - XCTAssertTrue((idxA ..< idxB).isValid(within: str), "Initial range was invalid in original", file: file, line: line) - XCTAssertTrue(RangeSet(idxA ..< idxB).isValid(within: str), "Initial range set was invalid in original", file: file, line: line) - XCTAssertTrue(idxA.isValid(within: copy), "Initial index A was invalid in copy", file: file, line: line) - XCTAssertTrue(idxB.isValid(within: copy), "Initial index B was invalid in copy", file: file, line: line) - XCTAssertTrue((idxA ..< idxB).isValid(within: copy), "Initial range was invalid in copy", file: file, line: line) - XCTAssertTrue(RangeSet(idxA ..< idxB).isValid(within: copy), "Initial range set was invalid in copy", file: file, line: line) - - mutation(©) - - XCTAssertTrue(idxA.isValid(within: str), "Initial index A was invalid in original after copy", file: file, line: line) - XCTAssertTrue(idxB.isValid(within: str), "Initial index B was invalid in original after copy", file: file, line: line) - XCTAssertTrue((idxA ..< idxB).isValid(within: str), "Initial range was invalid in original after copy", file: file, line: line) - XCTAssertTrue(RangeSet(idxA ..< idxB).isValid(within: str), "Initial range set was invalid in original after copy", file: file, line: line) - XCTAssertFalse(idxA.isValid(within: copy), "Initial index A was valid in copy", file: file, line: line) - XCTAssertFalse(idxB.isValid(within: copy), "Initial index B was valid in copy", file: file, line: line) - XCTAssertFalse((idxA ..< idxB).isValid(within: copy), "Initial range was valid in copy", file: file, line: line) - XCTAssertFalse(RangeSet(idxA ..< idxB).isValid(within: copy), "Initial range set was valid in copy", file: file, line: line) - } - - func check(_ mutation: (inout AttributedString) -> (), file: StaticString = #file, line: UInt = #line) { - checkInPlace(mutation, file: file, line: line) - checkCopy(mutation, file: file, line: line) - } - - check { - $0.replaceSubrange($0.startIndex ..< $0.endIndex, with: AttributedString("Hello")) - } - - check { - $0.testInt = 2 - } - - check { - $0.characters.append(contentsOf: "Hello") - } - - check { - $0.unicodeScalars.remove(at: $0.startIndex) - } - - check { - $0[$0.startIndex ..< $0.index(afterCharacter: $0.startIndex)].testInt = 2 - } - } -} diff --git a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringTestSupport.swift b/Tests/FoundationEssentialsTests/AttributedString/AttributedStringTestSupport.swift deleted file mode 100644 index 78e78bee3..000000000 --- a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringTestSupport.swift +++ /dev/null @@ -1,169 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2020 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if FOUNDATION_FRAMEWORK -extension NSAttributedString.Key { - static let testInt = NSAttributedString.Key("TestInt") - static let testString = NSAttributedString.Key("TestString") - static let testDouble = NSAttributedString.Key("TestDouble") - static let testBool = NSAttributedString.Key("TestBool") - static let testParagraphConstrained = NSAttributedString.Key("TestParagraphConstrained") - static let testSecondParagraphConstrained = NSAttributedString.Key("TestSecondParagraphConstrained") - static let testCharacterConstrained = NSAttributedString.Key("TestCharacterConstrained") -} -#endif - -extension AttributeScopes.TestAttributes { - - enum TestIntAttribute: CodableAttributedStringKey { - typealias Value = Int - static let name = "TestInt" - } - - enum TestStringAttribute: CodableAttributedStringKey { - typealias Value = String - static let name = "TestString" - } - - enum TestDoubleAttribute: CodableAttributedStringKey { - typealias Value = Double - static let name = "TestDouble" - } - - enum TestBoolAttribute: CodableAttributedStringKey { - typealias Value = Bool - static let name = "TestBool" - } - - enum TestNonExtended: CodableAttributedStringKey { - typealias Value = Int - static let name = "TestNonExtended" - static let inheritedByAddedText: Bool = false - } - - enum TestParagraphConstrained: CodableAttributedStringKey { - typealias Value = Int - static let name = "TestParagraphConstrained" - static let runBoundaries: AttributedString.AttributeRunBoundaries? = .paragraph - } - - enum TestSecondParagraphConstrained: CodableAttributedStringKey { - typealias Value = Int - static let name = "TestSecondParagraphConstrained" - static let runBoundaries: AttributedString.AttributeRunBoundaries? = .paragraph - } - - enum TestCharacterConstrained: CodableAttributedStringKey { - typealias Value = Int - static let name = "TestCharacterConstrained" - static let runBoundaries: AttributedString.AttributeRunBoundaries? = .character("*") - } - - enum TestUnicodeCharacterConstrained: CodableAttributedStringKey { - typealias Value = Int - static let name = "TestUnicodeCharacterConstrained" - static let runBoundaries: AttributedString.AttributeRunBoundaries? = .character("\u{FFFD}") // U+FFFD Replacement Character - } - - enum TestAttributeDependent: CodableAttributedStringKey { - typealias Value = Int - static let name = "TestAttributeDependent" - static let invalidationConditions: Set? = [.attributeChanged(\.testInt)] - } - - enum TestCharacterDependent: CodableAttributedStringKey { - typealias Value = Int - static let name = "TestCharacterDependent" - static let invalidationConditions: Set? = [.textChanged] - } - - enum NonCodableAttribute : AttributedStringKey { - typealias Value = NonCodableType - static let name = "NonCodable" - } - - enum CustomCodableAttribute : CodableAttributedStringKey { - typealias Value = NonCodableType - static let name = "NonCodableConvertible" - - static func encode(_ value: NonCodableType, to encoder: Encoder) throws { - var c = encoder.singleValueContainer() - try c.encode(value.inner) - } - - static func decode(from decoder: Decoder) throws -> NonCodableType { - let c = try decoder.singleValueContainer() - let inner = try c.decode(Int.self) - return NonCodableType(inner: inner) - } - } -} - -#if FOUNDATION_FRAMEWORK -extension AttributeScopes.TestAttributes.TestIntAttribute : MarkdownDecodableAttributedStringKey {} -extension AttributeScopes.TestAttributes.TestStringAttribute : MarkdownDecodableAttributedStringKey {} -extension AttributeScopes.TestAttributes.TestBoolAttribute : MarkdownDecodableAttributedStringKey {} -extension AttributeScopes.TestAttributes.TestDoubleAttribute : MarkdownDecodableAttributedStringKey {} -#endif // FOUNDATION_FRAMEWORK - -struct NonCodableType : Hashable { - var inner : Int -} - -extension AttributeScopes { - var test: TestAttributes.Type { TestAttributes.self } - - struct TestAttributes : AttributeScope { - var testInt : TestIntAttribute - var testString : TestStringAttribute - var testDouble : TestDoubleAttribute - var testBool : TestBoolAttribute - var testNonExtended : TestNonExtended - var testParagraphConstrained : TestParagraphConstrained - var testSecondParagraphConstrained : TestSecondParagraphConstrained - var testCharacterConstrained : TestCharacterConstrained - var testUnicodeScalarConstrained : TestUnicodeCharacterConstrained - var testAttributeDependent : TestAttributeDependent - var testCharacterDependent : TestCharacterDependent - } -} - -extension AttributeDynamicLookup { - subscript(dynamicMember keyPath: KeyPath) -> T { - get { self[T.self] } - } -} - -enum TestError: Error { - case encodingError - case decodingError - case conversionError - case markdownError -} - -#if !FOUNDATION_FRAMEWORK - -extension AttributedStringProtocol { - func range(of other: String) -> Range? { - let str = String(characters) - guard let strRange = str.firstRange(of: other) else { return nil } - let start = str.unicodeScalars.distance(from: str.startIndex, to: strRange.lowerBound) - let end = str.unicodeScalars.distance(from: str.startIndex, to: strRange.upperBound) - return unicodeScalars.index(startIndex, offsetBy: start) ..< unicodeScalars.index(startIndex, offsetBy: end) - } -} - -#endif // !FOUNDATION_FRAMEWORK diff --git a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringTests.swift b/Tests/FoundationEssentialsTests/AttributedString/AttributedStringTests.swift deleted file mode 100644 index b77a4b238..000000000 --- a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringTests.swift +++ /dev/null @@ -1,2628 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2020 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(FoundationEssentials) -@testable import FoundationEssentials -#endif // FOUNDATION_FRAMEWORK - -#if FOUNDATION_FRAMEWORK -@testable @_spi(AttributedString) @_spi(AttributedStringWritingDirection) import Foundation -// For testing default attribute scope conversion -#if canImport(Accessibility) -import Accessibility -#endif -#if canImport(SwiftUI) -import SwiftUI -#endif -#if canImport(UIKit) -import UIKit -#endif -#if canImport(AppKit) -import AppKit -#endif -#endif // FOUNDATION_FRAMEWORK - -/// Regression and coverage tests for `AttributedString` and its associated objects -final class TestAttributedString: XCTestCase { - // MARK: - Enumeration Tests - - func testEmptyEnumeration() { - for _ in AttributedString().runs { - XCTFail("Empty AttributedString should not enumerate any attributes") - } - - do { - let str = AttributedString("Foo") - for _ in str[str.startIndex ..< str.startIndex].runs { - XCTFail("Empty AttributedSubstring should not enumerate any attributes") - } - } - - do { - let str = AttributedString("Foo", attributes: AttributeContainer.testInt(2)) - let i = str.index(afterCharacter: str.startIndex) - for _ in str[i ..< i].runs { - XCTFail("Empty AttributedSubstring should not enumerate any attributes") - } - } - } - - func verifyAttributes(_ runs: AttributedString.Runs.AttributesSlice1, string: AttributedString, expectation: [(String, T.Value?)]) where T.Value : Sendable { - // Test that the attribute is correct when iterating through attribute runs - var expectIterator = expectation.makeIterator() - for (attribute, range) in runs { - let expected = expectIterator.next()! - XCTAssertEqual(String(string[range].characters), expected.0, "Substring of AttributedString characters for range of run did not match expectation") - XCTAssertEqual(attribute, expected.1, "Attribute of run did not match expectation") - } - XCTAssertNil(expectIterator.next(), "Additional runs expected but not found") - - // Test that the attribute is correct when iterating through reversed attribute runs - expectIterator = expectation.reversed().makeIterator() - for (attribute, range) in runs.reversed() { - let expected = expectIterator.next()! - XCTAssertEqual(String(string[range].characters), expected.0, "Substring of AttributedString characters for range of run did not match expectation") - XCTAssertEqual(attribute, expected.1, "Attribute of run did not match expectation") - } - XCTAssertNil(expectIterator.next(), "Additional runs expected but not found") - } - - func verifyAttributes(_ runs: AttributedString.Runs.AttributesSlice2, string: AttributedString, expectation: [(String, T.Value?, U.Value?)]) where T.Value : Sendable, U.Value : Sendable { - // Test that the attributes are correct when iterating through attribute runs - var expectIterator = expectation.makeIterator() - for (attribute, attribute2, range) in runs { - let expected = expectIterator.next()! - XCTAssertEqual(String(string[range].characters), expected.0, "Substring of AttributedString characters for range of run did not match expectation") - XCTAssertEqual(attribute, expected.1, "Attribute of run did not match expectation") - XCTAssertEqual(attribute2, expected.2, "Attribute of run did not match expectation") - } - XCTAssertNil(expectIterator.next(), "Additional runs expected but not found") - - // Test that the attributes are correct when iterating through reversed attribute runs - expectIterator = expectation.reversed().makeIterator() - for (attribute, attribute2, range) in runs.reversed() { - let expected = expectIterator.next()! - XCTAssertEqual(String(string[range].characters), expected.0, "Substring of AttributedString characters for range of run did not match expectation") - XCTAssertEqual(attribute, expected.1, "Attribute of run did not match expectation") - XCTAssertEqual(attribute2, expected.2, "Attribute of run did not match expectation") - } - XCTAssertNil(expectIterator.next(), "Additional runs expected but not found") - } - -#if FOUNDATION_FRAMEWORK - func verifyAttributes(_ runs: AttributedString.Runs.NSAttributesSlice, string: AttributedString, expectation: [(String, AttributeContainer)], file: StaticString = #filePath, line: UInt = #line) { - // Test that the attribute is correct when iterating through attribute runs - var expectIterator = expectation.makeIterator() - for (attribute, range) in runs { - let expected = expectIterator.next()! - XCTAssertEqual(String(string[range].characters), expected.0, "Substring of AttributedString characters for range of run did not match expectation", file: file, line: line) - XCTAssertEqual(attribute, expected.1, "Attribute of run did not match expectation", file: file, line: line) - } - XCTAssertNil(expectIterator.next(), "Additional runs expected but not found", file: file, line: line) - - // Test that the attribute is correct when iterating through reversed attribute runs - expectIterator = expectation.reversed().makeIterator() - for (attribute, range) in runs.reversed() { - let expected = expectIterator.next()! - XCTAssertEqual(String(string[range].characters), expected.0, "Substring of AttributedString characters for range of run did not match expectation", file: file, line: line) - XCTAssertEqual(attribute, expected.1, "Attribute of run did not match expectation", file: file, line: line) - } - XCTAssertNil(expectIterator.next(), "Additional runs expected but not found", file: file, line: line) - } -#endif // FOUNDATION_FRAMEWORK - - func testSimpleEnumeration() { - var attrStr = AttributedString("Hello", attributes: AttributeContainer().testInt(1)) - attrStr += " " - attrStr += AttributedString("World", attributes: AttributeContainer().testDouble(2.0)) - - let expectation = [("Hello", 1, nil), (" ", nil, nil), ("World", nil, 2.0)] - var expectationIterator = expectation.makeIterator() - for run in attrStr.runs { - let expected = expectationIterator.next()! - XCTAssertEqual(String(attrStr[run.range].characters), expected.0) - XCTAssertEqual(run.testInt, expected.1) - XCTAssertEqual(run.testDouble, expected.2) - XCTAssertNil(run.testString) - } - XCTAssertNil(expectationIterator.next()) - - expectationIterator = expectation.reversed().makeIterator() - for run in attrStr.runs.reversed() { - let expected = expectationIterator.next()! - XCTAssertEqual(String(attrStr[run.range].characters), expected.0) - XCTAssertEqual(run.testInt, expected.1) - XCTAssertEqual(run.testDouble, expected.2) - XCTAssertNil(run.testString) - } - XCTAssertNil(expectationIterator.next()) - - let attrView = attrStr.runs - verifyAttributes(attrView[\.testInt], string: attrStr, expectation: [("Hello", 1), (" World", nil)]) - verifyAttributes(attrView[\.testDouble], string: attrStr, expectation: [("Hello ", nil), ("World", 2.0)]) - verifyAttributes(attrView[\.testString], string: attrStr, expectation: [("Hello World", nil)]) - verifyAttributes(attrView[\.testInt, \.testDouble], string: attrStr, expectation: [("Hello", 1, nil), (" ", nil, nil), ("World", nil, 2.0)]) - } - - func testSliceEnumeration() { - var attrStr = AttributedString("Hello", attributes: AttributeContainer().testInt(1)) - attrStr += AttributedString(" ") - attrStr += AttributedString("World", attributes: AttributeContainer().testDouble(2.0)) - - let attrStrSlice = attrStr[attrStr.characters.index(attrStr.startIndex, offsetBy: 3) ..< attrStr.characters.index(attrStr.endIndex, offsetBy: -3)] - - let expectation = [("lo", 1, nil), (" ", nil, nil), ("Wo", nil, 2.0)] - var expectationIterator = expectation.makeIterator() - for run in attrStrSlice.runs { - let expected = expectationIterator.next()! - XCTAssertEqual(String(attrStr[run.range].characters), expected.0) - XCTAssertEqual(run.testInt, expected.1) - XCTAssertEqual(run.testDouble, expected.2) - XCTAssertNil(run.testString) - } - XCTAssertNil(expectationIterator.next()) - - expectationIterator = expectation.reversed().makeIterator() - for run in attrStrSlice.runs.reversed() { - let expected = expectationIterator.next()! - XCTAssertEqual(String(attrStr[run.range].characters), expected.0) - XCTAssertEqual(run.testInt, expected.1) - XCTAssertEqual(run.testDouble, expected.2) - XCTAssertNil(run.testString) - } - XCTAssertNil(expectationIterator.next()) - - let attrView = attrStrSlice.runs - verifyAttributes(attrView[\.testInt], string: attrStr, expectation: [("lo", 1), (" Wo", nil)]) - verifyAttributes(attrView[\.testDouble], string: attrStr, expectation: [("lo ", nil), ("Wo", 2.0)]) - verifyAttributes(attrView[\.testString], string: attrStr, expectation: [("lo Wo", nil)]) - verifyAttributes(attrView[\.testInt, \.testDouble], string: attrStr, expectation: [("lo", 1, nil), (" ", nil, nil), ("Wo", nil, 2.0)]) - } - -#if FOUNDATION_FRAMEWORK - func testNSSliceEnumeration() { - var attrStr = AttributedString("Hello", attributes: AttributeContainer().testInt(1)) - attrStr += AttributedString(" ") - attrStr += AttributedString("World", attributes: AttributeContainer().testDouble(2.0)) - - let middleRange = attrStr.characters.index(attrStr.startIndex, offsetBy: 3) ..< attrStr.characters.index(attrStr.endIndex, offsetBy: -3) - let view = attrStr[middleRange].runs - verifyAttributes(view[nsAttributedStringKeys: [.testInt]], string: attrStr, expectation: [("lo", .init().testInt(1)), (" Wo", .init())]) - verifyAttributes(view[nsAttributedStringKeys: [.testDouble]], string: attrStr, expectation: [("lo ", .init()), ("Wo", .init().testDouble(2.0))]) - verifyAttributes(view[nsAttributedStringKeys: [.testString]], string: attrStr, expectation: [("lo Wo", .init())]) - verifyAttributes(view[nsAttributedStringKeys: [.testInt, .testDouble]], string: attrStr, expectation: [("lo", .init().testInt(1)), (" ", .init()), ("Wo", .init().testDouble(2.0))]) - - attrStr[middleRange].testString = "Test" - verifyAttributes(attrStr.runs[nsAttributedStringKeys: [.testInt]], string: attrStr, expectation: [("Hello", .init().testInt(1)), (" World", .init())]) - verifyAttributes(attrStr.runs[nsAttributedStringKeys: [.testDouble]], string: attrStr, expectation: [("Hello ", .init()), ("World", .init().testDouble(2.0))]) - verifyAttributes(attrStr.runs[nsAttributedStringKeys: [.testString]], string: attrStr, expectation: [("Hel", .init()), ("lo Wo", .init().testString("Test")), ("rld", .init())]) - verifyAttributes(attrStr.runs[nsAttributedStringKeys: [.testInt, .testDouble, .testString]], string: attrStr, expectation: [ - ("Hel", .init().testInt(1)), - ("lo", .init().testInt(1).testString("Test")), - (" ", .init().testString("Test")), - ("Wo", .init().testDouble(2.0).testString("Test")), - ("rld", .init().testDouble(2.0)) - ]) - } -#endif // FOUNDATION_FRAMEWORK - - // MARK: - Attribute Tests - - func testSimpleAttribute() { - let attrStr = AttributedString("Foo", attributes: AttributeContainer().testInt(42)) - let (value, range) = attrStr.runs[\.testInt][attrStr.startIndex] - XCTAssertEqual(value, 42) - XCTAssertEqual(range, attrStr.startIndex ..< attrStr.endIndex) - } - - func testConstructorAttribute() { - // TODO: Re-evaluate whether we want these. - let attrStr = AttributedString("Hello", attributes: AttributeContainer().testString("Helvetica").testInt(2)) - var expected = AttributedString("Hello") - expected.testString = "Helvetica" - expected.testInt = 2 - XCTAssertEqual(attrStr, expected) - } - - func testAddAndRemoveAttribute() { - let attr : Int = 42 - let attr2 : Double = 1.0 - var attrStr = AttributedString("Test") - attrStr.testInt = attr - attrStr.testDouble = attr2 - - let expected1 = AttributedString("Test", attributes: AttributeContainer().testInt(attr).testDouble(attr2)) - XCTAssertEqual(attrStr, expected1) - - attrStr.testDouble = nil - - let expected2 = AttributedString("Test", attributes: AttributeContainer().testInt(attr)) - XCTAssertEqual(attrStr, expected2) - } - - func testAddingAndRemovingAttribute() { - let container = AttributeContainer().testInt(1).testDouble(2.2) - let attrStr = AttributedString("Test").mergingAttributes(container) - let expected = AttributedString("Test", attributes: AttributeContainer().testInt(1).testDouble(2.2)) - XCTAssertEqual(attrStr, expected) - var doubleRemoved = attrStr - doubleRemoved.testDouble = nil - XCTAssertEqual(doubleRemoved, AttributedString("Test", attributes: AttributeContainer().testInt(1))) - } - - func testScopedAttributes() { - var str = AttributedString("Hello, world", attributes: AttributeContainer().testInt(2).testDouble(3.4)) - XCTAssertEqual(str.test.testInt, 2) - XCTAssertEqual(str.test.testDouble, 3.4) - XCTAssertEqual(str.runs[str.runs.startIndex].test.testInt, 2) - - str.test.testInt = 4 - XCTAssertEqual(str, AttributedString("Hello, world", attributes: AttributeContainer.testInt(4).testDouble(3.4))) - - let range = str.startIndex ..< str.characters.index(after: str.startIndex) - str[range].test.testBool = true - XCTAssertNil(str.test.testBool) - XCTAssertNotNil(str[range].test.testBool) - XCTAssertTrue(str[range].test.testBool!) - } - - func testRunAttributes() { - var str = AttributedString("String", attributes: .init().testString("test1")) - str += "None" - str += AttributedString("String+Int", attributes: .init().testString("test2").testInt(42)) - - let attributes = str.runs.map { $0.attributes } - XCTAssertEqual(attributes.count, 3) - XCTAssertEqual(attributes[0], .init().testString("test1")) - XCTAssertEqual(attributes[1], .init()) - XCTAssertEqual(attributes[2], .init().testString("test2").testInt(42)) - } - - // MARK: - Comparison Tests - - func testAttributedStringEquality() { - XCTAssertEqual(AttributedString(), AttributedString()) - XCTAssertEqual(AttributedString("abc"), AttributedString("abc")) - XCTAssertEqual(AttributedString("abc", attributes: AttributeContainer().testInt(1)), AttributedString("abc", attributes: AttributeContainer().testInt(1))) - XCTAssertNotEqual(AttributedString("abc", attributes: AttributeContainer().testInt(1)), AttributedString("abc", attributes: AttributeContainer().testInt(2))) - XCTAssertNotEqual(AttributedString("abc", attributes: AttributeContainer().testInt(1)), AttributedString("def", attributes: AttributeContainer().testInt(1))) - - var a = AttributedString("abc", attributes: AttributeContainer().testInt(1)) - a += AttributedString("def", attributes: AttributeContainer().testInt(1)) - XCTAssertEqual(a, AttributedString("abcdef", attributes: AttributeContainer().testInt(1))) - - a = AttributedString("ab", attributes: AttributeContainer().testInt(1)) - a += AttributedString("cdef", attributes: AttributeContainer().testInt(2)) - var b = AttributedString("abcd", attributes: AttributeContainer().testInt(1)) - b += AttributedString("ef", attributes: AttributeContainer().testInt(2)) - XCTAssertNotEqual(a, b) - - a = AttributedString("abc") - a += AttributedString("defghi", attributes: AttributeContainer().testInt(2)) - a += "jkl" - b = AttributedString("abc") - b += AttributedString("def", attributes: AttributeContainer().testInt(2)) - b += "ghijkl" - XCTAssertNotEqual(a, b) - - - let a1 = AttributedString("Café", attributes: AttributeContainer().testInt(1)) - let a2 = AttributedString("Cafe\u{301}", attributes: AttributeContainer().testInt(1)) - XCTAssertEqual(a1, a2) - - let a3 = (AttributedString("Cafe", attributes: AttributeContainer().testInt(1)) - + AttributedString("\u{301}", attributes: AttributeContainer().testInt(2))) - XCTAssertNotEqual(a1, a3) - XCTAssertNotEqual(a2, a3) - XCTAssertTrue(a1.characters.elementsEqual(a3.characters)) - XCTAssertTrue(a2.characters.elementsEqual(a3.characters)) - } - - func testAttributedSubstringEquality() { - let emptyStr = AttributedString("01234567890123456789") - - let index0 = emptyStr.characters.startIndex - let index5 = emptyStr.characters.index(index0, offsetBy: 5) - let index10 = emptyStr.characters.index(index0, offsetBy: 10) - let index20 = emptyStr.characters.index(index0, offsetBy: 20) - - var singleAttrStr = emptyStr - singleAttrStr[index0 ..< index10].testInt = 1 - - var halfhalfStr = emptyStr - halfhalfStr[index0 ..< index10].testInt = 1 - halfhalfStr[index10 ..< index20].testDouble = 2.0 - - XCTAssertEqual(emptyStr[index0 ..< index0], emptyStr[index0 ..< index0]) - XCTAssertEqual(emptyStr[index0 ..< index5], emptyStr[index0 ..< index5]) - XCTAssertEqual(emptyStr[index0 ..< index20], emptyStr[index0 ..< index20]) - XCTAssertEqual(singleAttrStr[index0 ..< index20], singleAttrStr[index0 ..< index20]) - XCTAssertEqual(halfhalfStr[index0 ..< index20], halfhalfStr[index0 ..< index20]) - - XCTAssertEqual(emptyStr[index0 ..< index10], singleAttrStr[index10 ..< index20]) - XCTAssertEqual(halfhalfStr[index0 ..< index10], singleAttrStr[index0 ..< index10]) - - XCTAssertNotEqual(emptyStr[index0 ..< index10], singleAttrStr[index0 ..< index10]) - XCTAssertNotEqual(emptyStr[index0 ..< index10], singleAttrStr[index0 ..< index20]) - - XCTAssertTrue(emptyStr[index0 ..< index5] == AttributedString("01234")) - } - - func testRunEquality() { - var attrStr = AttributedString("Hello", attributes: AttributeContainer().testInt(1)) - attrStr += AttributedString(" ") - attrStr += AttributedString("World", attributes: AttributeContainer().testInt(2)) - - var attrStr2 = AttributedString("Hello", attributes: AttributeContainer().testInt(2)) - attrStr2 += AttributedString("_") - attrStr2 += AttributedString("World", attributes: AttributeContainer().testInt(2)) - attrStr2 += AttributedString("Hello", attributes: AttributeContainer().testInt(1)) - - var attrStr3 = AttributedString("Hel", attributes: AttributeContainer().testInt(1)) - attrStr3 += AttributedString("lo W") - attrStr3 += AttributedString("orld", attributes: AttributeContainer().testInt(2)) - - func run(_ num: Int, in str: AttributedString) -> AttributedString.Runs.Run { - return str.runs[str.runs.index(str.runs.startIndex, offsetBy: num)] - } - - // Same string, same range, different attributes - XCTAssertNotEqual(run(0, in: attrStr), run(0, in: attrStr2)) - - // Different strings, same range, same attributes - XCTAssertEqual(run(1, in: attrStr), run(1, in: attrStr2)) - - // Same string, same range, same attributes - XCTAssertEqual(run(2, in: attrStr), run(2, in: attrStr2)) - - // Different string, different range, same attributes - XCTAssertEqual(run(2, in: attrStr), run(0, in: attrStr2)) - - // Same string, different range, same attributes - XCTAssertEqual(run(0, in: attrStr), run(3, in: attrStr2)) - - // A runs collection of the same order but different run lengths - XCTAssertNotEqual(attrStr.runs, attrStr3.runs) - } - - func testSubstringRunEquality() { - var attrStr = AttributedString("Hello", attributes: AttributeContainer().testInt(1)) - attrStr += AttributedString(" ") - attrStr += AttributedString("World", attributes: AttributeContainer().testInt(2)) - - var attrStr2 = AttributedString("Hello", attributes: AttributeContainer().testInt(2)) - attrStr2 += AttributedString("_") - attrStr2 += AttributedString("World", attributes: AttributeContainer().testInt(2)) - - XCTAssertEqual(attrStr[attrStr.runs.last!.range].runs, attrStr2[attrStr2.runs.first!.range].runs) - XCTAssertEqual(attrStr[attrStr.runs.last!.range].runs, attrStr2[attrStr2.runs.last!.range].runs) - - let rangeA = attrStr.runs.first!.range.upperBound ..< attrStr.endIndex - let rangeB = attrStr2.runs.first!.range.upperBound ..< attrStr.endIndex - let rangeC = attrStr.startIndex ..< attrStr.runs.last!.range.lowerBound - let rangeD = attrStr.runs.first!.range - XCTAssertEqual(attrStr[rangeA].runs, attrStr2[rangeB].runs) - XCTAssertNotEqual(attrStr[rangeC].runs, attrStr2[rangeB].runs) - XCTAssertNotEqual(attrStr[rangeD].runs, attrStr2[rangeB].runs) - - // Test starting/ending runs that only differ outside of the range do not prevent equality - attrStr2[attrStr.runs.first!.range].testInt = 1 - attrStr2.characters.insert(contentsOf: "123", at: attrStr.startIndex) - attrStr2.characters.append(contentsOf: "45") - let rangeE = attrStr.startIndex ..< attrStr.endIndex - let rangeF = attrStr2.characters.index(attrStr2.startIndex, offsetBy: 3) ..< attrStr2.characters.index(attrStr2.startIndex, offsetBy: 14) - XCTAssertEqual(attrStr[rangeE].runs, attrStr2[rangeF].runs) - } - - // MARK: - Mutation Tests - - func testDirectMutationCopyOnWrite() { - var attrStr = AttributedString("ABC") - let copy = attrStr - attrStr += "D" - - XCTAssertEqual(copy, AttributedString("ABC")) - XCTAssertNotEqual(attrStr, copy) - } - - func testAttributeMutationCopyOnWrite() { - var attrStr = AttributedString("ABC") - let copy = attrStr - attrStr.testInt = 1 - - XCTAssertNotEqual(attrStr, copy) - } - - func testSliceAttributeMutation() { - let attr : Int = 42 - let attr2 : Double = 1.0 - - var attrStr = AttributedString("Hello World", attributes: AttributeContainer().testInt(attr)) - let copy = attrStr - - let chars = attrStr.characters - let start = chars.startIndex - let end = chars.index(start, offsetBy: 5) - attrStr[start ..< end].testDouble = attr2 - - var expected = AttributedString("Hello", attributes: AttributeContainer().testInt(attr).testDouble(attr2)) - expected += AttributedString(" World", attributes: AttributeContainer().testInt(attr)) - XCTAssertEqual(attrStr, expected) - - XCTAssertNotEqual(copy, attrStr) - } - - func testEnumerationAttributeMutation() { - var attrStr = AttributedString("A", attributes: AttributeContainer().testInt(1)) - attrStr += AttributedString("B", attributes: AttributeContainer().testDouble(2.0)) - attrStr += AttributedString("C", attributes: AttributeContainer().testInt(3)) - - for (attr, range) in attrStr.runs[\.testInt] { - if let _ = attr { - attrStr[range].testInt = nil - } - } - - var expected = AttributedString("A") - expected += AttributedString("B", attributes: AttributeContainer().testDouble(2.0)) - expected += "C" - XCTAssertEqual(expected, attrStr) - } - - func testMutateMultipleAttributes() { - var attrStr = AttributedString("A", attributes: AttributeContainer().testInt(1).testBool(true)) - attrStr += AttributedString("B", attributes: AttributeContainer().testInt(1).testDouble(2)) - attrStr += AttributedString("C", attributes: AttributeContainer().testDouble(2).testBool(false)) - - // Test removal - let removal1 = attrStr.transformingAttributes(\.testInt, \.testDouble, \.testBool) { - $0.value = nil - $1.value = nil - $2.value = nil - } - let removal1expected = AttributedString("ABC") - XCTAssertEqual(removal1expected, removal1) - - // Test change value, same attribute. - let changeSame1 = attrStr.transformingAttributes(\.testInt, \.testDouble, \.testBool) { - if let _ = $0.value { - $0.value = 42 - } - if let _ = $1.value { - $1.value = 3 - } - if let boolean = $2.value { - $2.value = !boolean - } - } - var changeSame1expected = AttributedString("A", attributes: AttributeContainer().testInt(42).testBool(false)) - changeSame1expected += AttributedString("B", attributes: AttributeContainer().testInt(42).testDouble(3)) - changeSame1expected += AttributedString("C", attributes: AttributeContainer().testDouble(3).testBool(true)) - XCTAssertEqual(changeSame1expected, changeSame1) - - // Test change value, different attribute - let changeDifferent1 = attrStr.transformingAttributes(\.testInt, \.testDouble, \.testBool) { - if let _ = $0.value { - $0.replace(with: AttributeScopes.TestAttributes.TestDoubleAttribute.self, value: 2) - } - if let _ = $1.value { - $1.replace(with: AttributeScopes.TestAttributes.TestBoolAttribute.self, value: false) - } - if let _ = $2.value { - $2.replace(with: AttributeScopes.TestAttributes.TestIntAttribute.self, value: 42) - } - } - - var changeDifferent1expected = AttributedString("A", attributes: AttributeContainer().testDouble(2).testInt(42)) - changeDifferent1expected += AttributedString("B", attributes: AttributeContainer().testDouble(2).testBool(false)) - changeDifferent1expected += AttributedString("C", attributes: AttributeContainer().testBool(false).testInt(42)) - XCTAssertEqual(changeDifferent1expected, changeDifferent1) - - // Test change range - var changeRange1First = true - let changeRange1 = attrStr.transformingAttributes(\.testInt, \.testDouble, \.testBool) { - if changeRange1First { - let range = $0.range - let extendedRange = range.lowerBound ..< attrStr.characters.index(after: range.upperBound) - $0.range = extendedRange - $1.range = extendedRange - $2.range = extendedRange - changeRange1First = false - } - } - var changeRange1expected = AttributedString("A", attributes: AttributeContainer().testInt(1).testBool(true)) - changeRange1expected += AttributedString("B", attributes: AttributeContainer().testInt(1).testBool(true)) - changeRange1expected += AttributedString("C", attributes: AttributeContainer().testDouble(2).testBool(false)) - XCTAssertEqual(changeRange1expected, changeRange1) - } - - func testMutateAttributes() { - var attrStr = AttributedString("A", attributes: AttributeContainer().testInt(1).testBool(true)) - attrStr += AttributedString("B", attributes: AttributeContainer().testInt(1).testDouble(2)) - attrStr += AttributedString("C", attributes: AttributeContainer().testDouble(2).testBool(false)) - - // Test removal - let removal1 = attrStr.transformingAttributes(\.testInt) { - $0.value = nil - } - var removal1expected = AttributedString("A", attributes: AttributeContainer().testBool(true)) - removal1expected += AttributedString("B", attributes: AttributeContainer().testDouble(2)) - removal1expected += AttributedString("C", attributes: AttributeContainer().testDouble(2).testBool(false)) - XCTAssertEqual(removal1expected, removal1) - - // Test change value, same attribute. - let changeSame1 = attrStr.transformingAttributes(\.testBool) { - if let boolean = $0.value { - $0.value = !boolean - } - } - var changeSame1expected = AttributedString("A", attributes: AttributeContainer().testInt(1).testBool(false)) - changeSame1expected += AttributedString("B", attributes: AttributeContainer().testInt(1).testDouble(2)) - changeSame1expected += AttributedString("C", attributes: AttributeContainer().testDouble(2).testBool(true)) - XCTAssertEqual(changeSame1expected, changeSame1) - - // Test change value, different attribute - let changeDifferent1 = attrStr.transformingAttributes(\.testBool) { - if let value = $0.value { - $0.replace(with: AttributeScopes.TestAttributes.TestDoubleAttribute.self, value: (value ? 42 : 43)) - } - } - var changeDifferent1expected = AttributedString("A", attributes: AttributeContainer().testInt(1).testDouble(42)) - changeDifferent1expected += AttributedString("B", attributes: AttributeContainer().testInt(1).testDouble(2)) - changeDifferent1expected += AttributedString("C", attributes: AttributeContainer().testDouble(43)) - XCTAssertEqual(changeDifferent1expected, changeDifferent1) - - // Test change range - let changeRange1 = attrStr.transformingAttributes(\.testInt) { - if let _ = $0.value { - // Shorten the range by one. - $0.range = $0.range.lowerBound ..< attrStr.characters.index(before: $0.range.upperBound) - } - } - var changeRange1expected = AttributedString("A", attributes: AttributeContainer().testInt(1).testBool(true)) - changeRange1expected += AttributedString("B", attributes: AttributeContainer().testDouble(2)) - changeRange1expected += AttributedString("C", attributes: AttributeContainer().testDouble(2).testBool(false)) - XCTAssertEqual(changeRange1expected, changeRange1) - - // Now try extending it - let changeRange2 = attrStr.transformingAttributes(\.testInt) { - if let _ = $0.value { - // Extend the range by one. - $0.range = $0.range.lowerBound ..< attrStr.characters.index(after: $0.range.upperBound) - } - } - var changeRange2expected = AttributedString("A", attributes: AttributeContainer().testInt(1).testBool(true)) - changeRange2expected += AttributedString("B", attributes: AttributeContainer().testInt(1).testDouble(2)) - changeRange2expected += AttributedString("C", attributes: AttributeContainer().testInt(1).testDouble(2).testBool(false)) - XCTAssertEqual(changeRange2expected, changeRange2) - } - - func testReplaceAttributes() { - var attrStr = AttributedString("A", attributes: AttributeContainer().testInt(1).testBool(true)) - attrStr += AttributedString("B", attributes: AttributeContainer().testInt(1).testDouble(2)) - attrStr += AttributedString("C", attributes: AttributeContainer().testDouble(2).testBool(false)) - - // Test removal - let removal1Find = AttributeContainer().testInt(1) - let removal1Replace = AttributeContainer() - var removal1 = attrStr - removal1.replaceAttributes(removal1Find, with: removal1Replace) - - var removal1expected = AttributedString("A", attributes: AttributeContainer().testBool(true)) - removal1expected += AttributedString("B", attributes: AttributeContainer().testDouble(2)) - removal1expected += AttributedString("C", attributes: AttributeContainer().testDouble(2).testBool(false)) - XCTAssertEqual(removal1expected, removal1) - - // Test change value, same attribute. - let changeSame1Find = AttributeContainer().testBool(false) - let changeSame1Replace = AttributeContainer().testBool(true) - var changeSame1 = attrStr - changeSame1.replaceAttributes(changeSame1Find, with: changeSame1Replace) - - var changeSame1expected = AttributedString("A", attributes: AttributeContainer().testInt(1).testBool(true)) - changeSame1expected += AttributedString("B", attributes: AttributeContainer().testInt(1).testDouble(2)) - changeSame1expected += AttributedString("C", attributes: AttributeContainer().testDouble(2).testBool(true)) - XCTAssertEqual(changeSame1expected, changeSame1) - - // Test change value, different attribute - let changeDifferent1Find = AttributeContainer().testBool(false) - let changeDifferent1Replace = AttributeContainer().testDouble(43) - var changeDifferent1 = attrStr - changeDifferent1.replaceAttributes(changeDifferent1Find, with: changeDifferent1Replace) - - var changeDifferent1expected = AttributedString("A", attributes: AttributeContainer().testInt(1).testBool(true)) - changeDifferent1expected += AttributedString("B", attributes: AttributeContainer().testInt(1).testDouble(2)) - changeDifferent1expected += AttributedString("C", attributes: AttributeContainer().testDouble(43)) - XCTAssertEqual(changeDifferent1expected, changeDifferent1) - } - - - func testSliceMutation() { - var attrStr = AttributedString("Hello World", attributes: AttributeContainer().testInt(1)) - let start = attrStr.characters.index(attrStr.startIndex, offsetBy: 6) - attrStr.replaceSubrange(start ..< attrStr.characters.index(start, offsetBy:5), with: AttributedString("Goodbye", attributes: AttributeContainer().testInt(2))) - - var expected = AttributedString("Hello ", attributes: AttributeContainer().testInt(1)) - expected += AttributedString("Goodbye", attributes: AttributeContainer().testInt(2)) - XCTAssertEqual(attrStr, expected) - XCTAssertNotEqual(attrStr, AttributedString("Hello Goodbye", attributes: AttributeContainer().testInt(1))) - } - - func testOverlappingSliceMutation() { - var attrStr = AttributedString("Hello, world!") - attrStr[attrStr.range(of: "Hello")!].testInt = 1 - attrStr[attrStr.range(of: "world")!].testInt = 2 - attrStr[attrStr.range(of: "o, wo")!].testBool = true - - var expected = AttributedString("Hell", attributes: AttributeContainer().testInt(1)) - expected += AttributedString("o", attributes: AttributeContainer().testInt(1).testBool(true)) - expected += AttributedString(", ", attributes: AttributeContainer().testBool(true)) - expected += AttributedString("wo", attributes: AttributeContainer().testBool(true).testInt(2)) - expected += AttributedString("rld", attributes: AttributeContainer().testInt(2)) - expected += AttributedString("!") - XCTAssertEqual(attrStr, expected) - } - - func testCharacters_replaceSubrange() { - var attrStr = AttributedString("Hello World", attributes: AttributeContainer().testInt(1)) - attrStr.characters.replaceSubrange(attrStr.range(of: " ")!, with: " Good ") - - let expected = AttributedString("Hello Good World", attributes: AttributeContainer().testInt(1)) - XCTAssertEqual(expected, attrStr) - } - - func testCharactersMutation_append() { - var attrStr = AttributedString("Hello World", attributes: AttributeContainer().testInt(1)) - attrStr.characters.append(contentsOf: " Goodbye") - - let expected = AttributedString("Hello World Goodbye", attributes: AttributeContainer().testInt(1)) - XCTAssertEqual(expected, attrStr) - } - - func testUnicodeScalars_replaceSubrange() { - var attrStr = AttributedString("La Cafe\u{301}", attributes: AttributeContainer().testInt(1)) - let unicode = attrStr.unicodeScalars - attrStr.unicodeScalars.replaceSubrange(unicode.index(unicode.startIndex, offsetBy: 3) ..< unicode.index(unicode.startIndex, offsetBy: 7), with: "Ole".unicodeScalars) - - let expected = AttributedString("La Ole\u{301}", attributes: AttributeContainer().testInt(1)) - XCTAssertEqual(expected, attrStr) - } - - func testUnicodeScalarsMutation_append() { - var attrStr = AttributedString("Cafe", attributes: AttributeContainer().testInt(1)) - attrStr.unicodeScalars.append("\u{301}") - - let expected = AttributedString("Cafe\u{301}", attributes: AttributeContainer().testInt(1)) - XCTAssertEqual(expected, attrStr) - } - - func testSubCharacterAttributeSetting() { - var attrStr = AttributedString("Cafe\u{301}", attributes: AttributeContainer().testInt(1)) - let cafRange = attrStr.characters.startIndex ..< attrStr.characters.index(attrStr.characters.startIndex, offsetBy: 3) - let eRange = cafRange.upperBound ..< attrStr.unicodeScalars.index(after: cafRange.upperBound) - let accentRange = eRange.upperBound ..< attrStr.unicodeScalars.endIndex - attrStr[cafRange].testDouble = 1.5 - attrStr[eRange].testDouble = 2.5 - attrStr[accentRange].testDouble = 3.5 - - var expected = AttributedString("Caf", attributes: AttributeContainer().testInt(1).testDouble(1.5)) - expected += AttributedString("e", attributes: AttributeContainer().testInt(1).testDouble(2.5)) - expected += AttributedString("\u{301}", attributes: AttributeContainer().testInt(1).testDouble(3.5)) - XCTAssertEqual(expected, attrStr) - } - - func testReplaceSubrange_rangeExpression() { - var attrStr = AttributedString("Hello World", attributes: AttributeContainer().testInt(1)) - - // Test with PartialRange, which conforms to RangeExpression but is not a Range - let rangeOfHello = ...attrStr.characters.index(attrStr.startIndex, offsetBy: 4) - attrStr.replaceSubrange(rangeOfHello, with: AttributedString("Goodbye")) - - var expected = AttributedString("Goodbye") - expected += AttributedString(" World", attributes: AttributeContainer().testInt(1)) - XCTAssertEqual(attrStr, expected) - } - - func testSettingAttributes() { - var attrStr = AttributedString("Hello World", attributes: .init().testInt(1)) - attrStr += AttributedString(". My name is Foundation!", attributes: .init().testBool(true)) - - let result = attrStr.settingAttributes(.init().testBool(false)) - - let expected = AttributedString("Hello World. My name is Foundation!", attributes: .init().testBool(false)) - XCTAssertEqual(result, expected) - } - - func testAddAttributedString() { - let attrStr = AttributedString("Hello ", attributes: .init().testInt(1)) - let attrStr2 = AttributedString("World", attributes: .init().testInt(2)) - let original = attrStr - let original2 = attrStr2 - - var concat = AttributedString("Hello ", attributes: .init().testInt(1)) - concat += AttributedString("World", attributes: .init().testInt(2)) - let combine = attrStr + attrStr2 - XCTAssertEqual(attrStr, original) - XCTAssertEqual(attrStr2, original2) - XCTAssertEqual(String(combine.characters), "Hello World") - XCTAssertEqual(String(concat.characters), "Hello World") - - let testInts = [1, 2] - for str in [concat, combine] { - var i = 0 - for run in str.runs { - XCTAssertEqual(run.testInt, testInts[i]) - i += 1 - } - } - } - - func testReplaceSubrangeWithSubstrings() { - let baseString = AttributedString("A", attributes: .init().testInt(1)) - + AttributedString("B", attributes: .init().testInt(2)) - + AttributedString("C", attributes: .init().testInt(3)) - + AttributedString("D", attributes: .init().testInt(4)) - + AttributedString("E", attributes: .init().testInt(5)) - - let substring = baseString[ baseString.characters.index(after: baseString.startIndex) ..< baseString.characters.index(before: baseString.endIndex) ] - - var targetString = AttributedString("XYZ", attributes: .init().testString("foo")) - targetString.replaceSubrange(targetString.characters.index(after: targetString.startIndex) ..< targetString.characters.index(before: targetString.endIndex), with: substring) - - var expected = AttributedString("X", attributes: .init().testString("foo")) - + AttributedString("B", attributes: .init().testInt(2)) - + AttributedString("C", attributes: .init().testInt(3)) - + AttributedString("D", attributes: .init().testInt(4)) - + AttributedString("Z", attributes: .init().testString("foo")) - - XCTAssertEqual(targetString, expected) - - targetString = AttributedString("XYZ", attributes: .init().testString("foo")) - targetString.append(substring) - expected = AttributedString("XYZ", attributes: .init().testString("foo")) - + AttributedString("B", attributes: .init().testInt(2)) - + AttributedString("C", attributes: .init().testInt(3)) - + AttributedString("D", attributes: .init().testInt(4)) - - XCTAssertEqual(targetString, expected) - } - - func assertStringIsCoalesced(_ str: AttributedString) { - var prev: AttributedString.Runs.Run? - for run in str.runs { - if let prev = prev { - XCTAssertNotEqual(prev.attributes, run.attributes) - } - prev = run - } - } - - func testCoalescing() { - let str = AttributedString("Hello", attributes: .init().testInt(1)) - let appendSame = str + AttributedString("World", attributes: .init().testInt(1)) - let appendDifferent = str + AttributedString("World", attributes: .init().testInt(2)) - - assertStringIsCoalesced(str) - assertStringIsCoalesced(appendSame) - assertStringIsCoalesced(appendDifferent) - XCTAssertEqual(appendSame.runs.count, 1) - XCTAssertEqual(appendDifferent.runs.count, 2) - - // Ensure replacing whole string keeps coalesced - var str2 = str - str2.replaceSubrange(str2.startIndex ..< str2.endIndex, with: AttributedString("Hello", attributes: .init().testInt(2))) - assertStringIsCoalesced(str2) - XCTAssertEqual(str2.runs.count, 1) - - // Ensure replacing subranges splits runs and doesn't coalesce when not equal - var str3 = str - str3.replaceSubrange(str3.characters.index(after: str3.startIndex) ..< str3.endIndex, with: AttributedString("ello", attributes: .init().testInt(2))) - assertStringIsCoalesced(str3) - XCTAssertEqual(str3.runs.count, 2) - - var str4 = str - str4.replaceSubrange(str4.startIndex ..< str4.characters.index(before: str4.endIndex), with: AttributedString("Hell", attributes: .init().testInt(2))) - assertStringIsCoalesced(str4) - XCTAssertEqual(str4.runs.count, 2) - - var str5 = str - str5.replaceSubrange(str5.characters.index(after: str5.startIndex) ..< str5.characters.index(before: str4.endIndex), with: AttributedString("ell", attributes: .init().testInt(2))) - assertStringIsCoalesced(str5) - XCTAssertEqual(str5.runs.count, 3) - - // Ensure changing attributes back to match bordering runs coalesces with edge of subrange - var str6 = str5 - str6.replaceSubrange(str6.characters.index(after: str6.startIndex) ..< str6.endIndex, with: AttributedString("ello", attributes: .init().testInt(1))) - assertStringIsCoalesced(str6) - XCTAssertEqual(str6.runs.count, 1) - - var str7 = str5 - str7.replaceSubrange(str7.startIndex ..< str7.characters.index(before: str7.endIndex), with: AttributedString("Hell", attributes: .init().testInt(1))) - assertStringIsCoalesced(str7) - XCTAssertEqual(str7.runs.count, 1) - - var str8 = str5 - str8.replaceSubrange(str8.characters.index(after: str8.startIndex) ..< str8.characters.index(before: str8.endIndex), with: AttributedString("ell", attributes: .init().testInt(1))) - assertStringIsCoalesced(str8) - XCTAssertEqual(str8.runs.count, 1) - - var str9 = str5 - str9.testInt = 1 - assertStringIsCoalesced(str9) - XCTAssertEqual(str9.runs.count, 1) - - var str10 = str5 - str10[str10.characters.index(after: str10.startIndex) ..< str10.characters.index(before: str10.endIndex)].testInt = 1 - assertStringIsCoalesced(str10) - XCTAssertEqual(str10.runs.count, 1) - } - - func testReplaceWithEmptyElements() { - var str = AttributedString("Hello, world") - let range = str.startIndex ..< str.characters.index(str.startIndex, offsetBy: 5) - str.characters.replaceSubrange(range, with: []) - - XCTAssertEqual(str, AttributedString(", world")) - } - - func testDescription() { - let string = AttributedString("A", attributes: .init().testInt(1)) - + AttributedString("B", attributes: .init().testInt(2)) - + AttributedString("C", attributes: .init().testInt(3)) - + AttributedString("D", attributes: .init().testInt(4)) - + AttributedString("E", attributes: .init().testInt(5)) - - let desc = String(describing: string) - let expected = """ -A { -\tTestInt = 1 -} -B { -\tTestInt = 2 -} -C { -\tTestInt = 3 -} -D { -\tTestInt = 4 -} -E { -\tTestInt = 5 -} -""" - XCTAssertEqual(desc, expected) - - let runsDesc = String(describing: string.runs) - XCTAssertEqual(runsDesc, expected) - } - - func testContainerDescription() { - let cont = AttributeContainer().testBool(false).testInt(1).testDouble(2.0).testString("3") - - let desc = String(describing: cont) - - // Don't get bitten by any potential changes in the hashing algorithm. - XCTAssertTrue(desc.hasPrefix("{\n")) - XCTAssertTrue(desc.hasSuffix("\n}")) - XCTAssertTrue(desc.contains("\tTestDouble = 2.0\n")) - XCTAssertTrue(desc.contains("\tTestInt = 1\n")) - XCTAssertTrue(desc.contains("\tTestString = 3\n")) - XCTAssertTrue(desc.contains("\tTestBool = false\n")) - } - - func testRunAndSubstringDescription() { - let string = AttributedString("A", attributes: .init().testInt(1)) - + AttributedString("B", attributes: .init().testInt(2)) - + AttributedString("C", attributes: .init().testInt(3)) - + AttributedString("D", attributes: .init().testInt(4)) - + AttributedString("E", attributes: .init().testInt(5)) - - let runsDescs = string.runs.map() { String(describing: $0) } - let expected = [ """ -A { -\tTestInt = 1 -} -""", """ -B { -\tTestInt = 2 -} -""", """ -C { -\tTestInt = 3 -} -""", """ -D { -\tTestInt = 4 -} -""", """ -E { -\tTestInt = 5 -} -"""] - XCTAssertEqual(runsDescs, expected) - - let subDescs = string.runs.map() { String(describing: string[$0.range]) } - XCTAssertEqual(subDescs, expected) - } - - func testReplacingAttributes() { - var str = AttributedString("Hello", attributes: .init().testInt(2)) - str += AttributedString("World", attributes: .init().testString("Test")) - - var result = str.replacingAttributes(.init().testInt(2).testString("NotTest"), with: .init().testBool(false)) - XCTAssertEqual(result, str) - - result = str.replacingAttributes(.init().testInt(2), with: .init().testBool(false)) - var expected = AttributedString("Hello", attributes: .init().testBool(false)) - expected += AttributedString("World", attributes: .init().testString("Test")) - XCTAssertEqual(result, expected) - } - - func testScopedAttributeContainer() { - var str = AttributedString("Hello, world") - - XCTAssertNil(str.test.testInt) - XCTAssertNil(str.testInt) - str.test.testInt = 2 - XCTAssertEqual(str.test.testInt, 2) - XCTAssertEqual(str.testInt, 2) - str.test.testInt = nil - XCTAssertNil(str.test.testInt) - XCTAssertNil(str.testInt) - - let range = str.startIndex ..< str.index(str.startIndex, offsetByCharacters: 5) - let otherRange = range.upperBound ..< str.endIndex - - str[range].test.testBool = true - XCTAssertEqual(str[range].test.testBool, true) - XCTAssertEqual(str[range].testBool, true) - XCTAssertNil(str.test.testBool) - XCTAssertNil(str.testBool) - str[range].test.testBool = nil - XCTAssertNil(str[range].test.testBool) - XCTAssertNil(str[range].testBool) - XCTAssertNil(str.test.testBool) - XCTAssertNil(str.testBool) - - str.test.testBool = true - str[range].test.testBool = nil - XCTAssertNil(str[range].test.testBool) - XCTAssertNil(str[range].testBool) - XCTAssertNil(str.test.testBool) - XCTAssertNil(str.testBool) - XCTAssertEqual(str[otherRange].test.testBool, true) - XCTAssertEqual(str[otherRange].testBool, true) - } - - func testMergeAttributes() { - let originalAttributes = AttributeContainer.testInt(2).testBool(true) - let newAttributes = AttributeContainer.testString("foo") - let overlappingAttributes = AttributeContainer.testInt(3).testDouble(4.3) - let str = AttributedString("Hello, world", attributes: originalAttributes) - - XCTAssertEqual(str.mergingAttributes(newAttributes, mergePolicy: .keepNew), AttributedString("Hello, world", attributes: newAttributes.testInt(2).testBool(true))) - XCTAssertEqual(str.mergingAttributes(newAttributes, mergePolicy: .keepCurrent), AttributedString("Hello, world", attributes: newAttributes.testInt(2).testBool(true))) - XCTAssertEqual(str.mergingAttributes(overlappingAttributes, mergePolicy: .keepNew), AttributedString("Hello, world", attributes: overlappingAttributes.testBool(true))) - XCTAssertEqual(str.mergingAttributes(overlappingAttributes, mergePolicy: .keepCurrent), AttributedString("Hello, world", attributes: originalAttributes.testDouble(4.3))) - } - - func testMergeAttributeContainers() { - let originalAttributes = AttributeContainer.testInt(2).testBool(true) - let newAttributes = AttributeContainer.testString("foo") - let overlappingAttributes = AttributeContainer.testInt(3).testDouble(4.3) - - XCTAssertEqual(originalAttributes.merging(newAttributes, mergePolicy: .keepNew), newAttributes.testInt(2).testBool(true)) - XCTAssertEqual(originalAttributes.merging(newAttributes, mergePolicy: .keepCurrent), newAttributes.testInt(2).testBool(true)) - XCTAssertEqual(originalAttributes.merging(overlappingAttributes, mergePolicy: .keepNew), overlappingAttributes.testBool(true)) - XCTAssertEqual(originalAttributes.merging(overlappingAttributes, mergePolicy: .keepCurrent), originalAttributes.testDouble(4.3)) - } - - func testChangingSingleCharacterUTF8Length() { - var attrstr = AttributedString("\u{1F3BA}\u{1F3BA}") // UTF-8 Length of 8 - attrstr.characters[attrstr.startIndex] = "A" // Changes UTF-8 Length to 5 - XCTAssertEqual(attrstr.runs.count, 1) - let runRange = attrstr.runs.first!.range - let substring = String(attrstr[runRange].characters) - XCTAssertEqual(substring, "A\u{1F3BA}") - } - - // MARK: - Substring Tests - - func testSubstringBase() { - let str = AttributedString("Hello World", attributes: .init().testInt(1)) - var substr = str[str.startIndex ..< str.characters.index(str.startIndex, offsetBy: 5)] - XCTAssertEqual(substr.base, str) - substr.testInt = 3 - XCTAssertNotEqual(substr.base, str) - - var str2 = AttributedString("Hello World", attributes: .init().testInt(1)) - let range = str2.startIndex ..< str2.characters.index(str2.startIndex, offsetBy: 5) - XCTAssertEqual(str2[range].base, str2) - str2[range].testInt = 3 - XCTAssertEqual(str2[range].base, str2) - } - - func testSubstringGetAttribute() { - let str = AttributedString("Hello World", attributes: .init().testInt(1)) - let range = str.startIndex ..< str.characters.index(str.startIndex, offsetBy: 5) - XCTAssertEqual(str[range].testInt, 1) - XCTAssertNil(str[range].testString) - - var str2 = AttributedString("Hel", attributes: .init().testInt(1)) - str2 += AttributedString("lo World", attributes: .init().testInt(2).testBool(true)) - let range2 = str2.startIndex ..< str2.characters.index(str2.startIndex, offsetBy: 5) - XCTAssertNil(str2[range2].testInt) - XCTAssertNil(str2[range2].testBool) - } - - func testSubstringDescription() { - var str = AttributedString("Hello", attributes: .init().testInt(2)) - str += " " - str += AttributedString("World", attributes: .init().testInt(3)) - - for run in str.runs { - let desc = str[run.range].description - XCTAssertFalse(desc.isEmpty) - } - } - - func testSubstringReplaceAttributes() { - var str = AttributedString("Hello", attributes: .init().testInt(2).testString("Foundation")) - str += " " - str += AttributedString("World", attributes: .init().testInt(3)) - - let range = str.index(str.startIndex, offsetByCharacters: 2) ..< str.index(str.startIndex, offsetByCharacters: 8) - str[range].replaceAttributes(.init().testInt(2).testString("Foundation"), with: .init().testBool(true)) - - var expected = AttributedString("He", attributes: .init().testInt(2).testString("Foundation")) - expected += AttributedString("llo", attributes: .init().testBool(true)) - expected += " " - expected += AttributedString("World", attributes: .init().testInt(3)) - XCTAssertEqual(str, expected) - } - - func testSubstringEquality() { - let str = AttributedString("") - let range = str.startIndex ..< str.endIndex - XCTAssertEqual(str[range], str[range]) - - let str2 = "A" + AttributedString("A", attributes: .init().testInt(2)) - let substringA = str2[str2.startIndex ..< str2.index(afterCharacter: str2.startIndex)] - let substringB = str2[str2.index(afterCharacter: str2.startIndex) ..< str2.endIndex] - XCTAssertNotEqual(substringA, substringB) - XCTAssertEqual(substringA, substringA) - XCTAssertEqual(substringB, substringB) - } - - func testInitializationFromSubstring() { - var attrStr = AttributedString("yolo^+1 result<:s>^", attributes: AttributeContainer.testInt(2).testString("Hello")) - attrStr.replaceSubrange(attrStr.range(of: "<:s>")!, with: AttributedString("")) - attrStr[attrStr.range(of: "1 result")!].testInt = 3 - - let range = attrStr.range(of: "+1 result")! - let subFinal = attrStr[range] - let attrFinal = AttributedString(subFinal) - XCTAssertTrue(attrFinal.characters.elementsEqual(subFinal.characters)) - XCTAssertEqual(attrFinal.runs, subFinal.runs) - - var attrStr2 = AttributedString("xxxxxxxx", attributes: .init().testInt(1)) - attrStr2 += AttributedString("y", attributes: .init().testInt(2)) - attrStr2 += AttributedString("zzzzzzzz", attributes: .init().testInt(3)) - - let subrange = attrStr2.index(attrStr2.startIndex, offsetByCharacters: 5) ..< attrStr2.endIndex - let substring2 = attrStr2[subrange] - let recreated = AttributedString(substring2) - XCTAssertEqual(recreated.runs.count, 3) - } - -#if FOUNDATION_FRAMEWORK - // MARK: - Coding Tests - // TODO: Support AttributedString codable conformance in FoundationPreview - struct CodableType : Codable { - // One of potentially many different values being encoded: - @CodableConfiguration(from: \.test) - var attributedString = AttributedString() - } - - func testJSONEncoding() throws { - let encoder = JSONEncoder() - var attrStr = AttributedString("Hello", attributes: AttributeContainer().testBool(true).testString("blue").testInt(1)) - attrStr += AttributedString(" World", attributes: AttributeContainer().testInt(2).testDouble(3.0).testString("http://www.apple.com")) - - let c = CodableType(attributedString: attrStr) - let json = try encoder.encode(c) - - let decoder = JSONDecoder() - let decoded = try decoder.decode(CodableType.self, from: json) - XCTAssertEqual(decoded.attributedString, attrStr) - } - - func testDecodingThenConvertingToNSAttributedString() throws { - let encoder = JSONEncoder() - var attrStr = AttributedString("Hello", attributes: AttributeContainer().testBool(true)) - attrStr += AttributedString(" World", attributes: AttributeContainer().testInt(2)) - let c = CodableType(attributedString: attrStr) - let json = try encoder.encode(c) - - let decoder = JSONDecoder() - let decoded = try decoder.decode(CodableType.self, from: json) - let decodedns = try NSAttributedString(decoded.attributedString, including: AttributeScopes.TestAttributes.self) - let ns = try NSAttributedString(attrStr, including: AttributeScopes.TestAttributes.self) - XCTAssertEqual(ns, decodedns) - } - - func testCustomAttributeCoding() throws { - struct MyAttributes : AttributeScope { - var customCodable : AttributeScopes.TestAttributes.CustomCodableAttribute - } - - struct CodableType : Codable { - @CodableConfiguration(from: MyAttributes.self) - var attributedString = AttributedString() - } - - let encoder = JSONEncoder() - var attrStr = AttributedString("Hello") - attrStr[AttributeScopes.TestAttributes.CustomCodableAttribute.self] = .init(inner: 42) - - let c = CodableType(attributedString: attrStr) - let json = try encoder.encode(c) - - let decoder = JSONDecoder() - let decoded = try decoder.decode(CodableType.self, from: json) - XCTAssertEqual(decoded.attributedString, attrStr) - } - - func testCustomCodableTypeWithCodableAttributedString() throws { - struct MyType : Codable, Equatable { - var other: NonCodableType - var str: AttributedString - - init(other: NonCodableType, str: AttributedString) { - self.other = other - self.str = str - } - - enum Keys : CodingKey { - case other - case str - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Keys.self) - other = NonCodableType(inner: try container.decode(Int.self, forKey: .other)) - str = try container.decode(AttributedString.self, forKey: .str, configuration: AttributeScopes.TestAttributes.self) - } - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: Keys.self) - try container.encode(other.inner, forKey: .other) - try container.encode(str, forKey: .str, configuration: AttributeScopes.TestAttributes.self) - } - } - - var container = AttributeContainer() - container.testInt = 3 - let type = MyType(other: NonCodableType(inner: 2), str: AttributedString("Hello World", attributes: container)) - - let encoder = JSONEncoder() - let data = try encoder.encode(type) - let decoder = JSONDecoder() - let decoded = try decoder.decode(MyType.self, from: data) - XCTAssertEqual(type, decoded) - } - - func testCodingErrorsPropagateUpToCallSite() { - enum CustomAttribute : CodableAttributedStringKey { - typealias Value = String - static let name = "CustomAttribute" - - static func encode(_ value: Value, to encoder: Encoder) throws { - throw TestError.encodingError - } - - static func decode(from decoder: Decoder) throws -> Value { - throw TestError.decodingError - } - } - - struct CustomScope : AttributeScope { - var custom: CustomAttribute - } - - struct Obj : Codable { - @CodableConfiguration(from: CustomScope.self) var str = AttributedString() - } - - var str = AttributedString("Hello, world") - str[CustomAttribute.self] = "test" - let encoder = JSONEncoder() - XCTAssertThrowsError(try encoder.encode(Obj(str: str)), "Attribute encoding error did not throw at call site") { err in - XCTAssert(err is TestError, "Encoding did not throw the proper error") - } - } - - func testEncodeWithPartiallyCodableScope() throws { - enum NonCodableAttribute : AttributedStringKey { - typealias Value = Int - static let name = "NonCodableAttributes" - } - struct PartialCodableScope : AttributeScope { - var codableAttr : AttributeScopes.TestAttributes.TestIntAttribute - var nonCodableAttr : NonCodableAttribute - } - struct Obj : Codable { - @CodableConfiguration(from: PartialCodableScope.self) var str = AttributedString() - } - - var str = AttributedString("Hello, world") - str[AttributeScopes.TestAttributes.TestIntAttribute.self] = 2 - str[NonCodableAttribute.self] = 3 - - let encoder = JSONEncoder() - let data = try encoder.encode(Obj(str: str)) - let decoder = JSONDecoder() - let decoded = try decoder.decode(Obj.self, from: data) - - var expected = str - expected[NonCodableAttribute.self] = nil - XCTAssertEqual(decoded.str, expected) - } - - func testAutomaticCoding() throws { - struct Obj : Codable, Equatable { - @CodableConfiguration(from: AttributeScopes.TestAttributes.self) var attrStr = AttributedString() - @CodableConfiguration(from: AttributeScopes.TestAttributes.self) var optAttrStr : AttributedString? = nil - @CodableConfiguration(from: AttributeScopes.TestAttributes.self) var attrStrArr = [AttributedString]() - @CodableConfiguration(from: AttributeScopes.TestAttributes.self) var optAttrStrArr = [AttributedString?]() - - public init(testValueWithNils: Bool) { - attrStr = AttributedString("Test") - attrStr.testString = "TestAttr" - - attrStrArr = [attrStr, attrStr] - if testValueWithNils { - optAttrStr = nil - optAttrStrArr = [nil, attrStr, nil] - } else { - optAttrStr = attrStr - optAttrStrArr = [attrStr, attrStr] - } - } - } - - // nil - do { - let val = Obj(testValueWithNils: true) - let encoder = JSONEncoder() - let data = try encoder.encode(val) - print(String(data: data, encoding: .utf8)!) - let decoder = JSONDecoder() - let decoded = try decoder.decode(Obj.self, from: data) - - XCTAssertEqual(decoded, val) - } - - // non-nil - do { - let val = Obj(testValueWithNils: false) - let encoder = JSONEncoder() - let data = try encoder.encode(val) - print(String(data: data, encoding: .utf8)!) - let decoder = JSONDecoder() - let decoded = try decoder.decode(Obj.self, from: data) - - XCTAssertEqual(decoded, val) - } - - } - - - func testManualCoding() throws { - struct Obj : Codable, Equatable { - var attrStr : AttributedString - var optAttrStr : AttributedString? - var attrStrArr : [AttributedString] - var optAttrStrArr : [AttributedString?] - - public init(testValueWithNils: Bool) { - attrStr = AttributedString("Test") - attrStr.testString = "TestAttr" - - attrStrArr = [attrStr, attrStr] - if testValueWithNils { - optAttrStr = nil - optAttrStrArr = [nil, attrStr, nil] - } else { - optAttrStr = attrStr - optAttrStrArr = [attrStr, attrStr] - } - } - - enum Keys : CodingKey { - case attrStr - case optAttrStr - case attrStrArr - case optAttrStrArr - } - - func encode(to encoder: Encoder) throws { - var c = encoder.container(keyedBy: Keys.self) - try c.encode(attrStr, forKey: .attrStr, configuration: AttributeScopes.TestAttributes.self) - try c.encodeIfPresent(optAttrStr, forKey: .optAttrStr, configuration: AttributeScopes.TestAttributes.self) - try c.encode(attrStrArr, forKey: .attrStrArr, configuration: AttributeScopes.TestAttributes.self) - try c.encode(optAttrStrArr, forKey: .optAttrStrArr, configuration: AttributeScopes.TestAttributes.self) - } - - init(from decoder: Decoder) throws { - let c = try decoder.container(keyedBy: Keys.self) - attrStr = try c.decode(AttributedString.self, forKey: .attrStr, configuration: AttributeScopes.TestAttributes.self) - optAttrStr = try c.decodeIfPresent(AttributedString.self, forKey: .optAttrStr, configuration: AttributeScopes.TestAttributes.self) - attrStrArr = try c.decode([AttributedString].self, forKey: .attrStrArr, configuration: AttributeScopes.TestAttributes.self) - optAttrStrArr = try c.decode([AttributedString?].self, forKey: .optAttrStrArr, configuration: AttributeScopes.TestAttributes.self) - } - } - - // nil - do { - let val = Obj(testValueWithNils: true) - let encoder = JSONEncoder() - let data = try encoder.encode(val) - print(String(data: data, encoding: .utf8)!) - let decoder = JSONDecoder() - let decoded = try decoder.decode(Obj.self, from: data) - - XCTAssertEqual(decoded, val) - } - - // non-nil - do { - let val = Obj(testValueWithNils: false) - let encoder = JSONEncoder() - let data = try encoder.encode(val) - print(String(data: data, encoding: .utf8)!) - let decoder = JSONDecoder() - let decoded = try decoder.decode(Obj.self, from: data) - - XCTAssertEqual(decoded, val) - } - - } - - func testDecodingCorruptedData() throws { - let jsonStrings = [ - "{\"attributedString\": 2}", - "{\"attributedString\": []}", - "{\"attributedString\": [\"Test\"]}", - "{\"attributedString\": [\"Test\", 0]}", - "{\"attributedString\": [\"\", {}, \"Test\", {}]}", - "{\"attributedString\": [\"Test\", {}, \"\", {}]}", - "{\"attributedString\": [\"\", {\"TestInt\": 1}]}", - "{\"attributedString\": {}}", - "{\"attributedString\": {\"attributeTable\": []}}", - "{\"attributedString\": {\"runs\": []}}", - "{\"attributedString\": {\"runs\": [], \"attributeTable\": []}}", - "{\"attributedString\": {\"runs\": [\"\"], \"attributeTable\": []}}", - "{\"attributedString\": {\"runs\": [\"\", 1], \"attributeTable\": []}}", - "{\"attributedString\": {\"runs\": [\"\", {}, \"Test\", {}], \"attributeTable\": []}}", - "{\"attributedString\": {\"runs\": \"Test\", {}, \"\", {}, \"attributeTable\": []}}", - ] - - let decoder = JSONDecoder() - for string in jsonStrings { - XCTAssertThrowsError(try decoder.decode(CodableType.self, from: string.data(using: .utf8)!), "Corrupt data did not throw error for json data: \(string)") { err in - XCTAssertTrue(err is DecodingError, "Decoding threw an error that was not a DecodingError") - } - } - } - - func testCodableRawRepresentableAttribute() throws { - struct Attribute : CodableAttributedStringKey { - static let name = "MyAttribute" - enum Value: String, Codable, Hashable { - case one = "one" - case two = "two" - case three = "three" - } - } - - struct Scope : AttributeScope { - let attribute: Attribute - } - - struct Object : Codable { - @CodableConfiguration(from: Scope.self) - var str = AttributedString() - } - - var str = AttributedString("Test") - str[Attribute.self] = .two - let encoder = JSONEncoder() - let encoded = try encoder.encode(Object(str: str)) - let decoder = JSONDecoder() - let decoded = try decoder.decode(Object.self, from: encoded) - XCTAssertEqual(decoded.str[Attribute.self], .two) - } - - func testContainerEncoding() throws { - struct ContainerContainer : Codable { - @CodableConfiguration(from: AttributeScopes.TestAttributes.self) var container = AttributeContainer() - } - let obj = ContainerContainer(container: AttributeContainer().testInt(1).testBool(true)) - let encoder = JSONEncoder() - let data = try encoder.encode(obj) - print(String(data: data, encoding: .utf8)!) - let decoder = JSONDecoder() - let decoded = try decoder.decode(ContainerContainer.self, from: data) - - XCTAssertEqual(obj.container, decoded.container) - } - - func testDefaultAttributesCoding() throws { - struct DefaultContainer : Codable, Equatable { - var str : AttributedString - } - - let cont = DefaultContainer(str: AttributedString("Hello", attributes: .init().link(URL(string: "http://apple.com")!))) - let encoder = JSONEncoder() - let encoded = try encoder.encode(cont) - let decoder = JSONDecoder() - let decoded = try decoder.decode(DefaultContainer.self, from: encoded) - XCTAssertEqual(cont, decoded) - } - - func testDecodingMultibyteCharacters() throws { - let json = "{\"str\": [\"🎺ABC\", {\"TestInt\": 2}]}" - struct Object : Codable { - @CodableConfiguration(from: AttributeScopes.TestAttributes.self) var str: AttributedString = AttributedString() - } - let decoder = JSONDecoder() - let str = try decoder.decode(Object.self, from: json.data(using: .utf8)!).str - XCTAssertEqual(str.runs.count, 1) - XCTAssertEqual(str.testInt, 2) - let idx = str.index(beforeCharacter: str.endIndex) - XCTAssertEqual(str.runs[idx].testInt, 2) - } - - // MARK: - Conversion Tests - - func testConversionToObjC() throws { - var ourString = AttributedString("Hello", attributes: AttributeContainer().testInt(2)) - ourString += AttributedString(" ") - ourString += AttributedString("World", attributes: AttributeContainer().testString("Courier")) - let ourObjCString = try NSAttributedString(ourString, including: AttributeScopes.TestAttributes.self) - let theirString = NSMutableAttributedString(string: "Hello World") - theirString.addAttributes([.testInt: NSNumber(value: 2)], range: NSMakeRange(0, 5)) - theirString.addAttributes([.testString: "Courier"], range: NSMakeRange(6, 5)) - XCTAssertEqual(theirString, ourObjCString) - } - - func testConversionFromObjC() throws { - let nsString = NSMutableAttributedString(string: "Hello!") - let rangeA = NSMakeRange(0, 3) - let rangeB = NSMakeRange(3, 3) - nsString.addAttribute(.testString, value: "Courier", range: rangeA) - nsString.addAttribute(.testBool, value: NSNumber(value: true), range: rangeB) - let convertedString = try AttributedString(nsString, including: AttributeScopes.TestAttributes.self) - var string = AttributedString("Hel") - string.testString = "Courier" - string += AttributedString("lo!", attributes: AttributeContainer().testBool(true)) - XCTAssertEqual(string, convertedString) - } - - func testRoundTripConversion_boxed() throws { - struct MyCustomType : Hashable { - var num: Int - var str: String - } - - enum MyCustomAttribute : AttributedStringKey { - typealias Value = MyCustomType - static let name = "MyCustomAttribute" - } - - struct MyCustomScope : AttributeScope { - let attr : MyCustomAttribute - } - - let customVal = MyCustomType(num: 2, str: "test") - var attrString = AttributedString("Hello world") - attrString[MyCustomAttribute.self] = customVal - let nsString = try NSAttributedString(attrString, including: MyCustomScope.self) - let converted = try AttributedString(nsString, including: MyCustomScope.self) - - XCTAssertEqual(converted[MyCustomAttribute.self], customVal) - } - - func testRoundTripConversion_customConversion() throws { - struct MyCustomType : Hashable { } - - enum MyCustomAttribute : ObjectiveCConvertibleAttributedStringKey { - typealias Value = MyCustomType - static let name = "MyCustomAttribute" - - static func objectiveCValue(for value: Value) throws -> NSUUID { NSUUID() } - static func value(for object: NSUUID) throws -> Value { MyCustomType() } - } - - struct MyCustomScope : AttributeScope { - let attr : MyCustomAttribute - } - - let customVal = MyCustomType() - var attrString = AttributedString("Hello world") - attrString[MyCustomAttribute.self] = customVal - let nsString = try NSAttributedString(attrString, including: MyCustomScope.self) - - XCTAssertTrue(nsString.attribute(.init(MyCustomAttribute.name), at: 0, effectiveRange: nil) is NSUUID) - - let converted = try AttributedString(nsString, including: MyCustomScope.self) - XCTAssertEqual(converted[MyCustomAttribute.self], customVal) - } - - func testIncompleteConversionFromObjC() throws { - struct TestStringAttributeOnly : AttributeScope { - var testString: AttributeScopes.TestAttributes.TestStringAttribute // Missing TestBoolAttribute - } - - let nsString = NSMutableAttributedString(string: "Hello!") - let rangeA = NSMakeRange(0, 3) - let rangeB = NSMakeRange(3, 3) - nsString.addAttribute(.testString, value: "Courier", range: rangeA) - nsString.addAttribute(.testBool, value: NSNumber(value: true), range: rangeB) - let converted = try AttributedString(nsString, including: TestStringAttributeOnly.self) - - var expected = AttributedString("Hel", attributes: AttributeContainer().testString("Courier")) - expected += AttributedString("lo!") - XCTAssertEqual(converted, expected) - } - - func testIncompleteConversionToObjC() throws { - struct TestStringAttributeOnly : AttributeScope { - var testString: AttributeScopes.TestAttributes.TestStringAttribute // Missing TestBoolAttribute - } - - var attrStr = AttributedString("Hello ", attributes: .init().testBool(false)) - attrStr += AttributedString("world", attributes: .init().testString("Testing")) - let converted = try NSAttributedString(attrStr, including: TestStringAttributeOnly.self) - - let attrs = converted.attributes(at: 0, effectiveRange: nil) - XCTAssertFalse(attrs.keys.contains(.testBool)) - } - - func testConversionNestedScope() throws { - struct SuperScope : AttributeScope { - var subscope : SubScope - var testString: AttributeScopes.TestAttributes.TestStringAttribute - } - - struct SubScope : AttributeScope { - var testBool : AttributeScopes.TestAttributes.TestBoolAttribute - } - - let nsString = NSMutableAttributedString(string: "Hello!") - let rangeA = NSMakeRange(0, 3) - let rangeB = NSMakeRange(3, 3) - nsString.addAttribute(.testString, value: "Courier", range: rangeA) - nsString.addAttribute(.testBool, value: NSNumber(value: true), range: rangeB) - let converted = try AttributedString(nsString, including: SuperScope.self) - - var expected = AttributedString("Hel", attributes: AttributeContainer().testString("Courier")) - expected += AttributedString("lo!", attributes: AttributeContainer().testBool(true)) - XCTAssertEqual(converted, expected) - } - - func testConversionAttributeContainers() throws { - let container = AttributeContainer.testInt(2).testDouble(3.1).testString("Hello") - - let dictionary = try Dictionary(container, including: \.test) - let expected: [NSAttributedString.Key: Any] = [ - .testInt: 2, - .testDouble: 3.1, - .testString: "Hello" - ] - XCTAssertEqual(dictionary.keys, expected.keys) - XCTAssertEqual(dictionary[.testInt] as! Int, expected[.testInt] as! Int) - XCTAssertEqual(dictionary[.testDouble] as! Double, expected[.testDouble] as! Double) - XCTAssertEqual(dictionary[.testString] as! String, expected[.testString] as! String) - - let container2 = try AttributeContainer(dictionary, including: \.test) - XCTAssertEqual(container, container2) - } - - func testConversionFromInvalidObjectiveCValueTypes() throws { - let nsStr = NSAttributedString(string: "Hello", attributes: [.testInt : "I am not an Int"]) - XCTAssertThrowsError(try AttributedString(nsStr, including: AttributeScopes.TestAttributes.self)) - - struct ConvertibleAttribute: ObjectiveCConvertibleAttributedStringKey { - struct Value : Hashable { - var subValue: String - } - typealias ObjectiveCValue = NSString - static let name = "Convertible" - - static func objectiveCValue(for value: Value) throws -> NSString { - return value.subValue as NSString - } - - static func value(for object: NSString) throws -> Value { - return Value(subValue: object as String) - } - } - struct Scope : AttributeScope { - let convertible: ConvertibleAttribute - } - - let nsStr2 = NSAttributedString(string: "Hello", attributes: [NSAttributedString.Key(ConvertibleAttribute.name) : 12345]) - XCTAssertThrowsError(try AttributedString(nsStr2, including: Scope.self)) - } - - func testConversionToUTF16() throws { - // Ensure that we're correctly using UTF16 offsets with NSAS and UTF8 offsets with AS without mixing the two - let multiByteCharacters = ["\u{2029}", "\u{1D11E}", "\u{1D122}", "\u{1F91A}\u{1F3FB}"] - - for str in multiByteCharacters { - let attrStr = AttributedString(str, attributes: .init().testInt(2)) - let nsStr = NSAttributedString(string: str, attributes: [.testInt: 2]) - - let convertedAttrStr = try AttributedString(nsStr, including: AttributeScopes.TestAttributes.self) - XCTAssertEqual(str.utf8.count, convertedAttrStr._guts.runs.first!.length) - XCTAssertEqual(attrStr, convertedAttrStr) - - let convertedNSStr = try NSAttributedString(attrStr, including: AttributeScopes.TestAttributes.self) - XCTAssertEqual(nsStr, convertedNSStr) - } - } - - func testConversionWithoutScope() throws { - // Ensure simple conversion works (no errors when loading AppKit/UIKit/SwiftUI) - let attrStr = AttributedString() - let nsStr = NSAttributedString(attrStr) - XCTAssertEqual(nsStr, NSAttributedString()) - let attrStrReverse = AttributedString(nsStr) - XCTAssertEqual(attrStrReverse, attrStr) - - // Ensure foundation attributes are converted - let attrStr2 = AttributedString("Hello", attributes: .init().link(URL(string: "http://apple.com")!)) - let nsStr2 = NSAttributedString(attrStr2) - XCTAssertEqual(nsStr2, NSAttributedString(string: "Hello", attributes: [.link : URL(string: "http://apple.com")! as NSURL])) - let attrStr2Reverse = AttributedString(nsStr2) - XCTAssertEqual(attrStr2Reverse, attrStr2) - - // Ensure attributes that throw are dropped - enum Attribute : ObjectiveCConvertibleAttributedStringKey { - static let name = "TestAttribute" - typealias Value = Int - typealias ObjectiveCValue = NSString - - static func objectiveCValue(for value: Int) throws -> NSString { - throw TestError.conversionError - } - - static func value(for object: NSString) throws -> Int { - throw TestError.conversionError - } - } - - struct Scope : AttributeScope { - var test: Attribute - var other: AttributeScopes.TestAttributes - } - - var container = AttributeContainer() - container.testInt = 2 - container[Attribute.self] = 3 - let str = AttributedString("Hello", attributes: container) - let result = try? NSAttributedString(str, attributeTable: Scope.attributeKeyTypes(), options: .dropThrowingAttributes) // The same call that the no-scope initializer will make - XCTAssertEqual(result, NSAttributedString(string: "Hello", attributes: [NSAttributedString.Key("TestInt") : 2])) - } - - func testConversionWithoutScope_Accessibility() throws { -#if !canImport(Accessibility) - throw XCTSkip("Unable to import the Accessibility framework") -#else - let attributedString = AttributedString("Hello", attributes: .init().accessibilityTextCustom(["ABC"])) - let nsAttributedString = NSAttributedString(attributedString) - #if os(macOS) - let attribute = NSAttributedString.Key.accessibilityCustomText - #else - let attribute = NSAttributedString.Key.accessibilityTextCustom - #endif - XCTAssertEqual(nsAttributedString, NSAttributedString(string: "Hello", attributes: [attribute : ["ABC"]])) - let attributedStringReverse = AttributedString(nsAttributedString) - XCTAssertEqual(attributedStringReverse, attributedString) -#endif - } - - func testConversionWithoutScope_AppKit() throws { -#if !canImport(AppKit) - throw XCTSkip("Unable to import the AppKit framework") -#else - var container = AttributeContainer() - container.appKit.kern = 2.3 - let attributedString = AttributedString("Hello", attributes: container) - let nsAttributedString = NSAttributedString(attributedString) - XCTAssertEqual(nsAttributedString, NSAttributedString(string: "Hello", attributes: [.kern : CGFloat(2.3)])) - let attributedStringReverse = AttributedString(nsAttributedString) - XCTAssertEqual(attributedStringReverse, attributedString) -#endif - } - - func testConversionWithoutScope_UIKit() throws { -#if !canImport(UIKit) - throw XCTSkip("Unable to import the UIKit framework") -#else - var container = AttributeContainer() - container.uiKit.kern = 2.3 - let attributedString = AttributedString("Hello", attributes: container) - let nsAttributedString = NSAttributedString(attributedString) - XCTAssertEqual(nsAttributedString, NSAttributedString(string: "Hello", attributes: [.kern : CGFloat(2.3)])) - let attributedStringReverse = AttributedString(nsAttributedString) - XCTAssertEqual(attributedStringReverse, attributedString) -#endif - } - - func testConversionWithoutScope_SwiftUI() throws { -#if !canImport(SwiftUI) - throw XCTSkip("Unable to import the SwiftUI framework") -#else - var container = AttributeContainer() - container.swiftUI.kern = 2.3 - let attributedString = AttributedString("Hello", attributes: container) - let nsAttributedString = NSAttributedString(attributedString) - XCTAssertEqual(nsAttributedString, NSAttributedString(string: "Hello", attributes: [.init("SwiftUI.Kern") : CGFloat(2.3)])) - let attributedStringReverse = AttributedString(nsAttributedString) - XCTAssertEqual(attributedStringReverse, attributedString) -#endif - } - - func testConversionCoalescing() throws { - let nsStr = NSMutableAttributedString("Hello, world") - nsStr.setAttributes([.link : NSURL(string: "http://apple.com")!, .testInt : NSNumber(integerLiteral: 2)], range: NSRange(location: 0, length: 6)) - nsStr.setAttributes([.testInt : NSNumber(integerLiteral: 2)], range: NSRange(location: 6, length: 6)) - let attrStr = try AttributedString(nsStr, including: \.test) - XCTAssertEqual(attrStr.runs.count, 1) - XCTAssertEqual(attrStr.runs.first!.range, attrStr.startIndex ..< attrStr.endIndex) - XCTAssertEqual(attrStr.testInt, 2) - XCTAssertNil(attrStr.link) - } - - func testUnalignedConversion() throws { - let tests: [(NSRange, Int)] = [ - (NSRange(location: 0, length: 12), 1), - (NSRange(location: 5, length: 2), 3), - (NSRange(location: 0, length: 6), 2), - (NSRange(location: 5, length: 1), 3), - (NSRange(location: 6, length: 1), 1), - (NSRange(location: 6, length: 2), 3), - (NSRange(location: 6, length: 6), 2) - ] - - for test in tests { - // U+1F3BA Trumpet (represented by a UTF-16 surrogate pair) - let nsAttributedString = NSMutableAttributedString("Test \u{1F3BA} Test") - nsAttributedString.addAttribute(.testInt, value: NSNumber(1), range: test.0) - let attrStr = try AttributedString(nsAttributedString, including: \.test) - XCTAssertEqual(attrStr.runs.count, test.1, "Replacement of range \(NSStringFromRange(test.0)) caused a run count of \(attrStr.runs.count)") - } - } - -#endif // FOUNDATION_FRAMEWORK - - // MARK: - View Tests - - func testCharViewIndexing_backwardsFromEndIndex() { - let testString = AttributedString("abcdefghi") - let testChars = testString.characters - let testIndex = testChars.index(testChars.endIndex, offsetBy: -1) - XCTAssertEqual(testChars[testIndex], "i") - } - - func testAttrViewIndexing() { - var attrStr = AttributedString("A") - attrStr += "B" - attrStr += "C" - attrStr += "D" - - let attrStrRuns = attrStr.runs - - var i = 0 - var curIdx = attrStrRuns.startIndex - while curIdx < attrStrRuns.endIndex { - i += 1 - curIdx = attrStrRuns.index(after: curIdx) - } - XCTAssertEqual(i, 1) - XCTAssertEqual(attrStrRuns.count, 1) - } - - func testUnicodeScalarsViewIndexing() { - let attrStr = AttributedString("Cafe\u{301}", attributes: AttributeContainer().testInt(1)) - let unicode = attrStr.unicodeScalars - XCTAssertEqual(unicode[unicode.index(before: unicode.endIndex)], "\u{301}") - XCTAssertEqual(unicode[unicode.index(unicode.endIndex, offsetBy: -2)], "e") - } - - func testCharacterSlicing() { - let a: AttributedString = "\u{1f1fa}\u{1f1f8}" // Regional indicators U & S - let i = a.unicodeScalars.index(after: a.startIndex) - let b = a.characters[..( - _ a: some Sequence, - _ b: some Sequence, - file: StaticString = #file, line: UInt = #line - ) { - XCTAssertTrue( - a.elementsEqual(b), - "'\(Array(a))' does not equal '\(Array(b))'", - file: file, line: line) - } - - check(str, astr.characters) - check(str.unicodeScalars, astr.unicodeScalars) - - // Go through all valid range expressions within the two strings and compare slicing - // results. - var i1 = str.unicodeScalars.startIndex - var i2 = astr.unicodeScalars.startIndex - while true { - check(str[..(nsRange, in: str) - XCTAssertNotNil(strRange) - XCTAssertEqual(strRange, str.unicodeScalars.index(str.startIndex, offsetBy: 8) ..< str.unicodeScalars.index(str.startIndex, offsetBy: 9)) - XCTAssertEqual(str[strRange!], "e") - - var attrStrRange = Range(nsRange, in: attrStr) - XCTAssertNotNil(attrStrRange) - XCTAssertEqual(attrStrRange, attrStr.unicodeScalars.index(attrStr.startIndex, offsetBy: 8) ..< attrStr.unicodeScalars.index(attrStr.startIndex, offsetBy: 9)) - XCTAssertEqual(AttributedString(attrStr[attrStrRange!]), AttributedString("e")) - - attrStrRange = Range(strRange!, in: attrStr) - XCTAssertNotNil(attrStrRange) - XCTAssertEqual(attrStrRange, attrStr.unicodeScalars.index(attrStr.startIndex, offsetBy: 8) ..< attrStr.unicodeScalars.index(attrStr.startIndex, offsetBy: 9)) - XCTAssertEqual(AttributedString(attrStr[attrStrRange!]), AttributedString("e")) - - XCTAssertEqual(NSRange(strRange!, in: str), nsRange) - XCTAssertEqual(NSRange(attrStrRange!, in: attrStr), nsRange) - XCTAssertEqual(Range(attrStrRange!, in: str), strRange!) - } - - do { - // U+1F3BA Trumpet (one unicode scalar, two UTF-16) - let str = "Test \u{1F3BA}\u{1F3BA} Test" - let attrStr = AttributedString(str) - let nsRange = NSRange(location: 5, length: 3) // The whole first U+1F3BA and the leading surrogate character of the second U+1F3BA - - let strRange = Range(nsRange, in: str) - XCTAssertNotNil(strRange) - XCTAssertEqual(str[strRange!], "\u{1F3BA}") - - var attrStrRange = Range(nsRange, in: attrStr) - XCTAssertNotNil(attrStrRange) - XCTAssertEqual(AttributedString(attrStr[attrStrRange!]), AttributedString("\u{1F3BA}")) - - attrStrRange = Range(strRange!, in: attrStr) - XCTAssertNotNil(attrStrRange) - XCTAssertEqual(AttributedString(attrStr[attrStrRange!]), AttributedString("\u{1F3BA}")) - - XCTAssertEqual(NSRange(strRange!, in: str), nsRange) - XCTAssertEqual(NSRange(attrStrRange!, in: attrStr), nsRange) - XCTAssertEqual(Range(attrStrRange!, in: str), strRange!) - } - } - - func testNSRangeConversionOnSlice() throws { - let str = AttributedString("012345") - let slice = str[str.index(str.startIndex, offsetByCharacters: 3) ..< str.endIndex] - let nsRange = NSRange(location: 0, length: 2) - let range = try XCTUnwrap(Range(nsRange, in: slice)) - XCTAssertEqual(String(slice[range].characters), "34") - } - -#endif // FOUNDATION_FRAMEWORK - - func testOOBRangeConversion() { - let attrStr = AttributedString("") - let str = "Hello" - let range = str.index(before: str.endIndex) ..< str.endIndex - XCTAssertNil(Range(range, in: attrStr)) - } - -#if FOUNDATION_FRAMEWORK - // TODO: Support scope-specific AttributedString initialization in FoundationPreview - func testScopedCopy() { - var str = AttributedString("A") - str += AttributedString("B", attributes: .init().testInt(2)) - str += AttributedString("C", attributes: .init().link(URL(string: "http://apple.com")!)) - str += AttributedString("D", attributes: .init().testInt(3).link(URL(string: "http://apple.com")!)) - - struct FoundationAndTest : AttributeScope { - let foundation: AttributeScopes.FoundationAttributes - let test: AttributeScopes.TestAttributes - } - XCTAssertEqual(AttributedString(str, including: FoundationAndTest.self), str) - - struct None : AttributeScope { - - } - XCTAssertEqual(AttributedString(str, including: None.self), AttributedString("ABCD")) - - var expected = AttributedString("AB") - expected += AttributedString("CD", attributes: .init().link(URL(string: "http://apple.com")!)) - XCTAssertEqual(AttributedString(str, including: \.foundation), expected) - - expected = AttributedString("A") - expected += AttributedString("B", attributes: .init().testInt(2)) - expected += "C" - expected += AttributedString("D", attributes: .init().testInt(3)) - XCTAssertEqual(AttributedString(str, including: \.test), expected) - - let range = str.index(afterCharacter: str.startIndex) ..< str.index(beforeCharacter: str.endIndex) - expected = AttributedString("B", attributes: .init().testInt(2)) + "C" - XCTAssertEqual(AttributedString(str[range], including: \.test), expected) - - expected = "B" + AttributedString("C", attributes: .init().link(URL(string: "http://apple.com")!)) - XCTAssertEqual(AttributedString(str[range], including: \.foundation), expected) - - XCTAssertEqual(AttributedString(str[range], including: None.self), AttributedString("BC")) - } - - func testScopeIterationAPI() { - struct TestScope : AttributeScope { - let testInt: AttributeScopes.TestAttributes.TestIntAttribute - let testBool: AttributeScopes.TestAttributes.TestBoolAttribute - } - - let testNames = TestScope.attributeKeys.map { $0.name }.sorted() - XCTAssertEqual(testNames, [AttributeScopes.TestAttributes.TestBoolAttribute.name, AttributeScopes.TestAttributes.TestIntAttribute.name].sorted()) - - struct EmptyScope : AttributeScope { - - } - var emptyIterator = EmptyScope.attributeKeys.makeIterator() - XCTAssertNil(emptyIterator.next()) - } -#endif // FOUNDATION_FRAMEWORK - - func testAssignDifferentSubstring() { - var attrStr1 = AttributedString("ABCDE") - let attrStr2 = AttributedString("XYZ") - - attrStr1[ attrStr1.range(of: "BCD")! ] = attrStr2[ attrStr2.range(of: "X")! ] - - XCTAssertEqual(attrStr1, "AXE") - } - - func testCOWDuringSubstringMutation() { - func frobnicate(_ sub: inout AttributedSubstring) { - var new = sub - new.testInt = 2 - new.testString = "Hello" - sub = new - } - var attrStr = AttributedString("ABCDE") - frobnicate(&attrStr[ attrStr.range(of: "BCD")! ]) - - let expected = AttributedString("A") + AttributedString("BCD", attributes: .init().testInt(2).testString("Hello")) + AttributedString("E") - XCTAssertEqual(attrStr, expected) - } - -#if false // This causes an intentional fatalError(), which we can't test for yet, so unfortunately this test can't be enabled. - func testReassignmentDuringMutation() { - func frobnicate(_ sub: inout AttributedSubstring) { - let other = AttributedString("XYZ") - sub = other[ other.range(of: "X")! ] - } - var attrStr = AttributedString("ABCDE") - frobnicate(&attrStr[ attrStr.range(of: "BCD")! ]) - - XCTAssertEqual(attrStr, "AXE") - } -#endif - - func testAssignDifferentCharacterView() { - var attrStr1 = AttributedString("ABC", attributes: .init().testInt(1)) + AttributedString("DE", attributes: .init().testInt(3)) - let attrStr2 = AttributedString("XYZ", attributes: .init().testInt(2)) - - attrStr1.characters = attrStr2.characters - XCTAssertEqual(attrStr1, AttributedString("XYZ", attributes: .init().testInt(1))) - } - - func testCOWDuringCharactersMutation() { - func frobnicate(_ chars: inout AttributedString.CharacterView) { - var new = chars - new.replaceSubrange(chars.startIndex ..< chars.endIndex, with: "XYZ") - chars = new - } - var attrStr = AttributedString("ABCDE", attributes: .init().testInt(1)) - frobnicate(&attrStr.characters) - - XCTAssertEqual(attrStr, AttributedString("XYZ", attributes: .init().testInt(1))) - } - - func testAssignDifferentUnicodeScalarView() { - var attrStr1 = AttributedString("ABC", attributes: .init().testInt(1)) + AttributedString("DE", attributes: .init().testInt(3)) - let attrStr2 = AttributedString("XYZ", attributes: .init().testInt(2)) - - attrStr1.unicodeScalars = attrStr2.unicodeScalars - XCTAssertEqual(attrStr1, AttributedString("XYZ", attributes: .init().testInt(1))) - } - - func testCOWDuringUnicodeScalarsMutation() { - func frobnicate(_ chars: inout AttributedString.CharacterView) { - var new = chars - new.replaceSubrange(chars.startIndex ..< chars.endIndex, with: "XYZ") - chars = new - } - var attrStr = AttributedString("ABCDE", attributes: .init().testInt(1)) - frobnicate(&attrStr.characters) - - XCTAssertEqual(attrStr, AttributedString("XYZ", attributes: .init().testInt(1))) - } - - func testUTF8View() { - let testStrings = [ - "Hello, world", - "🎺😄abc🎶def", - "¡Hola! ¿Cómo estás?", - "שָ×לוֹ×" - ] - - for string in testStrings { - let attrStr = AttributedString(string) - XCTAssertEqual(attrStr.utf8.count, string.utf8.count, "Counts are not equal for string \(string)") - XCTAssertTrue(attrStr.utf8.elementsEqual(string.utf8), "Full elements are not equal for string \(string)") - for offset in 0 ..< string.utf8.count { - let idxInString = string.utf8.index(string.startIndex, offsetBy: offset) - let idxInAttrStr = attrStr.utf8.index(attrStr.startIndex, offsetBy: offset) - XCTAssertEqual( - string.utf8.distance(from: string.startIndex, to: idxInString), - attrStr.utf8.distance(from: attrStr.startIndex, to: idxInAttrStr), - "Offsets to \(idxInString) are not equal for string \(string)" - ) - XCTAssertEqual(string.utf8[idxInString], attrStr.utf8[idxInAttrStr], "Elements at offset \(offset) are not equal for string \(string)") - XCTAssertTrue(string.utf8[..>.size, MemoryLayout?>.size - ) - XCTAssertEqual( - MemoryLayout>.stride, MemoryLayout?>.stride - ) - XCTAssertEqual( - MemoryLayout>.alignment, MemoryLayout?>.alignment - ) - } - - func testInitBufferViewOrdinaryElement() { - let capacity = 4 - let s = (0..(start: nil, count: 0) - _ = BufferView(unsafeBufferPointer: e) - - a.withUnsafeBytes { - let b = BufferView(unsafeRawBufferPointer: $0)! - XCTAssertEqual(b.count, capacity) - - let r = BufferView(unsafeRawBufferPointer: $0)! - XCTAssertEqual(r.count, capacity * MemoryLayout.stride) - } - - let v = UnsafeRawBufferPointer(start: nil, count: 0) - _ = BufferView(unsafeRawBufferPointer: v) - } - - func testIndex() { - let count = 4 - let strings = (1...count).map({ "This String is not BitwiseCopyable (\($0))." }) - strings.withUnsafeBufferPointer { - let buffer = BufferView(unsafeBufferPointer: $0)! - - let first = buffer.startIndex - let second = first.advanced(by: 1) - XCTAssertLessThan(first, second) - XCTAssertEqual(1, first.distance(to: second)) - } - } - - func testIteratorOrdinaryElement() { - let capacity = 4 - let s = (0...stride + offset - var a = Array(repeating: UInt8.zero, count: bytes) - XCTAssertLessThan(offset, MemoryLayout.stride) - - a.withUnsafeMutableBytes { - for i in 0..<$0.count where i % 8 == offset { - $0.storeBytes(of: 1, toByteOffset: i, as: UInt8.self) - } - - let orig = $0.loadUnaligned(as: Int64.self) - XCTAssertNotEqual(orig, 1) - - // BufferView doesn't need to be aligned for accessing `BitwiseCopyable` types. - let buffer = BufferView( - unsafeBaseAddress: $0.baseAddress!.advanced(by: offset), - count: count - ) - - var iterator = buffer.makeIterator() - var buffered = 0 - while let value = iterator.next() { - XCTAssertEqual(value, 1) - buffered += 1 - } - XCTAssertEqual(buffered, count) - } - } - - func testBufferViewSequence() { - let capacity = 4 - let a = Array(0..(unsafeRawBufferPointer: $0)! - let stride = MemoryLayout.stride - - let s0 = view.load(as: String.self) - XCTAssertEqual(s0.contains("0"), true) - let i1 = view.startIndex.advanced(by: stride / 2) - let s1 = view.load(from: i1, as: String.self) - XCTAssertEqual(s1.contains("1"), true) - let s2 = view.load(fromByteOffset: 2 * stride, as: String.self) - XCTAssertEqual(s2.contains("2"), true) - } - } - - func testLoadUnaligned() { - let capacity = 64 - let a = Array(0..(unsafeRawBufferPointer: $0)! - - let u0 = view.dropFirst(1).loadUnaligned(as: UInt64.self) - XCTAssertEqual(u0 & 0xff, 2) - XCTAssertEqual(u0.byteSwapped & 0xff, 9) - let i1 = view.startIndex.advanced(by: 3) - let u1 = view.loadUnaligned(from: i1, as: UInt64.self) - XCTAssertEqual(u1 & 0xff, 6) - let u3 = view.loadUnaligned(fromByteOffset: 7, as: UInt32.self) - XCTAssertEqual(u3 & 0xff, 7) - } - } - - func testOffsetSubscript() { - let capacity = 4 - let a = Array(0.. URL { - // Generate a random file name - URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).appendingPathComponent("testfile-\(UUID().uuidString)") - } - - func generateTestData(count: Int = 16_777_216) -> Data { - let memory = malloc(count)! - let ptr = memory.bindMemory(to: UInt8.self, capacity: count) - - // Set a few bytes so we're sure to not be all zeros - let buf = UnsafeMutableBufferPointer(start: ptr, count: count) - for i in 0..<15 { - for j in 0..<128 { - buf[j * 1024 + i] = UInt8.random(in: 1..<42) - } - } - - return Data(bytesNoCopy: ptr, count: count, deallocator: .free) - } - - func writeAndVerifyTestData(to url: URL, writeOptions: Data.WritingOptions = [], readOptions: Data.ReadingOptions = []) throws { - let data = generateTestData() - try data.write(to: url, options: writeOptions) - let readData = try Data(contentsOf: url, options: readOptions) - XCTAssertEqual(data, readData) - } - - func cleanup(at url: URL) { - do { - try FileManager.default.removeItem(at: url) - } catch { - // Ignore - } - } - - - // MARK: - Tests - - func test_basicReadWrite() throws { - let url = testURL() - try writeAndVerifyTestData(to: url) - cleanup(at: url) - } - - func test_slicedReadWrite() throws { - // Be sure to use progress reporting so we get tests of the chunking - let url = testURL() - let data = generateTestData() - let slice = data[data.startIndex.advanced(by: 1 * 1024 * 1024)..(_ c: (UnsafePointer) throws -> R) rethrows -> R { - return try self.withUnsafeBytes { (ptr) in - return try ptr.baseAddress!.withMemoryRebound(to: UInt8.self, capacity: ptr.count) { - return try c($0) - } - } - } - - mutating func withUnsafeMutableUInt8Bytes(_ c: (UnsafeMutablePointer) throws -> R) rethrows -> R { - return try self.withUnsafeMutableBytes { (ptr) in - return try ptr.baseAddress!.withMemoryRebound(to: UInt8.self, capacity: ptr.count) { - return try c($0) - } - } - } -} - -class DataTests : XCTestCase { - - var heldData: Data? - - // this holds a reference while applying the function which forces the internal ref type to become non-uniquely referenced - func holdReference(_ data: Data, apply: () -> Void) { - heldData = data - apply() - heldData = nil - } - - // MARK: - - - // String of course has its own way to get data, but this way tests our own data struct - func dataFrom(_ string : String) -> Data { - // Create a Data out of those bytes - return string.utf8CString.withUnsafeBufferPointer { (ptr) in - ptr.baseAddress!.withMemoryRebound(to: UInt8.self, capacity: ptr.count) { - // Subtract 1 so we don't get the null terminator byte. This matches NSString behavior. - return Data(bytes: $0, count: ptr.count - 1) - } - } - } - - // MARK: - - - func testBasicConstruction() { - - // Make sure that we were able to create some data - let hello = dataFrom("hello") - let helloLength = hello.count - XCTAssertEqual(hello[0], 0x68, "Unexpected first byte") - - let world = dataFrom(" world") - var helloWorld = hello - world.withUnsafeUInt8Bytes { - helloWorld.append($0, count: world.count) - } - - XCTAssertEqual(hello[0], 0x68, "First byte should not have changed") - XCTAssertEqual(hello.count, helloLength, "Length of first data should not have changed") - XCTAssertEqual(helloWorld.count, hello.count + world.count, "The total length should include both buffers") - } - - func testInitializationWithArray() { - let data = Data([1, 2, 3]) - XCTAssertEqual(3, data.count) - - let data2 = Data([1, 2, 3].filter { $0 >= 2 }) - XCTAssertEqual(2, data2.count) - - let data3 = Data([1, 2, 3, 4, 5][1..<3]) - XCTAssertEqual(2, data3.count) - } - - func testInitializationWithBufferPointer() { - let nilBuffer = UnsafeBufferPointer(start: nil, count: 0) - let data = Data(buffer: nilBuffer) - XCTAssertEqual(data, Data()) - - let validPointer = UnsafeMutablePointer.allocate(capacity: 2) - validPointer[0] = 0xCA - validPointer[1] = 0xFE - defer { validPointer.deallocate() } - - let emptyBuffer = UnsafeBufferPointer(start: validPointer, count: 0) - let data2 = Data(buffer: emptyBuffer) - XCTAssertEqual(data2, Data()) - - let shortBuffer = UnsafeBufferPointer(start: validPointer, count: 1) - let data3 = Data(buffer: shortBuffer) - XCTAssertEqual(data3, Data([0xCA])) - - let fullBuffer = UnsafeBufferPointer(start: validPointer, count: 2) - let data4 = Data(buffer: fullBuffer) - XCTAssertEqual(data4, Data([0xCA, 0xFE])) - - let tuple: (UInt16, UInt16, UInt16, UInt16) = (0xFF, 0xFE, 0xFD, 0xFC) - withUnsafeBytes(of: tuple) { - // If necessary, port this to big-endian. - let tupleBuffer: UnsafeBufferPointer = $0.bindMemory(to: UInt8.self) - let data5 = Data(buffer: tupleBuffer) - XCTAssertEqual(data5, Data([0xFF, 0x00, 0xFE, 0x00, 0xFD, 0x00, 0xFC, 0x00])) - } - } - - func testInitializationWithMutableBufferPointer() { - let nilBuffer = UnsafeMutableBufferPointer(start: nil, count: 0) - let data = Data(buffer: nilBuffer) - XCTAssertEqual(data, Data()) - - let validPointer = UnsafeMutablePointer.allocate(capacity: 2) - validPointer[0] = 0xCA - validPointer[1] = 0xFE - defer { validPointer.deallocate() } - - let emptyBuffer = UnsafeMutableBufferPointer(start: validPointer, count: 0) - let data2 = Data(buffer: emptyBuffer) - XCTAssertEqual(data2, Data()) - - let shortBuffer = UnsafeMutableBufferPointer(start: validPointer, count: 1) - let data3 = Data(buffer: shortBuffer) - XCTAssertEqual(data3, Data([0xCA])) - - let fullBuffer = UnsafeMutableBufferPointer(start: validPointer, count: 2) - let data4 = Data(buffer: fullBuffer) - XCTAssertEqual(data4, Data([0xCA, 0xFE])) - - var tuple: (UInt16, UInt16, UInt16, UInt16) = (0xFF, 0xFE, 0xFD, 0xFC) - withUnsafeMutableBytes(of: &tuple) { - // If necessary, port this to big-endian. - let tupleBuffer: UnsafeMutableBufferPointer = $0.bindMemory(to: UInt8.self) - let data5 = Data(buffer: tupleBuffer) - XCTAssertEqual(data5, Data([0xFF, 0x00, 0xFE, 0x00, 0xFD, 0x00, 0xFC, 0x00])) - } - } - - func testMutableData() { - let hello = dataFrom("hello") - let helloLength = hello.count - XCTAssertEqual(hello[0], 0x68, "Unexpected first byte") - - // Double the length - var mutatingHello = hello - mutatingHello.count *= 2 - - XCTAssertEqual(hello.count, helloLength, "The length of the initial data should not have changed") - XCTAssertEqual(mutatingHello.count, helloLength * 2, "The length should have changed") - - // Get the underlying data for hello2 - mutatingHello.withUnsafeMutableUInt8Bytes { (bytes : UnsafeMutablePointer) in - XCTAssertEqual(bytes.pointee, 0x68, "First byte should be 0x68") - - // Mutate it - bytes.pointee = 0x67 - XCTAssertEqual(bytes.pointee, 0x67, "First byte should be 0x67") - - // Verify that the first data is still correct - XCTAssertEqual(hello[0], 0x68, "The first byte should still be 0x68") - } - } - - func testEquality() { - let d1 = dataFrom("hello") - let d2 = dataFrom("hello") - - // Use == explicitly here to make sure we're calling the right methods - XCTAssertTrue(d1 == d2, "Data should be equal") - } - - func testDataInSet() { - let d1 = dataFrom("Hello") - let d2 = dataFrom("Hello") - let d3 = dataFrom("World") - - var s = Set() - s.insert(d1) - s.insert(d2) - s.insert(d3) - - XCTAssertEqual(s.count, 2, "Expected only two entries in the Set") - } - - func testReplaceSubrange() { - var hello = dataFrom("Hello") - let world = dataFrom("World") - - hello[0] = world[0] - XCTAssertEqual(hello[0], world[0]) - - var goodbyeWorld = dataFrom("Hello World") - let goodbye = dataFrom("Goodbye") - let expected = dataFrom("Goodbye World") - - goodbyeWorld.replaceSubrange(0..<5, with: goodbye) - XCTAssertEqual(goodbyeWorld, expected) - } - - func testReplaceSubrange3() { - // The expected result - let expectedBytes : [UInt8] = [1, 2, 9, 10, 11, 12, 13] - let expected = expectedBytes.withUnsafeBufferPointer { - return Data(buffer: $0) - } - - // The data we'll mutate - let someBytes : [UInt8] = [1, 2, 3, 4, 5] - var a = someBytes.withUnsafeBufferPointer { - return Data(buffer: $0) - } - - // The bytes we'll insert - let b : [UInt8] = [9, 10, 11, 12, 13] - b.withUnsafeBufferPointer { - a.replaceSubrange(2..<5, with: $0) - } - XCTAssertEqual(expected, a) - } - - func testReplaceSubrange4() { - let expectedBytes : [UInt8] = [1, 2, 9, 10, 11, 12, 13] - let expected = Data(expectedBytes) - - // The data we'll mutate - let someBytes : [UInt8] = [1, 2, 3, 4, 5] - var a = Data(someBytes) - - // The bytes we'll insert - let b : [UInt8] = [9, 10, 11, 12, 13] - a.replaceSubrange(2..<5, with: b) - XCTAssertEqual(expected, a) - } - - func testReplaceSubrange5() { - var d = Data([1, 2, 3]) - d.replaceSubrange(0..<0, with: [4]) - XCTAssertEqual(Data([4, 1, 2, 3]), d) - - d.replaceSubrange(0..<4, with: [9]) - XCTAssertEqual(Data([9]), d) - - d.replaceSubrange(0..= 65 && byte <= 90 } - - let allCaps = hello.filter(isCapital) - XCTAssertEqual(allCaps.count, 2) - - let capCount = hello.reduce(0) { isCapital($1) ? $0 + 1 : $0 } - XCTAssertEqual(capCount, 2) - - let allLower = hello.map { isCapital($0) ? $0 + 31 : $0 } - XCTAssertEqual(allLower.count, hello.count) - } - - func testCopyBytes() { - let c = 10 - let underlyingBuffer = malloc(c * MemoryLayout.stride)! - let u16Ptr = underlyingBuffer.bindMemory(to: UInt16.self, capacity: c) - let buffer = UnsafeMutableBufferPointer(start: u16Ptr, count: c) - - buffer[0] = 0 - buffer[1] = 0 - - var data = Data(capacity: c * MemoryLayout.stride) - data.resetBytes(in: 0...stride) - data[0] = 0xFF - data[1] = 0xFF - let copiedCount = data.copyBytes(to: buffer) - XCTAssertEqual(copiedCount, c * MemoryLayout.stride) - - XCTAssertEqual(buffer[0], 0xFFFF) - free(underlyingBuffer) - } - - func testCopyBytes_undersized() { - let a : [UInt8] = [1, 2, 3, 4, 5] - let data = a.withUnsafeBufferPointer { - return Data(buffer: $0) - } - let expectedSize = MemoryLayout.stride * a.count - XCTAssertEqual(expectedSize, data.count) - - let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: expectedSize - 1, alignment: MemoryLayout.size) - // We should only copy in enough bytes that can fit in the buffer - let copiedCount = data.copyBytes(to: buffer) - XCTAssertEqual(expectedSize - 1, copiedCount) - - var index = 0 - for v in a[0...stride * a.count - XCTAssertEqual(expectedSize, data.count) - - let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: expectedSize, alignment: MemoryLayout.size) - let copiedCount = data.copyBytes(to: buffer) - XCTAssertEqual(expectedSize, copiedCount) - - buffer.deallocate() - } - - func testCopyBytes_ranges() { - - do { - // Equal sized buffer, data - let a : [UInt8] = [1, 2, 3, 4, 5] - let data = a.withUnsafeBufferPointer { - return Data(buffer: $0) - } - - let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: data.count, alignment: MemoryLayout.size) - - var copiedCount : Int - - copiedCount = data.copyBytes(to: buffer, from: 0..<0) - XCTAssertEqual(0, copiedCount) - - copiedCount = data.copyBytes(to: buffer, from: 1..<1) - XCTAssertEqual(0, copiedCount) - - copiedCount = data.copyBytes(to: buffer, from: 0..<3) - XCTAssertEqual((0..<3).count, copiedCount) - - var index = 0 - for v in a[0..<3] { - XCTAssertEqual(v, buffer[index]) - index += 1 - } - buffer.deallocate() - } - - do { - // Larger buffer than data - let a : [UInt8] = [1, 2, 3, 4] - let data = a.withUnsafeBufferPointer { - return Data(buffer: $0) - } - - let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 10, alignment: MemoryLayout.size) - var copiedCount : Int - - copiedCount = data.copyBytes(to: buffer, from: 0..<3) - XCTAssertEqual((0..<3).count, copiedCount) - - var index = 0 - for v in a[0..<3] { - XCTAssertEqual(v, buffer[index]) - index += 1 - } - buffer.deallocate() - } - - do { - // Larger data than buffer - let a : [UInt8] = [1, 2, 3, 4, 5, 6] - let data = a.withUnsafeBufferPointer { - return Data(buffer: $0) - } - - let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 4, alignment: MemoryLayout.size) - - var copiedCount : Int - - copiedCount = data.copyBytes(to: buffer, from: 0..(repeating: 8, count: 4) - - destination.withUnsafeMutableBufferPointer { - let count = source.copyBytes(to: $0) - XCTAssertEqual(count, 2) - } - - XCTAssertEqual(destination, [3, 5, 8, 8]) - } - - func test_genericBuffers() { - let a : [Int32] = [1, 0, 1, 0, 1] - var data = a.withUnsafeBufferPointer { - return Data(buffer: $0) - } - - var expectedSize = MemoryLayout.stride * a.count - XCTAssertEqual(expectedSize, data.count) - - [false, true].withUnsafeBufferPointer { - data.append($0) - } - - expectedSize += MemoryLayout.stride * 2 - XCTAssertEqual(expectedSize, data.count) - - let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: expectedSize, alignment: MemoryLayout.size) - let copiedCount = data.copyBytes(to: buffer) - XCTAssertEqual(copiedCount, expectedSize) - buffer.deallocate() - } - - // intentionally structured so sizeof() != strideof() - struct MyStruct { - var time: UInt64 - let x: UInt32 - let y: UInt32 - let z: UInt32 - init() { - time = 0 - x = 1 - y = 2 - z = 3 - } - } - - func test_bufferSizeCalculation() { - // Make sure that Data is correctly using strideof instead of sizeof. - // n.b. if sizeof(MyStruct) == strideof(MyStruct), this test is not as useful as it could be - - // init - let stuff = [MyStruct(), MyStruct(), MyStruct()] - var data = stuff.withUnsafeBufferPointer { - return Data(buffer: $0) - } - - XCTAssertEqual(data.count, MemoryLayout.stride * 3) - - - // append - stuff.withUnsafeBufferPointer { - data.append($0) - } - - XCTAssertEqual(data.count, MemoryLayout.stride * 6) - - // copyBytes - do { - // equal size - let underlyingBuffer = malloc(6 * MemoryLayout.stride)! - defer { free(underlyingBuffer) } - - let ptr = underlyingBuffer.bindMemory(to: MyStruct.self, capacity: 6) - let buffer = UnsafeMutableBufferPointer(start: ptr, count: 6) - - let byteCount = data.copyBytes(to: buffer) - XCTAssertEqual(6 * MemoryLayout.stride, byteCount) - } - - do { - // undersized - let underlyingBuffer = malloc(3 * MemoryLayout.stride)! - defer { free(underlyingBuffer) } - - let ptr = underlyingBuffer.bindMemory(to: MyStruct.self, capacity: 3) - let buffer = UnsafeMutableBufferPointer(start: ptr, count: 3) - - let byteCount = data.copyBytes(to: buffer) - XCTAssertEqual(3 * MemoryLayout.stride, byteCount) - } - - do { - // oversized - let underlyingBuffer = malloc(12 * MemoryLayout.stride)! - defer { free(underlyingBuffer) } - - let ptr = underlyingBuffer.bindMemory(to: MyStruct.self, capacity: 6) - let buffer = UnsafeMutableBufferPointer(start: ptr, count: 6) - - let byteCount = data.copyBytes(to: buffer) - XCTAssertEqual(6 * MemoryLayout.stride, byteCount) - } - } - - - // MARK: - - - func test_repeatingValueInitialization() { - var d = Data(repeating: 0x01, count: 3) - let elements = repeatElement(UInt8(0x02), count: 3) // ensure we fall into the sequence case - d.append(contentsOf: elements) - - XCTAssertEqual(d[0], 0x01) - XCTAssertEqual(d[1], 0x01) - XCTAssertEqual(d[2], 0x01) - - XCTAssertEqual(d[3], 0x02) - XCTAssertEqual(d[4], 0x02) - XCTAssertEqual(d[5], 0x02) - } - - func test_rangeSlice() { - let a: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7] - let d = Data(a) - for i in 0..? = nil, - expectedStartIndex: Int?, - _ message: @autoclosure () -> String = "", - file: StaticString = #filePath, line: UInt = #line) { - if let index = expectedStartIndex { - let expectedRange: Range = index..<(index + fragment.count) - if let someRange = range { - XCTAssertEqual(data.firstRange(of: fragment, in: someRange), expectedRange, message(), file: file, line: line) - } else { - XCTAssertEqual(data.firstRange(of: fragment), expectedRange, message(), file: file, line: line) - } - } else { - if let someRange = range { - XCTAssertNil(data.firstRange(of: fragment, in: someRange), message(), file: file, line: line) - } else { - XCTAssertNil(data.firstRange(of: fragment), message(), file: file, line: line) - } - } - } - - assertFirstRange(base, base, expectedStartIndex: base.startIndex) - assertFirstRange(base, subdata, expectedStartIndex: 2) - assertFirstRange(base, oneByte, expectedStartIndex: 2) - - assertFirstRange(subdata, base, expectedStartIndex: nil) - assertFirstRange(subdata, subdata, expectedStartIndex: subdata.startIndex) - assertFirstRange(subdata, oneByte, expectedStartIndex: subdata.startIndex) - - assertFirstRange(oneByte, base, expectedStartIndex: nil) - assertFirstRange(oneByte, subdata, expectedStartIndex: nil) - assertFirstRange(oneByte, oneByte, expectedStartIndex: oneByte.startIndex) - - assertFirstRange(base, subdata, range: 1...14, expectedStartIndex: 2) - assertFirstRange(base, subdata, range: 6...8, expectedStartIndex: 6) - assertFirstRange(base, subdata, range: 8...10, expectedStartIndex: nil) - - assertFirstRange(base, oneByte, range: 1...14, expectedStartIndex: 2) - assertFirstRange(base, oneByte, range: 6...6, expectedStartIndex: 6) - assertFirstRange(base, oneByte, range: 8...9, expectedStartIndex: nil) - } - - do { // lastRange(of:in:) - func assertLastRange(_ data: Data, _ fragment: Data, range: ClosedRange? = nil, - expectedStartIndex: Int?, - _ message: @autoclosure () -> String = "", - file: StaticString = #filePath, line: UInt = #line) { - if let index = expectedStartIndex { - let expectedRange: Range = index..<(index + fragment.count) - if let someRange = range { - XCTAssertEqual(data.lastRange(of: fragment, in: someRange), expectedRange, file: file, line: line) - } else { - XCTAssertEqual(data.lastRange(of: fragment), expectedRange, message(), file: file, line: line) - } - } else { - if let someRange = range { - XCTAssertNil(data.lastRange(of: fragment, in: someRange), message(), file: file, line: line) - } else { - XCTAssertNil(data.lastRange(of: fragment), message(), file: file, line: line) - } - } - } - - assertLastRange(base, base, expectedStartIndex: base.startIndex) - assertLastRange(base, subdata, expectedStartIndex: 10) - assertLastRange(base, oneByte, expectedStartIndex: 14) - - assertLastRange(subdata, base, expectedStartIndex: nil) - assertLastRange(subdata, subdata, expectedStartIndex: subdata.startIndex) - assertLastRange(subdata, oneByte, expectedStartIndex: subdata.startIndex) - - assertLastRange(oneByte, base, expectedStartIndex: nil) - assertLastRange(oneByte, subdata, expectedStartIndex: nil) - assertLastRange(oneByte, oneByte, expectedStartIndex: oneByte.startIndex) - - assertLastRange(base, subdata, range: 1...14, expectedStartIndex: 10) - assertLastRange(base, subdata, range: 6...8, expectedStartIndex: 6) - assertLastRange(base, subdata, range: 8...10, expectedStartIndex: nil) - - assertLastRange(base, oneByte, range: 1...14, expectedStartIndex: 14) - assertLastRange(base, oneByte, range: 6...6, expectedStartIndex: 6) - assertLastRange(base, oneByte, range: 8...9, expectedStartIndex: nil) - } - } - - func test_sliceAppending() { - // https://bugs.swift.org/browse/SR-4473 - var fooData = Data() - let barData = Data([0, 1, 2, 3, 4, 5]) - let slice = barData.suffix(from: 3) - fooData.append(slice) - XCTAssertEqual(fooData[0], 0x03) - XCTAssertEqual(fooData[1], 0x04) - XCTAssertEqual(fooData[2], 0x05) - } - - func test_sliceWithUnsafeBytes() { - let base = Data([0, 1, 2, 3, 4, 5]) - let slice = base[2..<4] - let segment = slice.withUnsafeUInt8Bytes { (ptr: UnsafePointer) -> [UInt8] in - return [ptr.pointee, ptr.advanced(by: 1).pointee] - } - XCTAssertEqual(segment, [UInt8(2), UInt8(3)]) - } - - func test_sliceIteration() { - let base = Data([0, 1, 2, 3, 4, 5]) - let slice = base[2..<4] - var found = [UInt8]() - for byte in slice { - found.append(byte) - } - XCTAssertEqual(found[0], 2) - XCTAssertEqual(found[1], 3) - } - - func test_sliceIndexing() { - let d = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) - let slice = d[5..<10] - XCTAssertEqual(slice[5], d[5]) - } - - func test_sliceEquality() { - let d = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) - let slice = d[5..<7] - let expected = Data([5, 6]) - XCTAssertEqual(expected, slice) - } - - func test_sliceEquality2() { - let d = Data([5, 6, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) - let slice1 = d[0..<2] - let slice2 = d[5..<7] - XCTAssertEqual(slice1, slice2) - } - - func test_map() { - let d1 = Data([81, 0, 0, 0, 14]) - let d2 = d1[1...4] - XCTAssertEqual(4, d2.count) - let expected: [UInt8] = [0, 0, 0, 14] - let actual = d2.map { $0 } - XCTAssertEqual(expected, actual) - } - - func test_dropFirst() { - let data = Data([0, 1, 2, 3, 4, 5]) - let sliced = data.dropFirst() - XCTAssertEqual(data.count - 1, sliced.count) - XCTAssertEqual(UInt8(1), sliced[1]) - XCTAssertEqual(UInt8(2), sliced[2]) - XCTAssertEqual(UInt8(3), sliced[3]) - XCTAssertEqual(UInt8(4), sliced[4]) - XCTAssertEqual(UInt8(5), sliced[5]) - } - - func test_dropFirst2() { - let data = Data([0, 1, 2, 3, 4, 5]) - let sliced = data.dropFirst(2) - XCTAssertEqual(data.count - 2, sliced.count) - XCTAssertEqual(UInt8(2), sliced[2]) - XCTAssertEqual(UInt8(3), sliced[3]) - XCTAssertEqual(UInt8(4), sliced[4]) - XCTAssertEqual(UInt8(5), sliced[5]) - } - - func test_copyBytes1() { - var array: [UInt8] = [0, 1, 2, 3] - let data = Data(array) - - array.withUnsafeMutableBufferPointer { - data[1..<3].copyBytes(to: $0.baseAddress!, from: 1..<3) - } - XCTAssertEqual([UInt8(1), UInt8(2), UInt8(2), UInt8(3)], array) - } - - func test_copyBytes2() { - let array: [UInt8] = [0, 1, 2, 3] - let data = Data(array) - - let expectedSlice = array[1..<3] - - let start = data.index(after: data.startIndex) - let end = data.index(before: data.endIndex) - let slice = data[start..(_:)` -- a discontiguous sequence of unknown length. - func test_appendingNonContiguousSequence_underestimatedCount() { - var d = Data() - - // d should go from .empty representation to .inline. - // Appending a small enough sequence to fit in .inline should actually be copied. - d.append(contentsOf: (0x00...0x01).makeIterator()) // `.makeIterator()` produces a sequence whose `.underestimatedCount` is 0. - XCTAssertEqual(Data([0x00, 0x01]), d) - - // Appending another small sequence should similarly still work. - d.append(contentsOf: (0x02...0x02).makeIterator()) // `.makeIterator()` produces a sequence whose `.underestimatedCount` is 0. - XCTAssertEqual(Data([0x00, 0x01, 0x02]), d) - - // If we append a sequence of elements larger than a single InlineData, the internal append here should buffer. - // We want to make sure that buffering in this way does not accidentally drop trailing elements on the floor. - d.append(contentsOf: (0x03...0x2F).makeIterator()) // `.makeIterator()` produces a sequence whose `.underestimatedCount` is 0. - XCTAssertEqual(Data([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F]), d) - } - - func test_sequenceInitializers() { - let seq = repeatElement(UInt8(0x02), count: 3) // ensure we fall into the sequence case - - let dataFromSeq = Data(seq) - XCTAssertEqual(3, dataFromSeq.count) - XCTAssertEqual(UInt8(0x02), dataFromSeq[0]) - XCTAssertEqual(UInt8(0x02), dataFromSeq[1]) - XCTAssertEqual(UInt8(0x02), dataFromSeq[2]) - - let array: [UInt8] = [0, 1, 2, 3, 4, 5, 6] - - let dataFromArray = Data(array) - XCTAssertEqual(array.count, dataFromArray.count) - XCTAssertEqual(array[0], dataFromArray[0]) - XCTAssertEqual(array[1], dataFromArray[1]) - XCTAssertEqual(array[2], dataFromArray[2]) - XCTAssertEqual(array[3], dataFromArray[3]) - - let slice = array[1..<4] - - let dataFromSlice = Data(slice) - XCTAssertEqual(slice.count, dataFromSlice.count) - XCTAssertEqual(slice.first, dataFromSlice.first) - XCTAssertEqual(slice.last, dataFromSlice.last) - - let data = Data([1, 2, 3, 4, 5, 6, 7, 8, 9]) - - let dataFromData = Data(data) - XCTAssertEqual(data, dataFromData) - - let sliceOfData = data[1..<3] - - let dataFromSliceOfData = Data(sliceOfData) - XCTAssertEqual(sliceOfData, dataFromSliceOfData) - } - - func test_reversedDataInit() { - let data = Data([1, 2, 3, 4, 5, 6, 7, 8, 9]) - let reversedData = Data(data.reversed()) - let expected = Data([9, 8, 7, 6, 5, 4, 3, 2, 1]) - XCTAssertEqual(expected, reversedData) - } - - func test_validateMutation_withUnsafeMutableBytes() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - data.withUnsafeMutableUInt8Bytes { (ptr: UnsafeMutablePointer) in - ptr.advanced(by: 5).pointee = 0xFF - } - XCTAssertEqual(data, Data([0, 1, 2, 3, 4, 0xFF, 6, 7, 8, 9])) - } - - func test_validateMutation_appendBytes() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - data.append("hello", count: 5) - XCTAssertEqual(data[data.startIndex.advanced(by: 5)], 0x5) - } - - func test_validateMutation_appendData() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - let other = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - data.append(other) - XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9) - XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0) - } - - func test_validateMutation_appendBuffer() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - bytes.withUnsafeBufferPointer { data.append($0) } - XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9) - XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0) - } - - func test_validateMutation_appendSequence() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - let seq = repeatElement(UInt8(1), count: 10) - data.append(contentsOf: seq) - XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9) - XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 1) - } - - func test_validateMutation_appendContentsOf() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - data.append(contentsOf: bytes) - XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9) - XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0) - } - - func test_validateMutation_resetBytes() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - data.resetBytes(in: 5..<8) - XCTAssertEqual(data, Data([0, 1, 2, 3, 4, 0, 0, 0, 8, 9])) - } - - func test_validateMutation_replaceSubrange() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - let range: Range = data.startIndex.advanced(by: 4).. = data.startIndex.advanced(by: 4).. = data.startIndex.advanced(by: 4).. = data.startIndex.advanced(by: 4).. = data.startIndex.advanced(by: 4)..) in - ptr.advanced(by: 1).pointee = 0xFF - } - XCTAssertEqual(data, Data([4, 0xFF, 6, 7, 8])) - } - - func test_validateMutation_slice_appendBytes() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - let bytes: [UInt8] = [0xFF, 0xFF] - bytes.withUnsafeBufferPointer { data.append($0.baseAddress!, count: $0.count) } - XCTAssertEqual(data, Data([4, 5, 6, 7, 8, 0xFF, 0xFF])) - } - - func test_validateMutation_slice_appendData() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - let other = Data([0xFF, 0xFF]) - data.append(other) - XCTAssertEqual(data, Data([4, 5, 6, 7, 8, 0xFF, 0xFF])) - } - - func test_validateMutation_slice_appendBuffer() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - let bytes: [UInt8] = [0xFF, 0xFF] - bytes.withUnsafeBufferPointer { data.append($0) } - XCTAssertEqual(data, Data([4, 5, 6, 7, 8, 0xFF, 0xFF])) - } - - func test_validateMutation_slice_appendSequence() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - let seq = repeatElement(UInt8(0xFF), count: 2) - data.append(contentsOf: seq) - XCTAssertEqual(data, Data([4, 5, 6, 7, 8, 0xFF, 0xFF])) - } - - func test_validateMutation_slice_appendContentsOf() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - let bytes: [UInt8] = [0xFF, 0xFF] - data.append(contentsOf: bytes) - XCTAssertEqual(data, Data([4, 5, 6, 7, 8, 0xFF, 0xFF])) - } - - func test_validateMutation_slice_resetBytes() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - data.resetBytes(in: 5..<8) - XCTAssertEqual(data, Data([4, 0, 0, 0, 8])) - } - - func test_validateMutation_slice_replaceSubrange() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - let range: Range = data.startIndex.advanced(by: 1).. = data.startIndex.advanced(by: 1).. = data.startIndex.advanced(by: 1).. = data.startIndex.advanced(by: 1).. = data.startIndex.advanced(by: 1)..) in - ptr.advanced(by: 5).pointee = 0xFF - } - XCTAssertEqual(data, Data([0, 1, 2, 3, 4, 0xFF, 6, 7, 8, 9])) - } - } - - func test_validateMutation_cow_appendBytes() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - holdReference(data) { - data.append("hello", count: 5) - XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 0x9) - XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0x68) - } - } - - func test_validateMutation_cow_appendData() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - holdReference(data) { - let other = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - data.append(other) - XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9) - XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0) - } - } - - func test_validateMutation_cow_appendBuffer() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - holdReference(data) { - let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - bytes.withUnsafeBufferPointer { data.append($0) } - XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9) - XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0) - } - } - - func test_validateMutation_cow_appendSequence() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - holdReference(data) { - let seq = repeatElement(UInt8(1), count: 10) - data.append(contentsOf: seq) - XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9) - XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 1) - } - } - - func test_validateMutation_cow_appendContentsOf() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - holdReference(data) { - let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - data.append(contentsOf: bytes) - XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9) - XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0) - } - } - - func test_validateMutation_cow_resetBytes() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - holdReference(data) { - data.resetBytes(in: 5..<8) - XCTAssertEqual(data, Data([0, 1, 2, 3, 4, 0, 0, 0, 8, 9])) - } - } - - func test_validateMutation_cow_replaceSubrange() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - holdReference(data) { - let range: Range = data.startIndex.advanced(by: 4).. = data.startIndex.advanced(by: 4).. = data.startIndex.advanced(by: 4).. = data.startIndex.advanced(by: 4).. = data.startIndex.advanced(by: 4)..) in - ptr.advanced(by: 1).pointee = 0xFF - } - XCTAssertEqual(data, Data([4, 0xFF, 6, 7, 8])) - } - } - - func test_validateMutation_slice_cow_appendBytes() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - holdReference(data) { - data.append("hello", count: 5) - XCTAssertEqual(data[data.startIndex.advanced(by: 4)], 0x8) - XCTAssertEqual(data[data.startIndex.advanced(by: 5)], 0x68) - } - } - - func test_validateMutation_slice_cow_appendData() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - holdReference(data) { - let other = Data([0xFF, 0xFF]) - data.append(other) - XCTAssertEqual(data, Data([4, 5, 6, 7, 8, 0xFF, 0xFF])) - } - } - - func test_validateMutation_slice_cow_appendBuffer() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - holdReference(data) { - let bytes: [UInt8] = [0xFF, 0xFF] - bytes.withUnsafeBufferPointer { data.append($0) } - XCTAssertEqual(data, Data([4, 5, 6, 7, 8, 0xFF, 0xFF])) - } - } - - func test_validateMutation_slice_cow_appendSequence() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - holdReference(data) { - let seq = repeatElement(UInt8(0xFF), count: 2) - data.append(contentsOf: seq) - XCTAssertEqual(data, Data([4, 5, 6, 7, 8, 0xFF, 0xFF])) - } - } - - func test_validateMutation_slice_cow_appendContentsOf() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - holdReference(data) { - let bytes: [UInt8] = [0xFF, 0xFF] - data.append(contentsOf: bytes) - XCTAssertEqual(data, Data([4, 5, 6, 7, 8, 0xFF, 0xFF])) - } - } - - func test_validateMutation_slice_cow_resetBytes() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - holdReference(data) { - data.resetBytes(in: 5..<8) - XCTAssertEqual(data, Data([4, 0, 0, 0, 8])) - } - } - - func test_validateMutation_slice_cow_replaceSubrange() { - var data = Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9] - holdReference(data) { - let range: Range = data.startIndex.advanced(by: 1).. = data.startIndex.advanced(by: 1).. = data.startIndex.advanced(by: 1).. = data.startIndex.advanced(by: 1).. = data.startIndex.advanced(by: 1)..) in - ptr.advanced(by: 1).pointee = 0xFF - } - XCTAssertEqual(data, Data([4, 0xFF])) - } - - func test_increaseCount() { - let initials: [Range] = [ - 0..<0, - 0..<2, - 0..<4, - 0..<8, - 0..<16, - 0..<32, - 0..<64 - ] - let diffs = [0, 1, 2, 4, 8, 16, 32] - for initial in initials { - for diff in diffs { - var data = Data(initial) - data.count += diff - XCTAssertEqual( - Data(Array(initial) + Array(repeating: 0, count: diff)), - data) - } - } - } - - func test_decreaseCount() { - let initials: [Range] = [ - 0..<0, - 0..<2, - 0..<4, - 0..<8, - 0..<16, - 0..<32, - 0..<64 - ] - let diffs = [0, 1, 2, 4, 8, 16, 32] - for initial in initials { - for diff in diffs { - guard initial.count >= diff else { continue } - var data = Data(initial) - data.count -= diff - XCTAssertEqual( - Data(initial.dropLast(diff)), - data) - } - } - } - - func test_decrease_increase_count() { - var data = Data(Array(repeating: 0, count: 8) + [42]) - data.count -= 1 - XCTAssertEqual(Data(Array(repeating: 0, count: 8)), data) - data.count += 1 - XCTAssertEqual(Data(Array(repeating: 0, count: 9)), data) - - data = Data(Array(repeating: 0, count: 64) + [42]) - data.count -= 1 - XCTAssertEqual(Data(Array(repeating: 0, count: 64)), data) - data.count += 1 - XCTAssertEqual(Data(Array(repeating: 0, count: 65)), data) - } - - // This is a (potentially invalid) sequence that produces a configurable number of 42s and has a freely customizable `underestimatedCount`. - struct TestSequence: Sequence { - typealias Element = UInt8 - struct Iterator: IteratorProtocol { - var _remaining: Int - init(_ count: Int) { - _remaining = count - } - mutating func next() -> UInt8? { - guard _remaining > 0 else { return nil } - _remaining -= 1 - return 42 - } - } - let underestimatedCount: Int - let count: Int - - func makeIterator() -> Iterator { - return Iterator(count) - } - } - - func test_init_TestSequence() { - // Underestimated count - do { - let d = Data(TestSequence(underestimatedCount: 0, count: 10)) - XCTAssertEqual(10, d.count) - XCTAssertEqual(Array(repeating: 42 as UInt8, count: 10), Array(d)) - } - - // Very underestimated count (to exercise realloc path) - do { - let d = Data(TestSequence(underestimatedCount: 0, count: 1000)) - XCTAssertEqual(1000, d.count) - XCTAssertEqual(Array(repeating: 42 as UInt8, count: 1000), Array(d)) - } - - // Exact count - do { - let d = Data(TestSequence(underestimatedCount: 10, count: 10)) - XCTAssertEqual(10, d.count) - XCTAssertEqual(Array(repeating: 42 as UInt8, count: 10), Array(d)) - } - - // Overestimated count. This is an illegal case, so trapping would be fine. - // However, for compatibility with the implementation in Swift 5, Data - // handles this case by simply truncating itself to the actual size. - do { - let d = Data(TestSequence(underestimatedCount: 20, count: 10)) - XCTAssertEqual(10, d.count) - XCTAssertEqual(Array(repeating: 42 as UInt8, count: 10), Array(d)) - } - } - - func test_append_TestSequence() { - let base = Data(Array(repeating: 23 as UInt8, count: 10)) - - // Underestimated count - do { - var d = base - d.append(contentsOf: TestSequence(underestimatedCount: 0, count: 10)) - XCTAssertEqual(20, d.count) - XCTAssertEqual(Array(base) + Array(repeating: 42 as UInt8, count: 10), - Array(d)) - } - - // Very underestimated count (to exercise realloc path) - do { - var d = base - d.append(contentsOf: TestSequence(underestimatedCount: 0, count: 1000)) - XCTAssertEqual(1010, d.count) - XCTAssertEqual(Array(base) + Array(repeating: 42 as UInt8, count: 1000), Array(d)) - } - - // Exact count - do { - var d = base - d.append(contentsOf: TestSequence(underestimatedCount: 10, count: 10)) - XCTAssertEqual(20, d.count) - XCTAssertEqual(Array(base) + Array(repeating: 42 as UInt8, count: 10), Array(d)) - } - - // Overestimated count. This is an illegal case, so trapping would be fine. - // However, for compatibility with the implementation in Swift 5, Data - // handles this case by simply truncating itself to the actual size. - do { - var d = base - d.append(contentsOf: TestSequence(underestimatedCount: 20, count: 10)) - XCTAssertEqual(20, d.count) - XCTAssertEqual(Array(base) + Array(repeating: 42 as UInt8, count: 10), Array(d)) - } - } - - func testAdvancedBy() { - let source: Data = Data([1, 42, 64, 8]) - XCTAssertEqual(source.advanced(by: 0), Data([1, 42, 64, 8])) - XCTAssertEqual(source.advanced(by: 2), Data([64, 8])) - XCTAssertEqual(source.advanced(by: 4), Data()) - // Make sure .advanced creates a new data - XCTAssert(source.advanced(by: 3).startIndex == 0) - // Make sure .advanced works on Data whose `startIndex` isn't 0 - let offsetData: Data = Data([1, 42, 64, 8, 90, 80])[1..<5] - XCTAssertEqual(offsetData.advanced(by: 0), Data([42, 64, 8, 90])) - XCTAssertEqual(offsetData.advanced(by: 2), Data([8, 90])) - XCTAssertEqual(offsetData.advanced(by: 4), Data()) - XCTAssert(offsetData.advanced(by: 3).startIndex == 0) - - // FIXME: XCTest doesn't support crash tests yet rdar://20195010&22387653 - // source.advanced(by: -1) - // source.advanced(by: 5) - } - - - #if false // FIXME: XCTest doesn't support crash tests yet rdar://20195010&22387653 - func test_bounding_failure_subdata() { - let data = "Hello World".data(using: .utf8)! - expectCrashLater() - let c = data.subdata(in: 5..<200) - } - #endif - - #if false // FIXME: XCTest doesn't support crash tests yet rdar://20195010&22387653 - func test_bounding_failure_replace() { - var data = "Hello World".data(using: .utf8)! - expectCrashLater() - data.replaceSubrange(5..<200, with: Data()) - } - #endif - - #if false // FIXME: XCTest doesn't support crash tests yet rdar://20195010&22387653 - func test_bounding_failure_replace2() { - var data = "a".data(using: .utf8)! - var bytes : [UInt8] = [1, 2, 3] - expectCrashLater() - bytes.withUnsafeBufferPointer { - // lowerBound ok, upperBound after end of data - data.replaceSubrange(0..<2, with: $0) - } - } - #endif - - #if false // FIXME: XCTest doesn't support crash tests yet rdar://20195010&22387653 - func test_bounding_failure_replace3() { - var data = "a".data(using: .utf8)! - var bytes : [UInt8] = [1, 2, 3] - expectCrashLater() - bytes.withUnsafeBufferPointer { - // lowerBound is > length - data.replaceSubrange(2..<4, with: $0) - } - } - #endif - - #if false // FIXME: XCTest doesn't support crash tests yet rdar://20195010&22387653 - func test_bounding_failure_replace4() { - var data = "a".data(using: .utf8)! - var bytes : [UInt8] = [1, 2, 3] - expectCrashLater() - // lowerBound is > length - data.replaceSubrange(2..<4, with: bytes) - } - #endif - - #if false // FIXME: XCTest doesn't support crash tests yet rdar://20195010&22387653 - func test_bounding_failure_reset_range() { - var data = "Hello World".data(using: .utf8)! - expectCrashLater() - data.resetBytes(in: 100..<200) - } - #endif - - #if false // FIXME: XCTest doesn't support crash tests yet rdar://20195010&22387653 - func test_bounding_failure_append_bad_length() { - var data = "Hello World".data(using: .utf8)! - expectCrashLater() - data.append("hello", count: -2) - } - #endif - - #if false // FIXME: XCTest doesn't support crash tests yet rdar://20195010&22387653 - func test_bounding_failure_append_absurd_length() { - var data = "Hello World".data(using: .utf8)! - expectCrashLater() - data.append("hello", count: Int.min) - } - #endif - - #if false // FIXME: XCTest doesn't support crash tests yet rdar://20195010&22387653 - func test_bounding_failure_subscript() { - var data = "Hello World".data(using: .utf8)! - expectCrashLater() - data[100] = 4 - } - #endif -} - -#if FOUNDATION_FRAMEWORK // FIXME: Re-enable test after String.data(using:) is implemented -extension DataTests { - func test_splittingHttp() { - func split(_ data: Data, on delimiter: String) -> [Data] { - let dataDelimiter = delimiter.data(using: .utf8)! - var found = [Data]() - let start = data.startIndex - let end = data.endIndex.advanced(by: -dataDelimiter.count) - guard end >= start else { return [data] } - var index = start - var previousIndex = index - while index < end { - let slice = data[index..) -> Int in - let slice = Data(bytesNoCopy: UnsafeMutablePointer(mutating: bytes), count: 1, deallocator: .none) - return slice.count - } - XCTAssertEqual(len, 1) - } - - func test_discontiguousEnumerateBytes() { - let dataToEncode = "Hello World".data(using: .utf8)! - - let subdata1 = dataToEncode.withUnsafeBytes { bytes in - return DispatchData(bytes: bytes) - } - let subdata2 = dataToEncode.withUnsafeBytes { bytes in - return DispatchData(bytes: bytes) - } - var data = subdata1 - data.append(subdata2) - - var numChunks = 0 - var offsets = [Int]() - data.enumerateBytes() { buffer, offset, stop in - numChunks += 1 - offsets.append(offset) - } - - XCTAssertEqual(2, numChunks, "composing two dispatch_data should enumerate as structural data as 2 chunks") - XCTAssertEqual(0, offsets[0], "composing two dispatch_data should enumerate as structural data with the first offset as the location of the region") - XCTAssertEqual(dataToEncode.count, offsets[1], "composing two dispatch_data should enumerate as structural data with the first offset as the location of the region") - } - - func test_rangeOfSlice() { - let data = "FooBar".data(using: .ascii)! - let slice = data[3...] // Bar - - let range = slice.range(of: "a".data(using: .ascii)!) - XCTAssertEqual(range, 4..<5 as Range) - } -} -#endif - -// MARK: - Base64 Encode/Decode Tests - -extension DataTests { - - func test_base64Encode_emptyData() { - XCTAssertEqual(Data().base64EncodedString(), "") - XCTAssertEqual(Data().base64EncodedData(), Data()) - } - - func test_base64Encode_arrayOfNulls() { - let input = Data(repeating: 0, count: 10) - XCTAssertEqual(input.base64EncodedString(), "AAAAAAAAAAAAAA==") - XCTAssertEqual(input.base64EncodedData(), Data("AAAAAAAAAAAAAA==".utf8)) - } - - func test_base64Encode_differentPaddingNeeds() { - XCTAssertEqual(Data([1, 2, 3, 4]).base64EncodedString(), "AQIDBA==") - XCTAssertEqual(Data([1, 2, 3, 4, 5]).base64EncodedString(), "AQIDBAU=") - XCTAssertEqual(Data([1, 2, 3, 4, 5, 6]).base64EncodedString(), "AQIDBAUG") - - XCTAssertEqual(Data([1, 2, 3, 4]).base64EncodedString(options: [.lineLength64Characters]), "AQIDBA==") - XCTAssertEqual(Data([1, 2, 3, 4, 5]).base64EncodedString(options: [.lineLength64Characters]), "AQIDBAU=") - XCTAssertEqual(Data([1, 2, 3, 4, 5, 6]).base64EncodedString(options: [.lineLength64Characters]), "AQIDBAUG") - } - - func test_base64Encode_addingLinebreaks() { - let input = """ - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut at tincidunt arcu. Suspendisse nec sodales erat, sit amet imperdiet ipsum. Etiam sed ornare felis. - """ - - // using .endLineWithLineFeed - XCTAssertEqual( - Data(input.utf8).base64EncodedString(options: [.lineLength64Characters, .endLineWithLineFeed]), - """ - TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2Np\n\ - bmcgZWxpdC4gVXQgYXQgdGluY2lkdW50IGFyY3UuIFN1c3BlbmRpc3NlIG5lYyBz\n\ - b2RhbGVzIGVyYXQsIHNpdCBhbWV0IGltcGVyZGlldCBpcHN1bS4gRXRpYW0gc2Vk\n\ - IG9ybmFyZSBmZWxpcy4= - """ - ) - XCTAssertEqual( - Data(input.utf8).base64EncodedString(options: [.lineLength76Characters, .endLineWithLineFeed]), - """ - TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4g\n\ - VXQgYXQgdGluY2lkdW50IGFyY3UuIFN1c3BlbmRpc3NlIG5lYyBzb2RhbGVzIGVyYXQsIHNpdCBh\n\ - bWV0IGltcGVyZGlldCBpcHN1bS4gRXRpYW0gc2VkIG9ybmFyZSBmZWxpcy4= - """ - ) - - // using .endLineWithCarriageReturn - XCTAssertEqual( - Data(input.utf8).base64EncodedString(options: [.lineLength64Characters, .endLineWithCarriageReturn]), - """ - TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2Np\r\ - bmcgZWxpdC4gVXQgYXQgdGluY2lkdW50IGFyY3UuIFN1c3BlbmRpc3NlIG5lYyBz\r\ - b2RhbGVzIGVyYXQsIHNpdCBhbWV0IGltcGVyZGlldCBpcHN1bS4gRXRpYW0gc2Vk\r\ - IG9ybmFyZSBmZWxpcy4= - """ - ) - XCTAssertEqual( - Data(input.utf8).base64EncodedString(options: [.lineLength76Characters, .endLineWithCarriageReturn]), - """ - TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4g\r\ - VXQgYXQgdGluY2lkdW50IGFyY3UuIFN1c3BlbmRpc3NlIG5lYyBzb2RhbGVzIGVyYXQsIHNpdCBh\r\ - bWV0IGltcGVyZGlldCBpcHN1bS4gRXRpYW0gc2VkIG9ybmFyZSBmZWxpcy4= - """ - ) - - // using .endLineWithLineFeed, .endLineWithCarriageReturn - XCTAssertEqual( - Data(input.utf8).base64EncodedString(options: [.lineLength64Characters, .endLineWithLineFeed, .endLineWithCarriageReturn]), - """ - TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2Np\r\n\ - bmcgZWxpdC4gVXQgYXQgdGluY2lkdW50IGFyY3UuIFN1c3BlbmRpc3NlIG5lYyBz\r\n\ - b2RhbGVzIGVyYXQsIHNpdCBhbWV0IGltcGVyZGlldCBpcHN1bS4gRXRpYW0gc2Vk\r\n\ - IG9ybmFyZSBmZWxpcy4= - """ - ) - XCTAssertEqual( - Data(input.utf8).base64EncodedString(options: [.lineLength76Characters, .endLineWithLineFeed, .endLineWithCarriageReturn]), - """ - TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4g\r\n\ - VXQgYXQgdGluY2lkdW50IGFyY3UuIFN1c3BlbmRpc3NlIG5lYyBzb2RhbGVzIGVyYXQsIHNpdCBh\r\n\ - bWV0IGltcGVyZGlldCBpcHN1bS4gRXRpYW0gc2VkIG9ybmFyZSBmZWxpcy4= - """ - ) - - // using no explicit endLine option - XCTAssertEqual( - Data(input.utf8).base64EncodedString(options: [.lineLength64Characters]), - """ - TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2Np\r\n\ - bmcgZWxpdC4gVXQgYXQgdGluY2lkdW50IGFyY3UuIFN1c3BlbmRpc3NlIG5lYyBz\r\n\ - b2RhbGVzIGVyYXQsIHNpdCBhbWV0IGltcGVyZGlldCBpcHN1bS4gRXRpYW0gc2Vk\r\n\ - IG9ybmFyZSBmZWxpcy4= - """ - ) - XCTAssertEqual( - Data(input.utf8).base64EncodedString(options: [.lineLength76Characters]), - """ - TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4g\r\n\ - VXQgYXQgdGluY2lkdW50IGFyY3UuIFN1c3BlbmRpc3NlIG5lYyBzb2RhbGVzIGVyYXQsIHNpdCBh\r\n\ - bWV0IGltcGVyZGlldCBpcHN1bS4gRXRpYW0gc2VkIG9ybmFyZSBmZWxpcy4= - """ - ) - } - - func test_base64Encode_DoesNotAddLineSeparatorsInLastLineWhenStringFitsInLine() { - XCTAssertEqual( - Data(repeating: 0, count: 48).base64EncodedString(options: .lineLength64Characters), - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - ) - - XCTAssertEqual( - Data(repeating: 0, count: 96).base64EncodedString(options: .lineLength64Characters), - """ - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\n\ - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - """ - ) - print([UInt8](Data(repeating: 0, count: 96).base64EncodedString(options: .lineLength64Characters).utf8)) - - XCTAssertEqual( - Data(repeating: 0, count: 57).base64EncodedString(options: .lineLength76Characters), - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - ) - - XCTAssertEqual( - Data(repeating: 0, count: 114).base64EncodedString(options: .lineLength76Characters), - """ - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\n\ - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - """ - ) - - } - - func test_base64Decode_emptyString() { - XCTAssertEqual(Data(), Data(base64Encoded: "")) - } - - func test_base64Decode_emptyData() { - XCTAssertEqual(Data(), Data(base64Encoded: Data())) - } - - func test_base64Decode_arrayOfNulls() { - XCTAssertEqual(Data(repeating: 0, count: 10), Data(base64Encoded: "AAAAAAAAAAAAAA==")) - } - - func test_base64Decode_AllTheBytesSequentially() { - let base64 = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==" - - XCTAssertEqual(Data(UInt8(0) ... UInt8(255)), Data(base64Encoded: base64)) - } - - func test_base64Decode_ignoringLineBreaks() { - let base64 = """ - TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2Np\r\n\ - bmcgZWxpdC4gVXQgYXQgdGluY2lkdW50IGFyY3UuIFN1c3BlbmRpc3NlIG5lYyBz\r\n\ - b2RhbGVzIGVyYXQsIHNpdCBhbWV0IGltcGVyZGlldCBpcHN1bS4gRXRpYW0gc2Vk\r\n\ - IG9ybmFyZSBmZWxpcy4= - """ - let expected = """ - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut at tincidunt arcu. Suspendisse nec sodales erat, sit amet imperdiet ipsum. Etiam sed ornare felis. - """ - - XCTAssertEqual(Data(expected.utf8), Data(base64Encoded: base64, options: .ignoreUnknownCharacters)) - } - - func test_base64Decode_invalidLength() { - XCTAssertNil(Data(base64Encoded: "AAAAA")) - XCTAssertNil(Data(base64Encoded: "AAAAA", options: .ignoreUnknownCharacters)) - } - - func test_base64Decode_variousPaddingNeeds() { - XCTAssertEqual(Data([1, 2, 3, 4]), Data(base64Encoded: "AQIDBA==")) - XCTAssertEqual(Data([1, 2, 3, 4, 5]), Data(base64Encoded: "AQIDBAU=")) - XCTAssertEqual(Data([1, 2, 3, 4, 5, 6]), Data(base64Encoded: "AQIDBAUG")) - } - - func test_base64Decode_ignoreWhitespaceAtVariousPlaces() { - XCTAssertEqual(Data([1, 2, 3, 4]), Data(base64Encoded: " AQIDBA==", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4]), Data(base64Encoded: "A QIDBA==", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4]), Data(base64Encoded: "AQ IDBA==", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4]), Data(base64Encoded: "AQI DBA==", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4]), Data(base64Encoded: "AQID BA==", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4]), Data(base64Encoded: "AQIDB A==", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4]), Data(base64Encoded: "AQIDBA ==", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4]), Data(base64Encoded: "AQIDBA= =", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4]), Data(base64Encoded: "AQIDBA== ", options: .ignoreUnknownCharacters)) - - XCTAssertEqual(Data([1, 2, 3, 4, 5]), Data(base64Encoded: " AQIDBAU=", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5]), Data(base64Encoded: "A QIDBAU=", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5]), Data(base64Encoded: "AQ IDBAU=", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5]), Data(base64Encoded: "AQI DBAU=", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5]), Data(base64Encoded: "AQID BAU=", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5]), Data(base64Encoded: "AQIDB AU=", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5]), Data(base64Encoded: "AQIDBA U=", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5]), Data(base64Encoded: "AQIDBAU =", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5]), Data(base64Encoded: "AQIDBAU= ", options: .ignoreUnknownCharacters)) - - XCTAssertEqual(Data([1, 2, 3, 4, 5, 6]), Data(base64Encoded: " AQIDBAUG", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5, 6]), Data(base64Encoded: "A QIDBAUG", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5, 6]), Data(base64Encoded: "AQ IDBAUG", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5, 6]), Data(base64Encoded: "AQI DBAUG", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5, 6]), Data(base64Encoded: "AQID BAUG", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5, 6]), Data(base64Encoded: "AQIDB AUG", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5, 6]), Data(base64Encoded: "AQIDBA UG", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5, 6]), Data(base64Encoded: "AQIDBAU G", options: .ignoreUnknownCharacters)) - XCTAssertEqual(Data([1, 2, 3, 4, 5, 6]), Data(base64Encoded: "AQIDBAUG ", options: .ignoreUnknownCharacters)) - } - - func test_base64Decode_test1MBDataGoing0to255OverAndOver() { - let oneMBTestData = createTestData(count: 1000 * 1024) - func createTestData(count: Int) -> Data { - var data = Data(count: count) - for index in data.indices { - data[index] = UInt8(index % Int(UInt8.max)) - } - return data - } - - let base64DataString = oneMBTestData.base64EncodedString(options: .lineLength64Characters) - XCTAssertEqual(oneMBTestData, Data(base64Encoded: base64DataString, options: .ignoreUnknownCharacters)) - } - - func test_base64Data_small() { - let data = Data("Hello World".utf8) - let base64 = data.base64EncodedString() - XCTAssertEqual("SGVsbG8gV29ybGQ=", base64, "trivial base64 conversion should work") - } - - func test_base64Data_bad() { - XCTAssertNil(Data(base64Encoded: "signature-not-base64-encoded")) - } - - func test_base64Data_medium() { - let data = Data("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut at tincidunt arcu. Suspendisse nec sodales erat, sit amet imperdiet ipsum. Etiam sed ornare felis. Nunc mauris turpis, bibendum non lectus quis, malesuada placerat turpis. Nam adipiscing non massa et semper. Nulla convallis semper bibendum. Aliquam dictum nulla cursus mi ultricies, at tincidunt mi sagittis. Nulla faucibus at dui quis sodales. Morbi rutrum, dui id ultrices venenatis, arcu urna egestas felis, vel suscipit mauris arcu quis risus. Nunc venenatis ligula at orci tristique, et mattis purus pulvinar. Etiam ultricies est odio. Nunc eleifend malesuada justo, nec euismod sem ultrices quis. Etiam nec nibh sit amet lorem faucibus dapibus quis nec leo. Praesent sit amet mauris vel lacus hendrerit porta mollis consectetur mi. Donec eget tortor dui. Morbi imperdiet, arcu sit amet elementum interdum, quam nisl tempor quam, vitae feugiat augue purus sed lacus. In ac urna adipiscing purus venenatis volutpat vel et metus. Nullam nec auctor quam. Phasellus porttitor felis ac nibh gravida suscipit tempus at ante. Nunc pellentesque iaculis sapien a mattis. Aenean eleifend dolor non nunc laoreet, non dictum massa aliquam. Aenean quis turpis augue. Praesent augue lectus, mollis nec elementum eu, dignissim at velit. Ut congue neque id ullamcorper pellentesque. Maecenas euismod in elit eu vehicula. Nullam tristique dui nulla, nec convallis metus suscipit eget. Cras semper augue nec cursus blandit. Nulla rhoncus et odio quis blandit. Praesent lobortis dignissim velit ut pulvinar. Duis interdum quam adipiscing dolor semper semper. Nunc bibendum convallis dui, eget mollis magna hendrerit et. Morbi facilisis, augue eu fringilla convallis, mauris est cursus dolor, eu posuere odio nunc quis orci. Ut eu justo sem. Phasellus ut erat rhoncus, faucibus arcu vitae, vulputate erat. Aliquam nec magna viverra, interdum est vitae, rhoncus sapien. Duis tincidunt tempor ipsum ut dapibus. Nullam commodo varius metus, sed sollicitudin eros. Etiam nec odio et dui tempor blandit posuere.".utf8) - let base64 = data.base64EncodedString() - XCTAssertEqual("TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gVXQgYXQgdGluY2lkdW50IGFyY3UuIFN1c3BlbmRpc3NlIG5lYyBzb2RhbGVzIGVyYXQsIHNpdCBhbWV0IGltcGVyZGlldCBpcHN1bS4gRXRpYW0gc2VkIG9ybmFyZSBmZWxpcy4gTnVuYyBtYXVyaXMgdHVycGlzLCBiaWJlbmR1bSBub24gbGVjdHVzIHF1aXMsIG1hbGVzdWFkYSBwbGFjZXJhdCB0dXJwaXMuIE5hbSBhZGlwaXNjaW5nIG5vbiBtYXNzYSBldCBzZW1wZXIuIE51bGxhIGNvbnZhbGxpcyBzZW1wZXIgYmliZW5kdW0uIEFsaXF1YW0gZGljdHVtIG51bGxhIGN1cnN1cyBtaSB1bHRyaWNpZXMsIGF0IHRpbmNpZHVudCBtaSBzYWdpdHRpcy4gTnVsbGEgZmF1Y2lidXMgYXQgZHVpIHF1aXMgc29kYWxlcy4gTW9yYmkgcnV0cnVtLCBkdWkgaWQgdWx0cmljZXMgdmVuZW5hdGlzLCBhcmN1IHVybmEgZWdlc3RhcyBmZWxpcywgdmVsIHN1c2NpcGl0IG1hdXJpcyBhcmN1IHF1aXMgcmlzdXMuIE51bmMgdmVuZW5hdGlzIGxpZ3VsYSBhdCBvcmNpIHRyaXN0aXF1ZSwgZXQgbWF0dGlzIHB1cnVzIHB1bHZpbmFyLiBFdGlhbSB1bHRyaWNpZXMgZXN0IG9kaW8uIE51bmMgZWxlaWZlbmQgbWFsZXN1YWRhIGp1c3RvLCBuZWMgZXVpc21vZCBzZW0gdWx0cmljZXMgcXVpcy4gRXRpYW0gbmVjIG5pYmggc2l0IGFtZXQgbG9yZW0gZmF1Y2lidXMgZGFwaWJ1cyBxdWlzIG5lYyBsZW8uIFByYWVzZW50IHNpdCBhbWV0IG1hdXJpcyB2ZWwgbGFjdXMgaGVuZHJlcml0IHBvcnRhIG1vbGxpcyBjb25zZWN0ZXR1ciBtaS4gRG9uZWMgZWdldCB0b3J0b3IgZHVpLiBNb3JiaSBpbXBlcmRpZXQsIGFyY3Ugc2l0IGFtZXQgZWxlbWVudHVtIGludGVyZHVtLCBxdWFtIG5pc2wgdGVtcG9yIHF1YW0sIHZpdGFlIGZldWdpYXQgYXVndWUgcHVydXMgc2VkIGxhY3VzLiBJbiBhYyB1cm5hIGFkaXBpc2NpbmcgcHVydXMgdmVuZW5hdGlzIHZvbHV0cGF0IHZlbCBldCBtZXR1cy4gTnVsbGFtIG5lYyBhdWN0b3IgcXVhbS4gUGhhc2VsbHVzIHBvcnR0aXRvciBmZWxpcyBhYyBuaWJoIGdyYXZpZGEgc3VzY2lwaXQgdGVtcHVzIGF0IGFudGUuIE51bmMgcGVsbGVudGVzcXVlIGlhY3VsaXMgc2FwaWVuIGEgbWF0dGlzLiBBZW5lYW4gZWxlaWZlbmQgZG9sb3Igbm9uIG51bmMgbGFvcmVldCwgbm9uIGRpY3R1bSBtYXNzYSBhbGlxdWFtLiBBZW5lYW4gcXVpcyB0dXJwaXMgYXVndWUuIFByYWVzZW50IGF1Z3VlIGxlY3R1cywgbW9sbGlzIG5lYyBlbGVtZW50dW0gZXUsIGRpZ25pc3NpbSBhdCB2ZWxpdC4gVXQgY29uZ3VlIG5lcXVlIGlkIHVsbGFtY29ycGVyIHBlbGxlbnRlc3F1ZS4gTWFlY2VuYXMgZXVpc21vZCBpbiBlbGl0IGV1IHZlaGljdWxhLiBOdWxsYW0gdHJpc3RpcXVlIGR1aSBudWxsYSwgbmVjIGNvbnZhbGxpcyBtZXR1cyBzdXNjaXBpdCBlZ2V0LiBDcmFzIHNlbXBlciBhdWd1ZSBuZWMgY3Vyc3VzIGJsYW5kaXQuIE51bGxhIHJob25jdXMgZXQgb2RpbyBxdWlzIGJsYW5kaXQuIFByYWVzZW50IGxvYm9ydGlzIGRpZ25pc3NpbSB2ZWxpdCB1dCBwdWx2aW5hci4gRHVpcyBpbnRlcmR1bSBxdWFtIGFkaXBpc2NpbmcgZG9sb3Igc2VtcGVyIHNlbXBlci4gTnVuYyBiaWJlbmR1bSBjb252YWxsaXMgZHVpLCBlZ2V0IG1vbGxpcyBtYWduYSBoZW5kcmVyaXQgZXQuIE1vcmJpIGZhY2lsaXNpcywgYXVndWUgZXUgZnJpbmdpbGxhIGNvbnZhbGxpcywgbWF1cmlzIGVzdCBjdXJzdXMgZG9sb3IsIGV1IHBvc3VlcmUgb2RpbyBudW5jIHF1aXMgb3JjaS4gVXQgZXUganVzdG8gc2VtLiBQaGFzZWxsdXMgdXQgZXJhdCByaG9uY3VzLCBmYXVjaWJ1cyBhcmN1IHZpdGFlLCB2dWxwdXRhdGUgZXJhdC4gQWxpcXVhbSBuZWMgbWFnbmEgdml2ZXJyYSwgaW50ZXJkdW0gZXN0IHZpdGFlLCByaG9uY3VzIHNhcGllbi4gRHVpcyB0aW5jaWR1bnQgdGVtcG9yIGlwc3VtIHV0IGRhcGlidXMuIE51bGxhbSBjb21tb2RvIHZhcml1cyBtZXR1cywgc2VkIHNvbGxpY2l0dWRpbiBlcm9zLiBFdGlhbSBuZWMgb2RpbyBldCBkdWkgdGVtcG9yIGJsYW5kaXQgcG9zdWVyZS4=", base64, "medium base64 conversion should work") - } - - func test_AnyHashableContainingData() { - let values: [Data] = [ - Data(base64Encoded: "AAAA")!, - Data(base64Encoded: "AAAB")!, - Data(base64Encoded: "AAAB")!, - ] - let anyHashables = values.map(AnyHashable.init) - expectEqual(Data.self, type(of: anyHashables[0].base)) - expectEqual(Data.self, type(of: anyHashables[1].base)) - expectEqual(Data.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) - } - - func test_replaceSubrange() { - // https://bugs.swift.org/browse/SR-4462 - let data = Data([0x01, 0x02]) - var dataII = Data(base64Encoded: data.base64EncodedString())! - dataII.replaceSubrange(0..<1, with: Data()) - XCTAssertEqual(dataII[0], 0x02) - } - - func testEOPNOTSUPP() throws { - #if !canImport(Darwin) && !os(Linux) && !os(Android) - throw XCTSkip("POSIXError.Code is not supported on this platform") - #else - // Opening a socket via open(2) on Darwin can result in the EOPNOTSUPP error code - // Validate that this does not crash despite missing a case in POSIXError.Code - let error = CocoaError.errorWithFilePath("/foo/bar", errno: EOPNOTSUPP, reading: true) - XCTAssertEqual(error.filePath, "/foo/bar") - #endif - } -} - -#if FOUNDATION_FRAMEWORK // FIXME: Re-enable tests once range(of:) is implemented -extension DataTests { - func testRange() { - let helloWorld = dataFrom("Hello World") - let goodbye = dataFrom("Goodbye") - let hello = dataFrom("Hello") - - do { - let found = helloWorld.range(of: goodbye) - XCTAssertNil(found) - } - - do { - let found = helloWorld.range(of: goodbye, options: .anchored) - XCTAssertNil(found) - } - - do { - let found = helloWorld.range(of: hello, in: 7...alignment) - - let data: Data = Data(bytesNoCopy: bytes.baseAddress!, count: bytes.count, deallocator: .free) - let copy = data._bridgeToObjectiveC().copy() as! NSData - data.withUnsafeBytes { buffer in - XCTAssertEqual(buffer.baseAddress, copy.bytes) - } - } - - func test_noCopy_uaf_bridge() { - // this can only really be tested (modulo ASAN) via comparison of the pointer address of the storage. - let bytes = UnsafeMutableRawBufferPointer.allocate(byteCount: 1024, alignment: MemoryLayout.alignment) - - let data: Data = Data(bytesNoCopy: bytes.baseAddress!, count: bytes.count, deallocator: .none) - let copy = data._bridgeToObjectiveC().copy() as! NSData - data.withUnsafeBytes { buffer in - XCTAssertNotEqual(buffer.baseAddress, copy.bytes) - } - bytes.deallocate() - } -} -#endif diff --git a/Tests/FoundationEssentialsTests/DateIntervalTests.swift b/Tests/FoundationEssentialsTests/DateIntervalTests.swift deleted file mode 100644 index 95d7773cd..000000000 --- a/Tests/FoundationEssentialsTests/DateIntervalTests.swift +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// RUN: %target-run-simple-swift -// REQUIRES: executable_test -// REQUIRES: objc_interop - -#if canImport(TestSupport) -import TestSupport -#endif - -final class DateIntervalTests : XCTestCase { - - func test_compareDateIntervals() { - // dateWithString("2010-05-17 14:49:47 -0700") - let start = Date(timeIntervalSinceReferenceDate: 295825787.0) - let duration: TimeInterval = 10000000.0 - let testInterval1 = DateInterval(start: start, duration: duration) - let testInterval2 = DateInterval(start: start, duration: duration) - XCTAssertEqual(testInterval1, testInterval2) - XCTAssertEqual(testInterval2, testInterval1) - XCTAssertEqual(testInterval1.compare(testInterval2), ComparisonResult.orderedSame) - - let testInterval3 = DateInterval(start: start, duration: 10000000000.0) - XCTAssertTrue(testInterval1 < testInterval3) - XCTAssertTrue(testInterval3 > testInterval1) - - // dateWithString("2009-05-17 14:49:47 -0700") - let earlierStart = Date(timeIntervalSinceReferenceDate: 264289787.0) - let testInterval4 = DateInterval(start: earlierStart, duration: duration) - - XCTAssertTrue(testInterval4 < testInterval1) - XCTAssertTrue(testInterval1 > testInterval4) - } - - func test_isEqualToDateInterval() { - // dateWithString("2010-05-17 14:49:47 -0700") - let start = Date(timeIntervalSinceReferenceDate: 295825787.0) - let duration = 10000000.0 - let testInterval1 = DateInterval(start: start, duration: duration) - let testInterval2 = DateInterval(start: start, duration: duration) - - XCTAssertEqual(testInterval1, testInterval2) - - let testInterval3 = DateInterval(start: start, duration: 100.0) - XCTAssertNotEqual(testInterval1, testInterval3) - } - - func test_hashing() { - // dateWithString("2019-04-04 17:09:23 -0700") - let start1a = Date(timeIntervalSinceReferenceDate: 576115763.0) - let start1b = Date(timeIntervalSinceReferenceDate: 576115763.0) - let start2a = Date(timeIntervalSinceReferenceDate: start1a.timeIntervalSinceReferenceDate.nextUp) - let start2b = Date(timeIntervalSinceReferenceDate: start1a.timeIntervalSinceReferenceDate.nextUp) - let duration1 = 1800.0 - let duration2 = duration1.nextUp - let intervals: [[DateInterval]] = [ - [ - DateInterval(start: start1a, duration: duration1), - DateInterval(start: start1b, duration: duration1), - ], - [ - DateInterval(start: start1a, duration: duration2), - DateInterval(start: start1b, duration: duration2), - ], - [ - DateInterval(start: start2a, duration: duration1), - DateInterval(start: start2b, duration: duration1), - ], - [ - DateInterval(start: start2a, duration: duration2), - DateInterval(start: start2b, duration: duration2), - ], - ] - checkHashableGroups(intervals) - } - - func test_checkIntersection() { - // dateWithString("2010-05-17 14:49:47 -0700") - let start1 = Date(timeIntervalSinceReferenceDate: 295825787.0) - // dateWithString("2010-08-17 14:49:47 -0700") - let end1 = Date(timeIntervalSinceReferenceDate: 303774587.0) - - let testInterval1 = DateInterval(start: start1, end: end1) - - // dateWithString("2010-02-17 14:49:47 -0700") - let start2 = Date(timeIntervalSinceReferenceDate: 288136187.0) - // dateWithString("2010-07-17 14:49:47 -0700") - let end2 = Date(timeIntervalSinceReferenceDate: 301096187.0) - - let testInterval2 = DateInterval(start: start2, end: end2) - - XCTAssertTrue(testInterval1.intersects(testInterval2)) - - // dateWithString("2010-10-17 14:49:47 -0700") - let start3 = Date(timeIntervalSinceReferenceDate: 309044987.0) - // dateWithString("2010-11-17 14:49:47 -0700") - let end3 = Date(timeIntervalSinceReferenceDate: 311723387.0) - - let testInterval3 = DateInterval(start: start3, end: end3) - - XCTAssertFalse(testInterval1.intersects(testInterval3)) - } - - func test_validIntersections() { - // dateWithString("2010-05-17 14:49:47 -0700") - let start1 = Date(timeIntervalSinceReferenceDate: 295825787.0) - // dateWithString("2010-08-17 14:49:47 -0700") - let end1 = Date(timeIntervalSinceReferenceDate: 303774587.0) - - let testInterval1 = DateInterval(start: start1, end: end1) - - // dateWithString("2010-02-17 14:49:47 -0700") - let start2 = Date(timeIntervalSinceReferenceDate: 288136187.0) - // dateWithString("2010-07-17 14:49:47 -0700") - let end2 = Date(timeIntervalSinceReferenceDate: 301096187.0) - - let testInterval2 = DateInterval(start: start2, end: end2) - - // dateWithString("2010-05-17 14:49:47 -0700") - let start3 = Date(timeIntervalSinceReferenceDate: 295825787.0) - // dateWithString("2010-07-17 14:49:47 -0700") - let end3 = Date(timeIntervalSinceReferenceDate: 301096187.0) - - let testInterval3 = DateInterval(start: start3, end: end3) - - let intersection1 = testInterval2.intersection(with: testInterval1) - XCTAssertNotNil(intersection1) - XCTAssertEqual(testInterval3, intersection1) - - let intersection2 = testInterval1.intersection(with: testInterval2) - XCTAssertNotNil(intersection2) - XCTAssertEqual(intersection1, intersection2) - } - - func test_containsDate() { - // dateWithString("2010-05-17 14:49:47 -0700") - let start = Date(timeIntervalSinceReferenceDate: 295825787.0) - let duration = 10000000.0 - - let testInterval = DateInterval(start: start, duration: duration) - // dateWithString("2010-05-17 20:49:47 -0700") - let containedDate = Date(timeIntervalSinceReferenceDate: 295847387.0) - - XCTAssertTrue(testInterval.contains(containedDate)) - - // dateWithString("2009-05-17 14:49:47 -0700") - let earlierStart = Date(timeIntervalSinceReferenceDate: 264289787.0) - XCTAssertFalse(testInterval.contains(earlierStart)) - } - - func test_AnyHashableContainingDateInterval() { - // dateWithString("2010-05-17 14:49:47 -0700") - let start = Date(timeIntervalSinceReferenceDate: 295825787.0) - let duration = 10000000.0 - let values: [DateInterval] = [ - DateInterval(start: start, duration: duration), - DateInterval(start: start, duration: duration / 2), - DateInterval(start: start, duration: duration / 2), - ] - let anyHashables = values.map(AnyHashable.init) - expectEqual(DateInterval.self, type(of: anyHashables[0].base)) - expectEqual(DateInterval.self, type(of: anyHashables[1].base)) - expectEqual(DateInterval.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) - } -} - -// MARK: - Bridging Tests -#if FOUNDATION_FRAMEWORK -extension DateIntervalTests { - func test_AnyHashableCreatedFromNSDateInterval() { - // dateWithString("2010-05-17 14:49:47 -0700") - let start = Date(timeIntervalSinceReferenceDate: 295825787.0) - let duration = 10000000.0 - let values: [NSDateInterval] = [ - NSDateInterval(start: start, duration: duration), - NSDateInterval(start: start, duration: duration / 2), - NSDateInterval(start: start, duration: duration / 2), - ] - let anyHashables = values.map(AnyHashable.init) - expectEqual(DateInterval.self, type(of: anyHashables[0].base)) - expectEqual(DateInterval.self, type(of: anyHashables[1].base)) - expectEqual(DateInterval.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) - } -} -#endif diff --git a/Tests/FoundationEssentialsTests/DateTests.swift b/Tests/FoundationEssentialsTests/DateTests.swift deleted file mode 100644 index 9558f580f..000000000 --- a/Tests/FoundationEssentialsTests/DateTests.swift +++ /dev/null @@ -1,183 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(FoundationEssentials) -@testable import FoundationEssentials -#endif - -final class DateTests : XCTestCase { - - func testDateComparison() { - let d1 = Date() - let d2 = d1 + 1 - - XCTAssertGreaterThan(d2, d1) - XCTAssertLessThan(d1, d2) - - let d3 = Date(timeIntervalSince1970: 12345) - let d4 = Date(timeIntervalSince1970: 12345) - - XCTAssertEqual(d3, d4) - XCTAssertLessThanOrEqual(d3, d4) - XCTAssertGreaterThanOrEqual(d4, d3) - } - - func testDateMutation() { - let d0 = Date() - var d1 = Date() - d1 = d1 + 1.0 - let d2 = Date(timeIntervalSinceNow: 10) - - XCTAssertGreaterThan(d2, d1) - XCTAssertNotEqual(d1, d0) - - let d3 = d1 - d1 += 10 - - XCTAssertGreaterThan(d1, d3) - } - - func testDistantPast() { - let distantPast = Date.distantPast - let currentDate = Date() - - XCTAssertLessThan(distantPast, currentDate) - XCTAssertGreaterThan(currentDate, distantPast) - XCTAssertLessThan(distantPast.timeIntervalSince(currentDate), - 3600.0 * 24 * 365 * 100) /* ~1 century in seconds */ - } - - func testDistantFuture() { - let distantFuture = Date.distantFuture - let currentDate = Date() - - XCTAssertLessThan(currentDate, distantFuture) - XCTAssertGreaterThan(distantFuture, currentDate) - XCTAssertGreaterThan(distantFuture.timeIntervalSince(currentDate), - 3600.0 * 24 * 365 * 100) /* ~1 century in seconds */ - } - - func test_now() { - let date1 : Date = .now - let date2 : Date = .now - - XCTAssertLessThanOrEqual(date1, date2) - } - - func testDescriptionReferenceDate() { - let date = Date(timeIntervalSinceReferenceDate: TimeInterval(0)) - - XCTAssertEqual("2001-01-01 00:00:00 +0000", date.description) - } - - func testDescription1970() { - let date = Date(timeIntervalSince1970: TimeInterval(0)) - - XCTAssertEqual("1970-01-01 00:00:00 +0000", date.description) - } - - func testDescriptionDistantPast() throws { -#if os(Windows) - throw XCTSkip("ucrt does not support distant past") -#else -#if FOUNDATION_FRAMEWORK - XCTAssertEqual("0001-01-01 00:00:00 +0000", Date.distantPast.description) -#else - XCTAssertEqual("0000-12-30 00:00:00 +0000", Date.distantPast.description) -#endif -#endif - } - - func testDescriptionDistantFuture() throws { -#if os(Windows) - throw XCTSkip("ucrt does not support distant future") -#else - XCTAssertEqual("4001-01-01 00:00:00 +0000", Date.distantFuture.description) -#endif - } - - func testDescriptionBeyondDistantPast() { - let date = Date.distantPast.addingTimeInterval(TimeInterval(-1)) -#if FOUNDATION_FRAMEWORK - XCTAssertEqual("0000-12-31 23:59:59 +0000", date.description) -#else - XCTAssertEqual("", date.description) -#endif - } - - func testDescriptionBeyondDistantFuture() { - let date = Date.distantFuture.addingTimeInterval(TimeInterval(1)) -#if FOUNDATION_FRAMEWORK - XCTAssertEqual("4001-01-01 00:00:01 +0000", date.description) -#else - XCTAssertEqual("", date.description) -#endif - } - - func testNowIsAfterReasonableDate() { - let date = Date.now - XCTAssert(date.timeIntervalSinceReferenceDate > 742100000.0) // "2024-07-08T02:53:20Z" - XCTAssert(date.timeIntervalSinceReferenceDate < 3896300000.0) // "2124-06-21T01:33:20Z" - } -} - -// MARK: - Bridging -#if FOUNDATION_FRAMEWORK -final class DateBridgingTests : XCTestCase { - func testCast() { - let d0 = NSDate() - let d1 = d0 as Date - XCTAssertEqual(d0.timeIntervalSinceReferenceDate, d1.timeIntervalSinceReferenceDate) - } - - func test_AnyHashableCreatedFromNSDate() { - let values: [NSDate] = [ - NSDate(timeIntervalSince1970: 1000000000), - NSDate(timeIntervalSince1970: 1000000001), - NSDate(timeIntervalSince1970: 1000000001), - ] - let anyHashables = values.map(AnyHashable.init) - expectEqual(Date.self, type(of: anyHashables[0].base)) - expectEqual(Date.self, type(of: anyHashables[1].base)) - expectEqual(Date.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) - } - - func test_AnyHashableCreatedFromNSDateComponents() { - func makeNSDateComponents(year: Int) -> NSDateComponents { - let result = NSDateComponents() - result.year = year - return result - } - let values: [NSDateComponents] = [ - makeNSDateComponents(year: 2016), - makeNSDateComponents(year: 1995), - makeNSDateComponents(year: 1995), - ] - let anyHashables = values.map(AnyHashable.init) - expectEqual(DateComponents.self, type(of: anyHashables[0].base)) - expectEqual(DateComponents.self, type(of: anyHashables[1].base)) - expectEqual(DateComponents.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) - } - - func test_dateComponents_unconditionallyBridgeFromObjectiveC() { - XCTAssertEqual(DateComponents(), DateComponents._unconditionallyBridgeFromObjectiveC(nil)) - } -} -#endif // FOUNDATION_FRAMEWORK diff --git a/Tests/FoundationEssentialsTests/DecimalTests.swift b/Tests/FoundationEssentialsTests/DecimalTests.swift deleted file mode 100644 index 6f7d08ff3..000000000 --- a/Tests/FoundationEssentialsTests/DecimalTests.swift +++ /dev/null @@ -1,1352 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif // canImport(TestSupport) - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#else -@_spi(SwiftCorelibsFoundation) -@testable import FoundationEssentials -#endif - -final class DecimalTests : XCTestCase { -#if !FOUNDATION_FRAMEWORK // These tests tests the stub implementations - func assertMantissaEquals(lhs: Decimal, rhs: Decimal.Mantissa) { - XCTAssertEqual(lhs[0], rhs.0, "Mantissa.0 does not equal: \(lhs[0]) vs \(rhs.0)") - XCTAssertEqual(lhs[1], rhs.1, "Mantissa.1 does not equal: \(lhs[1]) vs \(rhs.1)") - XCTAssertEqual(lhs[2], rhs.2, "Mantissa.2 does not equal: \(lhs[2]) vs \(rhs.2)") - XCTAssertEqual(lhs[3], rhs.3, "Mantissa.3 does not equal: \(lhs[3]) vs \(rhs.3)") - XCTAssertEqual(lhs[4], rhs.4, "Mantissa.4 does not equal: \(lhs[4]) vs \(rhs.4)") - XCTAssertEqual(lhs[5], rhs.5, "Mantissa.5 does not equal: \(lhs[5]) vs \(rhs.5)") - XCTAssertEqual(lhs[6], rhs.6, "Mantissa.6 does not equal: \(lhs[6]) vs \(rhs.6)") - XCTAssertEqual(lhs[7], rhs.7, "Mantissa.7 does not equal: \(lhs[7]) vs \(rhs.7)") - } - - func testDecimalRoundtripFuzzing() { - let iterations = 100 - for _ in 0 ..< iterations { - // Exponent is only 8 bits long - let exponent: CInt = CInt(Int8.random(in: Int8.min ..< Int8.max)) - // Length is only 4 bits long - var length: CUnsignedInt = .random(in: 0 ..< 0xF) - let isNegative: CUnsignedInt = .random(in: 0 ..< 1) - let isCompact: CUnsignedInt = .random(in: 0 ..< 1) - // Reserved is 18 bits long - let reserved: CUnsignedInt = .random(in: 0 ..< 0x3FFFF) - let mantissa: Decimal.Mantissa = ( - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max) - ) - - var decimal = Decimal( - _exponent: exponent, - _length: length, - _isNegative: isNegative, - _isCompact: isCompact, - _reserved: reserved, - _mantissa: mantissa - ) - - XCTAssertEqual(decimal._exponent, exponent) - XCTAssertEqual(decimal._length, length) - XCTAssertEqual(decimal._isNegative, isNegative) - XCTAssertEqual(decimal._isCompact, isCompact) - XCTAssertEqual(decimal._reserved, reserved) - assertMantissaEquals( - lhs: decimal, - rhs: mantissa - ) - - // Update invidividual values - length = .random(in: 0 ..< 0xF) - decimal._length = length - XCTAssertEqual(decimal._length, length) - } - } - -#endif - - func testAbusiveCompact() { - var decimal = Decimal() - decimal._exponent = 5 - decimal._length = 5 - decimal.compact() - XCTAssertEqual(Decimal.zero, decimal); - } - - func test_Description() { - XCTAssertEqual("0", Decimal().description) - XCTAssertEqual("0", Decimal(0).description) - XCTAssertEqual("10", Decimal(_exponent: 1, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1, 0, 0, 0, 0, 0, 0, 0)).description) - XCTAssertEqual("10", Decimal(10).description) - XCTAssertEqual("123.458", Decimal(_exponent: -3, _length: 2, _isNegative: 0, _isCompact:1, _reserved: 0, _mantissa: (57922, 1, 0, 0, 0, 0, 0, 0)).description) - XCTAssertEqual("123.458", Decimal(123.458).description) - XCTAssertEqual("123", Decimal(UInt8(123)).description) - XCTAssertEqual("45", Decimal(Int8(45)).description) - XCTAssertEqual("3.14159265358979323846264338327950288419", Decimal.pi.description) - XCTAssertEqual("-30000000000", Decimal(sign: .minus, exponent: 10, significand: Decimal(3)).description) - XCTAssertEqual("300000", Decimal(sign: .plus, exponent: 5, significand: Decimal(3)).description) - XCTAssertEqual("5", Decimal(signOf: Decimal(3), magnitudeOf: Decimal(5)).description) - XCTAssertEqual("-5", Decimal(signOf: Decimal(-3), magnitudeOf: Decimal(5)).description) - XCTAssertEqual("5", Decimal(signOf: Decimal(3), magnitudeOf: Decimal(-5)).description) - XCTAssertEqual("-5", Decimal(signOf: Decimal(-3), magnitudeOf: Decimal(-5)).description) - } - - func test_DescriptionWithLocale() { - let decimal = Decimal(string: "-123456.789")! - XCTAssertEqual(decimal._toString(withDecimalSeparator: "."), "-123456.789") - let en = decimal._toString(withDecimalSeparator: Locale(identifier: "en_GB").decimalSeparator!) - XCTAssertEqual(en, "-123456.789") - let fr = decimal._toString(withDecimalSeparator: Locale(identifier: "fr_FR").decimalSeparator!) - XCTAssertEqual(fr, "-123456,789") - } - - func test_BasicConstruction() { - let zero = Decimal() - XCTAssertEqual(20, MemoryLayout.size) - XCTAssertEqual(0, zero._exponent) - XCTAssertEqual(0, zero._length) - XCTAssertEqual(0, zero._isNegative) - XCTAssertEqual(0, zero._isCompact) - XCTAssertEqual(0, zero._reserved) - let (m0, m1, m2, m3, m4, m5, m6, m7) = zero._mantissa - XCTAssertEqual(0, m0) - XCTAssertEqual(0, m1) - XCTAssertEqual(0, m2) - XCTAssertEqual(0, m3) - XCTAssertEqual(0, m4) - XCTAssertEqual(0, m5) - XCTAssertEqual(0, m6) - XCTAssertEqual(0, m7) - XCTAssertEqual(8, Decimal.maxSize) - XCTAssertEqual(32767, CShort.max) - XCTAssertFalse(zero.isNormal) - XCTAssertTrue(zero.isFinite) - XCTAssertTrue(zero.isZero) - XCTAssertFalse(zero.isSubnormal) - XCTAssertFalse(zero.isInfinite) - XCTAssertFalse(zero.isNaN) - XCTAssertFalse(zero.isSignaling) - - let d1 = Decimal(1234567890123456789 as UInt64) - XCTAssertEqual(d1._exponent, 0) - XCTAssertEqual(d1._length, 4) - } - - func test_ExplicitConstruction() { - var explicit = Decimal( - _exponent: 0x17f, - _length: 0xff, - _isNegative: 3, - _isCompact: 4, - _reserved: UInt32(1<<18 + 1<<17 + 1), - _mantissa: (6, 7, 8, 9, 10, 11, 12, 13) - ) - XCTAssertEqual(0x7f, explicit._exponent) - XCTAssertEqual(0x7f, explicit.exponent) - XCTAssertEqual(0x0f, explicit._length) - XCTAssertEqual(1, explicit._isNegative) - XCTAssertEqual(FloatingPointSign.minus, explicit.sign) - XCTAssertTrue(explicit.isSignMinus) - XCTAssertEqual(0, explicit._isCompact) - XCTAssertEqual(UInt32(1<<17 + 1), explicit._reserved) - let (m0, m1, m2, m3, m4, m5, m6, m7) = explicit._mantissa - XCTAssertEqual(6, m0) - XCTAssertEqual(7, m1) - XCTAssertEqual(8, m2) - XCTAssertEqual(9, m3) - XCTAssertEqual(10, m4) - XCTAssertEqual(11, m5) - XCTAssertEqual(12, m6) - XCTAssertEqual(13, m7) - explicit._isCompact = 5 - explicit._isNegative = 6 - XCTAssertEqual(0, explicit._isNegative) - XCTAssertEqual(1, explicit._isCompact) - XCTAssertEqual(FloatingPointSign.plus, explicit.sign) - XCTAssertFalse(explicit.isSignMinus) - XCTAssertTrue(explicit.isNormal) - - let significand = explicit.significand - XCTAssertEqual(0, significand._exponent) - XCTAssertEqual(0, significand.exponent) - XCTAssertEqual(0x0f, significand._length) - XCTAssertEqual(0, significand._isNegative) - XCTAssertEqual(1, significand._isCompact) - XCTAssertEqual(0, significand._reserved) - let (sm0, sm1, sm2, sm3, sm4, sm5, sm6, sm7) = significand._mantissa - XCTAssertEqual(6, sm0) - XCTAssertEqual(7, sm1) - XCTAssertEqual(8, sm2) - XCTAssertEqual(9, sm3) - XCTAssertEqual(10, sm4) - XCTAssertEqual(11, sm5) - XCTAssertEqual(12, sm6) - XCTAssertEqual(13, sm7) - } - - func test_ScanDecimal() throws { - let testCases = [ - // expected, value - ( 123.456e78, "123.456e78", "123456000000000000000000000000000000000000000000000000000000000000000000000000000" ), - ( -123.456e78, "-123.456e78", "-123456000000000000000000000000000000000000000000000000000000000000000000000000000" ), - ( 123.456, " 123.456 ", "123.456" ), - ( 3.14159, " 3.14159e0", "3.14159" ), - ( 3.14159, " 3.14159e-0", "3.14159" ), - ( 0.314159, " 3.14159e-1", "0.314159" ), - ( 3.14159, " 3.14159e+0", "3.14159"), - ( 31.4159, " 3.14159e+1", "31.4159"), - ( 12.34, " 01234e-02", "12.34"), - ] - for testCase in testCases { - let (expected, string, _) = testCase - let decimal = Decimal(string:string)! - let aboutOne = Decimal(expected) / decimal - let approximatelyRight = aboutOne >= Decimal(0.99999) && aboutOne <= Decimal(1.00001) - XCTAssertTrue(approximatelyRight, "\(expected) ~= \(decimal) : \(aboutOne) \(aboutOne >= Decimal(0.99999)) \(aboutOne <= Decimal(1.00001))" ) - } - guard let answer = Decimal(string:"12345679012345679012345679012345679012.3") else { - XCTFail("Unable to parse Decimal(string:'12345679012345679012345679012345679012.3')") - return - } - guard let ones = Decimal(string:"111111111111111111111111111111111111111") else { - XCTFail("Unable to parse Decimal(string:'111111111111111111111111111111111111111')") - return - } - let num = ones / Decimal(9) - XCTAssertEqual(answer,num,"\(ones) / 9 = \(answer) \(num)") - - // Exponent overflow, returns nil - XCTAssertNil(Decimal(string: "1e200")) - XCTAssertNil(Decimal(string: "1e-200")) - XCTAssertNil(Decimal(string: "1e300")) - XCTAssertNil(Decimal(string: "1" + String(repeating: "0", count: 170))) - XCTAssertNil(Decimal(string: "0." + String(repeating: "0", count: 170) + "1")) - XCTAssertNil(Decimal(string: "0e200")) - - // Parsing zero in different forms - let zero1 = try XCTUnwrap(Decimal(string: "000.000e123")) - XCTAssertTrue(zero1.isZero) - XCTAssertEqual(zero1._isNegative, 0) - XCTAssertEqual(zero1._length, 0) - XCTAssertEqual(zero1.description, "0") - - let zero2 = try XCTUnwrap(Decimal(string: "+000.000e-123")) - XCTAssertTrue(zero2.isZero) - XCTAssertEqual(zero2._isNegative, 0) - XCTAssertEqual(zero2._length, 0) - XCTAssertEqual(zero2.description, "0") - - let zero3 = try XCTUnwrap(Decimal(string: "-0.0e1")) - XCTAssertTrue(zero3.isZero) - XCTAssertEqual(zero3._isNegative, 0) - XCTAssertEqual(zero3._length, 0) - XCTAssertEqual(zero3.description, "0") - - // Bin compat: invalid strings starting with E should be parsed as 0 - var zeroE = try XCTUnwrap(Decimal(string: "en")) - XCTAssertTrue(zeroE.isZero) - zeroE = try XCTUnwrap(Decimal(string: "e")) - XCTAssertTrue(zeroE.isZero) - // Partitally valid strings ending with e shold be parsed - let notZero = try XCTUnwrap(Decimal(string: "123e")) - XCTAssertEqual(notZero, Decimal(123)) - } - - func test_stringWithLocale() { - - let en_US = Locale(identifier: "en_US") - let fr_FR = Locale(identifier: "fr_FR") - - XCTAssertEqual(Decimal(string: "1,234.56")! * 1000, Decimal(1000)) - XCTAssertEqual(Decimal(string: "1,234.56", locale: en_US)! * 1000, Decimal(1000)) - XCTAssertEqual(Decimal(string: "1,234.56", locale: fr_FR)! * 1000, Decimal(1234)) - XCTAssertEqual(Decimal(string: "1.234,56", locale: en_US)! * 1000, Decimal(1234)) - XCTAssertEqual(Decimal(string: "1.234,56", locale: fr_FR)! * 1000, Decimal(1000)) - - XCTAssertEqual(Decimal(string: "-1,234.56")! * 1000, Decimal(-1000)) - XCTAssertEqual(Decimal(string: "+1,234.56")! * 1000, Decimal(1000)) - XCTAssertEqual(Decimal(string: "+1234.56e3"), Decimal(1234560)) - XCTAssertEqual(Decimal(string: "+1234.56E3"), Decimal(1234560)) - XCTAssertEqual(Decimal(string: "+123456000E-3"), Decimal(123456)) - - XCTAssertNil(Decimal(string: "")) - XCTAssertNil(Decimal(string: "x")) - XCTAssertEqual(Decimal(string: "-x"), Decimal.zero) - XCTAssertEqual(Decimal(string: "+x"), Decimal.zero) - XCTAssertEqual(Decimal(string: "-"), Decimal.zero) - XCTAssertEqual(Decimal(string: "+"), Decimal.zero) - XCTAssertEqual(Decimal(string: "-."), Decimal.zero) - XCTAssertEqual(Decimal(string: "+."), Decimal.zero) - - XCTAssertEqual(Decimal(string: "-0"), Decimal.zero) - XCTAssertEqual(Decimal(string: "+0"), Decimal.zero) - XCTAssertEqual(Decimal(string: "-0."), Decimal.zero) - XCTAssertEqual(Decimal(string: "+0."), Decimal.zero) - XCTAssertEqual(Decimal(string: "e1"), Decimal.zero) - XCTAssertEqual(Decimal(string: "e-5"), Decimal.zero) - XCTAssertEqual(Decimal(string: ".3e1"), Decimal(3)) - - XCTAssertEqual(Decimal(string: "."), Decimal.zero) - XCTAssertEqual(Decimal(string: ".", locale: en_US), Decimal.zero) - XCTAssertNil(Decimal(string: ".", locale: fr_FR)) - - XCTAssertNil(Decimal(string: ",")) - XCTAssertEqual(Decimal(string: ",", locale: fr_FR), Decimal.zero) - XCTAssertNil(Decimal(string: ",", locale: en_US)) - - let s1 = "1234.5678" - XCTAssertEqual(Decimal(string: s1, locale: en_US)?.description, s1) - XCTAssertEqual(Decimal(string: s1, locale: fr_FR)?.description, "1234") - - let s2 = "1234,5678" - XCTAssertEqual(Decimal(string: s2, locale: en_US)?.description, "1234") - XCTAssertEqual(Decimal(string: s2, locale: fr_FR)?.description, s1) - } - - func testStringPartialMatch() { - // This tests makes sure Decimal still has the - // same behavior that it only requires the beginning - // of the string to be valid number - let decimal = Decimal(string: "3.14notanumber") - XCTAssertNotNil(decimal) - XCTAssertEqual(decimal!.description, "3.14") - } - - func testStringNoMatch() { - // This test makes sure Decimal returns nil - // if the does not start with a number - var notDecimal = Decimal(string: "A Flamingo's head has to be upside down when it eats.") - XCTAssertNil(notDecimal) - // Same if the number does not appear at the beginning - notDecimal = Decimal(string: "Jump 22 Street") - XCTAssertNil(notDecimal) - } - - func testNormalize() throws { - var one = Decimal(1) - var ten = Decimal(-10) - var lossPrecision = try Decimal._normalize(a: &one, b: &ten, roundingMode: .plain) - XCTAssertFalse(lossPrecision) - XCTAssertEqual(Decimal(1), one) - XCTAssertEqual(Decimal(-10), ten) - XCTAssertEqual(1, one._length) - XCTAssertEqual(1, ten._length) - one = Decimal(1) - ten = Decimal(10) - lossPrecision = try Decimal._normalize(a: &one, b: &ten, roundingMode: .plain) - XCTAssertFalse(lossPrecision) - XCTAssertEqual(Decimal(1), one) - XCTAssertEqual(Decimal(10), ten) - XCTAssertEqual(1, one._length) - XCTAssertEqual(1, ten._length) - - // Normalise with loss of precision - let a = try XCTUnwrap(Decimal(string: "498.7509045")) - let b = try XCTUnwrap(Decimal(string: "8.453441368210501065891847765109162027")) - - var aNormalized = a - var bNormalized = b - - lossPrecision = try Decimal._normalize( - a: &aNormalized, b: &bNormalized, roundingMode: .plain) - XCTAssertTrue(lossPrecision) - - XCTAssertEqual(aNormalized.exponent, -31) - XCTAssertEqual(aNormalized._mantissa.0, 0) - XCTAssertEqual(aNormalized._mantissa.1, 21760) - XCTAssertEqual(aNormalized._mantissa.2, 45355) - XCTAssertEqual(aNormalized._mantissa.3, 11455) - XCTAssertEqual(aNormalized._mantissa.4, 62709) - XCTAssertEqual(aNormalized._mantissa.5, 14050) - XCTAssertEqual(aNormalized._mantissa.6, 62951) - XCTAssertEqual(aNormalized._mantissa.7, 0) - XCTAssertEqual(bNormalized.exponent, -31) - XCTAssertEqual(bNormalized._mantissa.0, 56467) - XCTAssertEqual(bNormalized._mantissa.1, 17616) - XCTAssertEqual(bNormalized._mantissa.2, 59987) - XCTAssertEqual(bNormalized._mantissa.3, 21635) - XCTAssertEqual(bNormalized._mantissa.4, 5988) - XCTAssertEqual(bNormalized._mantissa.5, 63852) - XCTAssertEqual(bNormalized._mantissa.6, 1066) - XCTAssertEqual(bNormalized._length, 7) - XCTAssertEqual(a, aNormalized) - XCTAssertNotEqual(b, bNormalized) // b had a loss Of Precision when normalising - } - - func testAdditionWithNormalization() throws { - let one: Decimal = Decimal(1) - var addend: Decimal = one - // 2 digits - addend._exponent = -1 - var (result, lostPrecision) = try one._add(rhs: addend, roundingMode: .plain) - var expected: Decimal = Decimal() - expected._isNegative = 0 - expected._isCompact = 0 - expected._exponent = -1 - expected._length = 1 - expected._mantissa.0 = 11 - XCTAssertTrue(Decimal._compare(lhs: result, rhs: expected) == .orderedSame) - // 38 digits - addend._exponent = -37 - expected._exponent = -37; - expected._length = 8; - expected._mantissa.0 = 0x0001; - expected._mantissa.1 = 0x0000; - expected._mantissa.2 = 0x36a0; - expected._mantissa.3 = 0x00f4; - expected._mantissa.4 = 0x46d9; - expected._mantissa.5 = 0xd5da; - expected._mantissa.6 = 0xee10; - expected._mantissa.7 = 0x0785; - (result, _) = try one._add(rhs: addend, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: expected, rhs: result) == .orderedSame) - // 39 Digits -- not guaranteed to work - addend._exponent = -38 - (result, lostPrecision) = try one._add(rhs: addend, roundingMode: .plain) - if !lostPrecision { - expected._exponent = -38; - expected._length = 8; - expected._mantissa.0 = 0x0001; - expected._mantissa.1 = 0x0000; - expected._mantissa.2 = 0x2240; - expected._mantissa.3 = 0x098a; - expected._mantissa.4 = 0xc47a; - expected._mantissa.5 = 0x5a86; - expected._mantissa.6 = 0x4ca8; - expected._mantissa.7 = 0x4b3b; - XCTAssertTrue(Decimal._compare(lhs: expected, rhs: result) == .orderedSame) - } else { - XCTAssertTrue(Decimal._compare(lhs: one, rhs: result) == .orderedSame) - } - // 40 Digits -- does NOT work, make sure we round - addend._exponent = -39 - (result, lostPrecision) = try one._add(rhs: addend, roundingMode: .plain) - XCTAssertTrue(lostPrecision) - XCTAssertEqual("1", result.description) - XCTAssertTrue(Decimal._compare(lhs: one, rhs: result) == .orderedSame) - } - - func testSimpleMultiplication() throws { - var multiplicand = Decimal() - multiplicand._isNegative = 0 - multiplicand._isCompact = 0 - multiplicand._length = 1 - multiplicand._exponent = 1 - var multiplier = multiplicand - multiplier._exponent = 2 - - var expected = multiplicand - expected._isNegative = 0 - expected._isCompact = 0 - expected._exponent = 3 - expected._length = 1 - - for i in 1 ..< UInt8.max { - multiplicand._mantissa.0 = UInt16(i) - for j in 1 ..< UInt8.max { - multiplier._mantissa.0 = UInt16(j) - expected._mantissa.0 = UInt16(i) * UInt16(j) - - let result = try multiplicand._multiply( - by: multiplier, roundingMode: .plain - ) - XCTAssertTrue(Decimal._compare(lhs: expected, rhs: result) == .orderedSame) - } - } - } - - func testNegativeAndZeroMultiplication() throws { - let one = Decimal(1) - let zero = Decimal(0) - var negativeOne = one - negativeOne._isNegative = 1 - - // 1 * 1 - var result = try one._multiply(by: one, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: one, rhs: result) == .orderedSame) - // 1 * -1 - result = try one._multiply(by: negativeOne, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: negativeOne, rhs: result) == .orderedSame) - // -1 * 1 - result = try negativeOne._multiply(by: one, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: negativeOne, rhs: result) == .orderedSame) - // -1 * -1 - result = try negativeOne._multiply(by: negativeOne, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: one, rhs: result) == .orderedSame) - // 1 * 0 - result = try one._multiply(by: zero, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: zero, rhs: result) == .orderedSame) - // 0 * 1 - result = try zero._multiply(by: negativeOne, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: zero, rhs: result) == .orderedSame) - } - - func testMultiplicationOverflow() throws { - let multiplicand = Decimal( - _exponent: 0, - _length: 8, - _isNegative: 0, - _isCompact: 0, - _reserved: 0, - _mantissa: (0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff) - ) - var multiplier = Decimal(1) - multiplier._mantissa.0 = 2 - - // This test makes sure the following does NOT throw - // max_mantissa * 2 - _ = try multiplicand._multiply( - by: multiplier, roundingMode: .plain) - // 2 * max_mantissa - _ = try multiplier._multiply( - by: multiplicand, roundingMode: .plain) - - // The following should throw .overlow - multiplier._exponent = 0x7F - do { - // 2e127 * max_mantissa - _ = try multiplicand._multiply( - by: multiplier, roundingMode: .plain) - XCTFail("Expected _CalculationError.overflow to be thrown") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) - } - - do { - // max_mantissa * 2e127 - _ = try multiplier._multiply( - by: multiplicand, roundingMode: .plain) - XCTFail("Expected _CalculationError.overflow to be thrown") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) - } - } - - func testMultiplyByPowerOfTen() throws { - let a = Decimal(1234) - var result = try a._multiplyByPowerOfTen(power: 1, roundingMode: .plain) - XCTAssertEqual(result, Decimal(12340)) - result = try a._multiplyByPowerOfTen(power: 2, roundingMode: .plain) - XCTAssertEqual(result, Decimal(123400)) - result = try a._multiplyByPowerOfTen(power: 0, roundingMode: .plain) - XCTAssertEqual(result, Decimal(1234)) - result = try a._multiplyByPowerOfTen(power: -2, roundingMode: .plain) - XCTAssertEqual(result, Decimal(12.34)) - - // Overflow - do { - _ = try a._multiplyByPowerOfTen(power: 128, roundingMode: .plain) - XCTFail("Expected overflow to have been thrown") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) - } - - // Underflow - do { - _ = try Decimal(12.34)._multiplyByPowerOfTen(power: -128, roundingMode: .plain) - XCTFail("Expected underflow to have been thrown") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .underflow) - } - } - - func testRepeatingDivision() throws { - let repeatingNumerator = Decimal(16) - let repeatingDenominator = Decimal(9) - let repeating = try repeatingNumerator._divide( - by: repeatingDenominator, roundingMode: .plain - ) - let numerator = Decimal(1010) - let result = try numerator._divide( - by: repeating, roundingMode: .plain - ) - var expected = Decimal() - expected._exponent = -35 - expected._length = 8 - expected._isNegative = 0 - expected._isCompact = 1 - expected._reserved = 0 - expected._mantissa.0 = 51946 - expected._mantissa.1 = 3 - expected._mantissa.2 = 15549 - expected._mantissa.3 = 55864 - expected._mantissa.4 = 57984 - expected._mantissa.5 = 55436 - expected._mantissa.6 = 45186 - expected._mantissa.7 = 10941 - XCTAssertTrue(Decimal._compare(lhs: expected, rhs: result) == .orderedSame) - } - -#if _pointerBitWidth(_64) - // This test require Int to be Int64 - func testCrashingDivision() throws { - // This test makes sure the following division - // does not crash - let first: Decimal = Decimal(1147858867) - let second: Decimal = Decimal(4294967295) - let result = first / second - let expected: Decimal = Decimal( - _exponent: -38, - _length: 8, - _isNegative: 0, - _isCompact: 1, - _reserved: 0, - _mantissa: ( - 58076, - 13229, - 12316, - 25502, - 15252, - 32996, - 11611, - 5147 - ) - ) - XCTAssertEqual(result, expected) - } -#endif - - func testPower() throws { - var a = Decimal(1234) - var result = try a._power(exponent: 0, roundingMode: .plain) - XCTAssert(Decimal._compare(lhs: result, rhs: Decimal(1)) == .orderedSame) - a = Decimal(8) - result = try a._power(exponent: 2, roundingMode: .plain) - XCTAssert(Decimal._compare(lhs: result, rhs: Decimal(64)) == .orderedSame) - a = Decimal(-2) - result = try a._power(exponent: 3, roundingMode: .plain) - XCTAssert(Decimal._compare(lhs: result, rhs: Decimal(-8)) == .orderedSame) - result = try a._power(exponent: 0, roundingMode: .plain) - XCTAssert(Decimal._compare(lhs: result, rhs: Decimal(1)) == .orderedSame) - // Positive base - let six = Decimal(6) - for exponent in 1 ..< 10 { - result = try six._power(exponent: exponent, roundingMode: .plain) - XCTAssertEqual(result.doubleValue, pow(6.0, Double(exponent))) - } - // Negative base - let negativeSix = Decimal(-6) - for exponent in 1 ..< 10 { - result = try negativeSix._power(exponent: exponent, roundingMode: .plain) - XCTAssertEqual(result.doubleValue, pow(-6.0, Double(exponent))) - } - for i in -2 ... 10 { - for j in 0 ... 5 { - let actual = Decimal(i) - let result = try actual._power( - exponent: j, roundingMode: .plain - ) - let expected = Decimal(pow(Double(i), Double(j))) - XCTAssertEqual(expected, result, "\(result) == \(i)^\(j)") - } - } - } - - func testNaNInput() throws { - let nan = Decimal.nan - let one = Decimal(1) - - do { - // NaN + 1 - _ = try nan._add(rhs: one, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) - } - do { - // 1 + NaN - _ = try one._add(rhs: nan, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) - } - - do { - // NaN - 1 - _ = try nan._subtract(rhs: one, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) - } - do { - // 1 - NaN - _ = try one._subtract(rhs: nan, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) - } - - do { - // NaN * 1 - _ = try nan._multiply(by: one, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) - } - do { - // 1 * NaN - _ = try one._multiply(by: nan, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) - } - - do { - // NaN / 1 - _ = try nan._divide(by: one, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) - } - do { - // 1 / NaN - _ = try one._divide(by: nan, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) - } - - do { - // NaN ^ 0 - _ = try nan._power(exponent: 0, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) - } - do { - // NaN ^ 1 - _ = try nan._power(exponent: 1, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) - } - - // Overflow doubles - XCTAssertTrue(Decimal(Double.leastNonzeroMagnitude).isNaN) - XCTAssertTrue(Decimal(Double.leastNormalMagnitude).isNaN) - XCTAssertTrue(Decimal(Double.greatestFiniteMagnitude).isNaN) - XCTAssertTrue(Decimal(Double("1e-129")!).isNaN) - XCTAssertTrue(Decimal(Double("0.1e-128")!).isNaN) - } - - func testDecimalRoundBankers() throws { - let onePointTwo = Decimal(1.2) - var result = try onePointTwo._round(scale: 1, roundingMode: .bankers) - XCTAssertEqual(1.2, result.doubleValue, accuracy: 0.0001) - - let onePointTwoOne = Decimal(1.21) - result = try onePointTwoOne._round(scale: 1, roundingMode: .bankers) - XCTAssertEqual(1.2, result.doubleValue, accuracy: 0.0001) - - let onePointTwoFive = Decimal(1.25) - result = try onePointTwoFive._round(scale: 1, roundingMode: .bankers) - XCTAssertEqual(1.2, result.doubleValue, accuracy: 0.0001) - - let onePointThreeFive = Decimal(1.35) - result = try onePointThreeFive._round(scale: 1, roundingMode: .bankers) - XCTAssertEqual(1.4, result.doubleValue, accuracy: 0.0001) - - let onePointTwoSeven = Decimal(1.27) - result = try onePointTwoSeven._round(scale: 1, roundingMode: .bankers) - XCTAssertEqual(1.3, result.doubleValue, accuracy: 0.0001) - - let minusEightPointFourFive = Decimal(-8.45) - result = try minusEightPointFourFive._round(scale: 1, roundingMode: .bankers) - XCTAssertEqual(-8.4, result.doubleValue, accuracy: 0.0001) - - let minusFourPointNineEightFive = Decimal(-4.985) - result = try minusFourPointNineEightFive._round(scale: 2, roundingMode: .bankers) - XCTAssertEqual(-4.98, result.doubleValue, accuracy: 0.0001) - } - - func test_Round() throws { - let testCases: [(Double, Double, Int, Decimal.RoundingMode)] = [ - // expected, start, scale, round - ( 0, 0.5, 0, .down ), - ( 1, 0.5, 0, .up ), - ( 2, 2.5, 0, .bankers ), - ( 4, 3.5, 0, .bankers ), - ( 5, 5.2, 0, .plain ), - ( 4.5, 4.5, 1, .down ), - ( 5.5, 5.5, 1, .up ), - ( 6.5, 6.5, 1, .plain ), - ( 7.5, 7.5, 1, .bankers ), - - ( -1, -0.5, 0, .down ), - ( -2, -2.5, 0, .up ), - ( -2, -2.5, 0, .bankers ), - ( -4, -3.5, 0, .bankers ), - ( -5, -5.2, 0, .plain ), - ( -4.5, -4.5, 1, .down ), - ( -5.5, -5.5, 1, .up ), - ( -6.5, -6.5, 1, .plain ), - ( -7.5, -7.5, 1, .bankers ), - ] - for testCase in testCases { - let (expected, start, scale, mode) = testCase - let num = Decimal(start) - let actual = try num._round(scale: scale, roundingMode: mode) - XCTAssertEqual(Decimal(expected), actual, "Failed test case: \(testCase)") - } - } - - func test_Maths() { - for i in -2...10 { - for j in 0...5 { - XCTAssertEqual(Decimal(i*j), Decimal(i) * Decimal(j), "\(Decimal(i*j)) == \(i) * \(j)") - XCTAssertEqual(Decimal(i+j), Decimal(i) + Decimal(j), "\(Decimal(i+j)) == \(i)+\(j)") - XCTAssertEqual(Decimal(i-j), Decimal(i) - Decimal(j), "\(Decimal(i-j)) == \(i)-\(j)") - if j != 0 { - let approximation = Decimal(Double(i)/Double(j)) - let answer = Decimal(i) / Decimal(j) - let answerDescription = answer.description - let approximationDescription = approximation.description - var failed: Bool = false - var count = 0 - let SIG_FIG = 14 - for (a, b) in zip(answerDescription, approximationDescription) { - if a != b { - failed = true - break - } - if count == 0 && (a == "-" || a == "0" || a == ".") { - continue // don't count these as significant figures - } - if count >= SIG_FIG { - break - } - count += 1 - } - XCTAssertFalse(failed, "\(Decimal(i/j)) == \(i)/\(j)") - } - } - } - - XCTAssertEqual(Decimal(186243 * 15673 as Int64), Decimal(186243) * Decimal(15673)) - - XCTAssertEqual(Decimal(string: "5538")! + Decimal(string: "2880.4")!, Decimal(string: "8418.4")!) - - XCTAssertEqual(Decimal(string: "5538.0")! - Decimal(string: "2880.4")!, Decimal(string: "2657.6")!) - XCTAssertEqual(Decimal(string: "2880.4")! - Decimal(5538), Decimal(string: "-2657.6")!) - XCTAssertEqual(Decimal(0x10000) - Decimal(0x1000), Decimal(0xf000)) -#if !os(watchOS) - XCTAssertEqual(Decimal(0x1_0000_0000) - Decimal(0x1000), Decimal(0xFFFFF000)) - XCTAssertEqual(Decimal(0x1_0000_0000_0000) - Decimal(0x1000), Decimal(0xFFFFFFFFF000)) -#endif - XCTAssertEqual(Decimal(1234_5678_9012_3456_7899 as UInt64) - Decimal(1234_5678_9012_3456_7890 as UInt64), Decimal(9)) - XCTAssertEqual(Decimal(0xffdd_bb00_8866_4422 as UInt64) - Decimal(0x7777_7777), Decimal(0xFFDD_BB00_10EE_CCAB as UInt64)) - - let highBit = Decimal(_exponent: 0, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000)) - let otherBits = Decimal(_exponent: 0, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x7fff)) - XCTAssertEqual(highBit - otherBits, Decimal(1)) - XCTAssertEqual(otherBits + Decimal(1), highBit) - } - - func testMisc() throws { - XCTAssertEqual(Decimal(-5.2).sign, .minus) - XCTAssertEqual(Decimal(5.2).sign, .plus) - var d = Decimal(5.2) - XCTAssertEqual(d.sign, .plus) - d.negate() - XCTAssertEqual(d.sign, .minus) - d.negate() - XCTAssertEqual(d.sign, .plus) - var e = Decimal(0) - e.negate() - XCTAssertEqual(e, Decimal(0)) - XCTAssertTrue(Decimal(3.5).isEqual(to: Decimal(3.5))) - XCTAssertTrue(Decimal.nan.isEqual(to: Decimal.nan)) - XCTAssertTrue(Decimal(1.28).isLess(than: Decimal(2.24))) - XCTAssertFalse(Decimal(2.28).isLess(than: Decimal(2.24))) - XCTAssertTrue(Decimal(1.28).isTotallyOrdered(belowOrEqualTo: Decimal(2.24))) - XCTAssertFalse(Decimal(2.28).isTotallyOrdered(belowOrEqualTo: Decimal(2.24))) - XCTAssertTrue(Decimal(1.2).isTotallyOrdered(belowOrEqualTo: Decimal(1.2))) - XCTAssertTrue(Decimal.nan.isEqual(to: Decimal.nan)) - XCTAssertTrue(Decimal.nan.isLess(than: Decimal(0))) - XCTAssertFalse(Decimal.nan.isLess(than: Decimal.nan)) - XCTAssertTrue(Decimal.nan.isLessThanOrEqualTo(Decimal(0))) - XCTAssertTrue(Decimal.nan.isLessThanOrEqualTo(Decimal.nan)) - XCTAssertFalse(Decimal.nan.isTotallyOrdered(belowOrEqualTo: Decimal.nan)) - XCTAssertFalse(Decimal.nan.isTotallyOrdered(belowOrEqualTo: Decimal(2.3))) - XCTAssertTrue(Decimal(2) < Decimal(3)) - XCTAssertTrue(Decimal(3) > Decimal(2)) - XCTAssertEqual(Decimal(-9), Decimal(1) - Decimal(10)) - XCTAssertEqual(Decimal(476), Decimal(1024).distance(to: Decimal(1500))) - XCTAssertEqual(Decimal(68040), Decimal(386).advanced(by: Decimal(67654))) - XCTAssertEqual(Decimal(1.234), abs(Decimal(1.234))) - XCTAssertEqual(Decimal(1.234), abs(Decimal(-1.234))) - XCTAssertTrue(Decimal.nan.magnitude.isNaN) - XCTAssertEqual(Decimal.leastFiniteMagnitude.magnitude, -Decimal.leastFiniteMagnitude) - - XCTAssertEqual(Decimal(-9), Decimal(1) - Decimal(10)) - XCTAssertEqual(Decimal(1.234), abs(Decimal(1.234))) - XCTAssertEqual(Decimal(1.234), abs(Decimal(-1.234))) - XCTAssertEqual((0 as Decimal).magnitude, 0 as Decimal) - XCTAssertEqual((1 as Decimal).magnitude, 1 as Decimal) - XCTAssertEqual((1 as Decimal).magnitude, abs(1 as Decimal)) - XCTAssertEqual((1 as Decimal).magnitude, abs(-1 as Decimal)) - XCTAssertEqual((-1 as Decimal).magnitude, abs(-1 as Decimal)) - XCTAssertEqual((-1 as Decimal).magnitude, abs(1 as Decimal)) - XCTAssertEqual(Decimal.greatestFiniteMagnitude.magnitude, Decimal.greatestFiniteMagnitude) - - var a = Decimal(1234) - var result = try a._multiplyByPowerOfTen(power: 1, roundingMode: .plain) - XCTAssertEqual(Decimal(12340), result) - a = Decimal(1234) - result = try a._multiplyByPowerOfTen(power: 2, roundingMode: .plain) - XCTAssertEqual(Decimal(123400), result) - a = result - do { - result = try a._multiplyByPowerOfTen(power: 128, roundingMode: .plain) - XCTFail("Expected to throw _CalcuationError.overflow") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Expected Decimal._CalculationError, got \(error)") - return - } - XCTAssertEqual(.overflow, calculationError) - } - a = Decimal(1234) - result = try a._multiplyByPowerOfTen(power: -2, roundingMode: .plain) - XCTAssertEqual(Decimal(12.34), result) - a = result - do { - result = try a._multiplyByPowerOfTen(power: -128, roundingMode: .plain) - XCTFail("Expected to throw _CalcuationError.underflow") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Expected Decimal._CalculationError, got \(error)") - return - } - XCTAssertEqual(.underflow, calculationError) - } - a = Decimal(1234) - result = try a._power(exponent: 0, roundingMode: .plain) - XCTAssertEqual(Decimal(1), result) - a = Decimal(8) - result = try a._power(exponent: 2, roundingMode: .plain) - XCTAssertEqual(Decimal(64), result) - a = Decimal(-2) - result = try a._power(exponent: 3, roundingMode: .plain) - XCTAssertEqual(Decimal(-8), result) - for i in -2...10 { - for j in 0...5 { - let power = Decimal(i) - let actual = try power._power(exponent: j, roundingMode: .plain) - let expected = Decimal(pow(Double(i), Double(j))) - XCTAssertEqual(expected, actual, "\(actual) == \(i)^\(j)") - XCTAssertEqual(expected, try power._power(exponent: j, roundingMode: .plain)) - } - } - - do { - // SR-13015 - let a = try XCTUnwrap(Decimal(string: "119.993")) - let b = try XCTUnwrap(Decimal(string: "4.1565")) - let c = try XCTUnwrap(Decimal(string: "18.209")) - let d = try XCTUnwrap(Decimal(string: "258.469")) - let ab = a * b - let aDivD = a / d - let caDivD = c * aDivD - XCTAssertEqual(ab, try XCTUnwrap(Decimal(string: "498.7509045"))) - XCTAssertEqual(aDivD, try XCTUnwrap(Decimal(string: "0.46424522863476857959755328492004843907"))) - XCTAssertEqual(caDivD, try XCTUnwrap(Decimal(string: "8.453441368210501065891847765109162027"))) - - let result = (a * b) + (c * (a / d)) - XCTAssertEqual(result, try XCTUnwrap(Decimal(string: "507.2043458682105010658918477651091"))) - } - } - - func test_Constants() { - let smallest = Decimal(_exponent: 127, _length: 8, _isNegative: 1, _isCompact: 1, _reserved: 0, _mantissa: (UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max)) - XCTAssertEqual(smallest, Decimal.leastFiniteMagnitude) - let biggest = Decimal(_exponent: 127, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max)) - XCTAssertEqual(biggest, Decimal.greatestFiniteMagnitude) - let leastNormal = Decimal(_exponent: -127, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1, 0, 0, 0, 0, 0, 0, 0)) - XCTAssertEqual(leastNormal, Decimal.leastNormalMagnitude) - let leastNonzero = Decimal(_exponent: -127, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1, 0, 0, 0, 0, 0, 0, 0)) - XCTAssertEqual(leastNonzero, Decimal.leastNonzeroMagnitude) - let pi = Decimal(_exponent: -38, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0x6623, 0x7d57, 0x16e7, 0xad0d, 0xaf52, 0x4641, 0xdfa7, 0xec58)) - XCTAssertEqual(pi, Decimal.pi) - XCTAssertEqual(10, Decimal.radix) - XCTAssertTrue(Decimal().isCanonical) - XCTAssertFalse(Decimal().isSignalingNaN) - XCTAssertFalse(Decimal.nan.isSignalingNaN) - XCTAssertTrue(Decimal.nan.isNaN) - XCTAssertEqual(.quietNaN, Decimal.nan.floatingPointClass) - XCTAssertEqual(.positiveZero, Decimal().floatingPointClass) - XCTAssertEqual(.negativeNormal, smallest.floatingPointClass) - XCTAssertEqual(.positiveNormal, biggest.floatingPointClass) - XCTAssertFalse(Double.nan.isFinite) - XCTAssertFalse(Double.nan.isInfinite) - } - - func test_parseDouble() throws { - XCTAssertEqual(Decimal(Double(0.0)), Decimal(Int.zero)) - XCTAssertEqual(Decimal(Double(-0.0)), Decimal(Int.zero)) - - // These values can only be represented as Decimal.nan - XCTAssertEqual(Decimal(Double.nan), Decimal.nan) - XCTAssertEqual(Decimal(Double.signalingNaN), Decimal.nan) - - // These values are out out range for Decimal - XCTAssertEqual(Decimal(-Double.leastNonzeroMagnitude), Decimal.nan) - XCTAssertEqual(Decimal(Double.leastNonzeroMagnitude), Decimal.nan) - XCTAssertEqual(Decimal(-Double.leastNormalMagnitude), Decimal.nan) - XCTAssertEqual(Decimal(Double.leastNormalMagnitude), Decimal.nan) - XCTAssertEqual(Decimal(-Double.greatestFiniteMagnitude), Decimal.nan) - XCTAssertEqual(Decimal(Double.greatestFiniteMagnitude), Decimal.nan) - - // SR-13837 - let testDoubles: [(Double, String)] = [ - (1.8446744073709550E18, "1844674407370954752"), - (1.8446744073709551E18, "1844674407370954752"), - (1.8446744073709552E18, "1844674407370955264"), - (1.8446744073709553E18, "1844674407370955264"), - (1.8446744073709554E18, "1844674407370955520"), - (1.8446744073709555E18, "1844674407370955520"), - - (1.8446744073709550E19, "18446744073709547520"), - (1.8446744073709551E19, "18446744073709552640"), - (1.8446744073709552E19, "18446744073709552640"), - (1.8446744073709553E19, "18446744073709552640"), - (1.8446744073709554E19, "18446744073709555200"), - (1.8446744073709555E19, "18446744073709555200"), - - (1.8446744073709550E20, "184467440737095526400"), - (1.8446744073709551E20, "184467440737095526400"), - (1.8446744073709552E20, "184467440737095526400"), - (1.8446744073709553E20, "184467440737095526400"), - (1.8446744073709554E20, "184467440737095552000"), - (1.8446744073709555E20, "184467440737095552000"), - ] - - for (d, s) in testDoubles { - XCTAssertEqual(Decimal(d), Decimal(string: s)) - XCTAssertEqual(Decimal(d).description, try XCTUnwrap(Decimal(string: s)).description) - } - } - - func test_initExactly() { - // This really requires some tests using a BinaryInteger of bitwidth > 128 to test failures. - let d1 = Decimal(exactly: UInt64.max) - XCTAssertNotNil(d1) - XCTAssertEqual(d1?.description, UInt64.max.description) - XCTAssertEqual(d1?._length, 4) - - let d2 = Decimal(exactly: Int64.min) - XCTAssertNotNil(d2) - XCTAssertEqual(d2?.description, Int64.min.description) - XCTAssertEqual(d2?._length, 4) - - let d3 = Decimal(exactly: Int64.max) - XCTAssertNotNil(d3) - XCTAssertEqual(d3?.description, Int64.max.description) - XCTAssertEqual(d3?._length, 4) - - let d4 = Decimal(exactly: Int32.min) - XCTAssertNotNil(d4) - XCTAssertEqual(d4?.description, Int32.min.description) - XCTAssertEqual(d4?._length, 2) - - let d5 = Decimal(exactly: Int32.max) - XCTAssertNotNil(d5) - XCTAssertEqual(d5?.description, Int32.max.description) - XCTAssertEqual(d5?._length, 2) - - let d6 = Decimal(exactly: 0) - XCTAssertNotNil(d6) - XCTAssertEqual(d6, Decimal.zero) - XCTAssertEqual(d6?.description, "0") - XCTAssertEqual(d6?._length, 0) - - let d7 = Decimal(exactly: 1) - XCTAssertNotNil(d7) - XCTAssertEqual(d7?.description, "1") - XCTAssertEqual(d7?._length, 1) - - let d8 = Decimal(exactly: -1) - XCTAssertNotNil(d8) - XCTAssertEqual(d8?.description, "-1") - XCTAssertEqual(d8?._length, 1) - } - - func test_Strideable() { - let x = 42 as Decimal - XCTAssertEqual(x.distance(to: 43), 1) - XCTAssertEqual(x.advanced(by: 1), 43) - XCTAssertEqual(x.distance(to: 41), -1) - XCTAssertEqual(x.advanced(by: -1), 41) - } - - func test_Significand() { - var x = -42 as Decimal - XCTAssertEqual(x.significand.sign, .plus) - var y = Decimal(sign: .plus, exponent: 0, significand: x) -#if FOUNDATION_FRAMEWORK - if Decimal.compatibility1 { - XCTAssertEqual(y, 42) - y = Decimal(sign: .minus, exponent: 0, significand: x) - XCTAssertEqual(y, -42) - } else { - XCTAssertEqual(y, -42) - y = Decimal(sign: .minus, exponent: 0, significand: x) - XCTAssertEqual(y, 42) - } -#else - XCTAssertEqual(y, -42) - y = Decimal(sign: .minus, exponent: 0, significand: x) - XCTAssertEqual(y, 42) -#endif - - x = 42 as Decimal - XCTAssertEqual(x.significand.sign, .plus) - y = Decimal(sign: .plus, exponent: 0, significand: x) - XCTAssertEqual(y, 42) - y = Decimal(sign: .minus, exponent: 0, significand: x) - XCTAssertEqual(y, -42) - - let a = Decimal.leastNonzeroMagnitude - XCTAssertEqual(Decimal(sign: .plus, exponent: -10, significand: a), 0) - XCTAssertEqual(Decimal(sign: .plus, exponent: .min, significand: a), 0) - let b = Decimal.greatestFiniteMagnitude - XCTAssertTrue(Decimal(sign: .plus, exponent: 10, significand: b).isNaN) - XCTAssertTrue(Decimal(sign: .plus, exponent: .max, significand: b).isNaN) - } - - func test_ULP() { - var x = 0.1 as Decimal - XCTAssertFalse(x.ulp > x) - - x = .nan - XCTAssertTrue(x.ulp.isNaN) - XCTAssertTrue(x.nextDown.isNaN) - XCTAssertTrue(x.nextUp.isNaN) - - x = .greatestFiniteMagnitude - XCTAssertEqual(x.ulp, Decimal(string: "1e127")!) - XCTAssertEqual(x.nextDown, x - Decimal(string: "1e127")!) - XCTAssertTrue(x.nextUp.isNaN) - - // '4' is an important value to test because the max supported - // significand of this type is not 10 ** 38 - 1 but rather 2 ** 128 - 1, - // for which reason '4.ulp' is not equal to '1.ulp' despite having the - // same decimal exponent. - x = 4 - XCTAssertEqual(x.ulp, Decimal(string: "1e-37")!) - XCTAssertEqual(x.nextDown, x - Decimal(string: "1e-37")!) - XCTAssertEqual(x.nextUp, x + Decimal(string: "1e-37")!) - XCTAssertEqual(x.nextDown.nextUp, x) - XCTAssertEqual(x.nextUp.nextDown, x) - XCTAssertNotEqual(x.nextDown, x) - XCTAssertNotEqual(x.nextUp, x) - - // For similar reasons, '3.40282366920938463463374607431768211455', - // which has the same significand as 'Decimal.greatestFiniteMagnitude', - // is an important value to test because the distance to the next - // representable value is more than 'ulp' and instead requires - // incrementing '_exponent'. - x = Decimal(string: "3.40282366920938463463374607431768211455")! - XCTAssertEqual(x.ulp, Decimal(string: "0.00000000000000000000000000000000000001")!) - XCTAssertEqual(x.nextUp, Decimal(string: "3.4028236692093846346337460743176821146")!) - x = Decimal(string: "3.4028236692093846346337460743176821146")! - XCTAssertEqual(x.ulp, Decimal(string: "0.0000000000000000000000000000000000001")!) - XCTAssertEqual(x.nextDown, Decimal(string: "3.40282366920938463463374607431768211455")!) - - x = 1 - XCTAssertEqual(x.ulp, Decimal(string: "1e-38")!) - XCTAssertEqual(x.nextDown, x - Decimal(string: "1e-38")!) - XCTAssertEqual(x.nextUp, x + Decimal(string: "1e-38")!) - XCTAssertEqual(x.nextDown.nextUp, x) - XCTAssertEqual(x.nextUp.nextDown, x) - XCTAssertNotEqual(x.nextDown, x) - XCTAssertNotEqual(x.nextUp, x) - - x = 0 - XCTAssertEqual(x.ulp, Decimal(string: "1e-128")!) - XCTAssertEqual(x.nextDown, -Decimal(string: "1e-128")!) - XCTAssertEqual(x.nextUp, Decimal(string: "1e-128")!) - XCTAssertEqual(x.nextDown.nextUp, x) - XCTAssertEqual(x.nextUp.nextDown, x) - XCTAssertNotEqual(x.nextDown, x) - XCTAssertNotEqual(x.nextUp, x) - - x = -1 - XCTAssertEqual(x.ulp, Decimal(string: "1e-38")!) - XCTAssertEqual(x.nextDown, x - Decimal(string: "1e-38")!) - XCTAssertEqual(x.nextUp, x + Decimal(string: "1e-38")!) - let y = x - x.ulp + x.ulp - XCTAssertEqual(x, y) - XCTAssertEqual(x.nextDown.nextUp, x) - XCTAssertEqual(x.nextUp.nextDown, x) - XCTAssertNotEqual(x.nextDown, x) - XCTAssertNotEqual(x.nextUp, x) - } - - #if FOUNDATION_FRAMEWORK - #else - func test_toString() { - let decimal = Decimal(string: "-123456.789")! - XCTAssertEqual(decimal._toString(withDecimalSeparator: "."), "-123456.789") - let en = decimal._toString(withDecimalSeparator: Locale(identifier: "en_GB").decimalSeparator!) - XCTAssertEqual(en, "-123456.789") - let fr = decimal._toString(withDecimalSeparator: Locale(identifier: "fr_FR").decimalSeparator!) - XCTAssertEqual(fr, "-123456,789") - } - - func test_int64Value() { - XCTAssertEqual(Decimal(-1).int64Value, -1) - XCTAssertEqual(Decimal(0).int64Value, 0) - XCTAssertEqual(Decimal(1).int64Value, 1) - XCTAssertEqual(Decimal.nan.int64Value, 0) - XCTAssertEqual(Decimal(1e50).int64Value, 0) - XCTAssertEqual(Decimal(1e-50).int64Value, 0) - - XCTAssertEqual(Decimal(UInt64.max).uint64Value, UInt64.max) - XCTAssertEqual((Decimal(UInt64.max) + 1).uint64Value, 0) - XCTAssertEqual(Decimal(Int64.max).int64Value, Int64.max) - XCTAssertEqual((Decimal(Int64.max) + 1 ).int64Value, Int64.min) - XCTAssertEqual((Decimal(Int64.max) + 1 ).uint64Value, UInt64(Int64.max) + 1) - XCTAssertEqual(Decimal(Int64.min).int64Value, Int64.min) - - XCTAssertEqual(Decimal(Int.min).int64Value, Int64(Int.min)) - - let div3 = Decimal(10) / 3 - XCTAssertEqual(div3.int64Value, 3) - let pi = Decimal(Double.pi) - XCTAssertEqual(pi.int64Value, 3) - } - - func test_doubleValue() { - XCTAssertEqual(Decimal(0).doubleValue, 0) - XCTAssertEqual(Decimal(1).doubleValue, 1) - XCTAssertEqual(Decimal(-1).doubleValue, -1) - XCTAssertTrue(Decimal.nan.doubleValue.isNaN) - XCTAssertEqual(Decimal(UInt64.max).doubleValue, Double(1.8446744073709552e+19)) - } - - func test_decimalFromString() { - let string = "x123x" - let scanLocation = 1 - - let start = string.index(string.startIndex, offsetBy: scanLocation, limitedBy: string.endIndex)! - let substring = string[start.. [FileManagerPlayground.Item]) { - self.name = name - self.attributes = attributes - self.contents = contentsClosure() - } - - fileprivate func build(in path: String, using fileManager: FileManager) throws { - let dirPath = path.appendingPathComponent(name) - try fileManager.createDirectory(atPath: dirPath, withIntermediateDirectories: true, attributes: attributes) - for item in contents { - try item.build(in: dirPath, using: fileManager) - } - } -} - -struct FileManagerPlayground { - enum Item : Buildable { - case file(File) - case directory(Directory) - case symbolicLink(SymbolicLink) - - fileprivate func build(in path: String, using fileManager: FileManager) throws { - switch self { - case let .file(file): try file.build(in: path, using: fileManager) - case let .directory(dir): try dir.build(in: path, using: fileManager) - case let .symbolicLink(symlink): try symlink.build(in: path, using: fileManager) - } - } - } - - @resultBuilder - enum DirectoryBuilder { - static func buildBlock(_ components: Item...) -> [Item] { - components - } - - static func buildExpression(_ expression: File) -> Item { - .file(expression) - } - - static func buildExpression(_ expression: Directory) -> Item { - .directory(expression) - } - - static func buildExpression(_ expression: SymbolicLink) -> Item { - .symbolicLink(expression) - } - } - - private let directory: Directory - - init(@DirectoryBuilder _ contentsClosure: () -> [Item]) { - self.directory = Directory("FileManagerPlayground_\(UUID().uuidString)", contentsClosure) - } - - func test(captureDelegateCalls: Bool = false, file: StaticString = #filePath, line: UInt = #line, _ tester: (FileManager) throws -> Void) throws { - let capturingDelegate = CapturingFileManagerDelegate() - try withExtendedLifetime(capturingDelegate) { - let fileManager = FileManager() - let tempDir = String.temporaryDirectoryPath - try directory.build(in: tempDir, using: fileManager) - let previousCWD = fileManager.currentDirectoryPath - if captureDelegateCalls { - // Add the delegate after the call to `build` to ensure that the builder doesn't mutate the delegate - fileManager.delegate = capturingDelegate - } - let createdDir = tempDir.appendingPathComponent(directory.name) - XCTAssertTrue(fileManager.changeCurrentDirectoryPath(createdDir), "Failed to change CWD to the newly created playground directory", file: file, line: line) - try tester(fileManager) - XCTAssertTrue(fileManager.changeCurrentDirectoryPath(previousCWD), "Failed to change CWD back to the original directory", file: file, line: line) - try fileManager.removeItem(atPath: createdDir) - } - } -} diff --git a/Tests/FoundationEssentialsTests/FileManager/FileManagerTests.swift b/Tests/FoundationEssentialsTests/FileManager/FileManagerTests.swift deleted file mode 100644 index efb13e4d1..000000000 --- a/Tests/FoundationEssentialsTests/FileManager/FileManagerTests.swift +++ /dev/null @@ -1,1075 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - - -#if canImport(TestSupport) -import TestSupport -#endif // canImport(TestSupport) - -#if canImport(FoundationEssentials) -@testable import FoundationEssentials -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#endif - -#if canImport(Android) -@preconcurrency import Android -#endif - -extension FileManager { - fileprivate var delegateCaptures: DelegateCaptures { - (self.delegate as! CapturingFileManagerDelegate).captures - } -} - -private struct DelegateCaptures : Equatable, Sendable { - struct Operation : Equatable, CustomStringConvertible, Comparable { - let src: String - let dst: String? - - var description: String { - if let dst { - "'\(src)' --> '\(dst)'" - } else { - "'\(src)'" - } - } - - static func <(lhs: Operation, rhs: Operation) -> Bool { - lhs.src < rhs.src || lhs.dst == nil || (rhs.dst != nil && lhs.dst! < rhs.dst!) - } - - init(_ src: String, _ dst: String? = nil) { - self.src = src - self.dst = dst - } - } - - struct ErrorOperation : Equatable, CustomStringConvertible { - let op: Operation - let code: CocoaError.Code? - - init(_ src: String, _ dst: String? = nil, code: CocoaError.Code?) { - self.op = Operation(src, dst) - self.code = code - } - - var description: String { - if let code { - "\(op.description) {\(code.rawValue)}" - } else { - "\(op.description) {non-CocoaError}" - } - } - } - var shouldCopy: [Operation] = [] - var shouldProceedAfterCopyError: [ErrorOperation] = [] - var shouldMove: [Operation] = [] - var shouldProceedAfterMoveError: [ErrorOperation] = [] - var shouldLink: [Operation] = [] - var shouldProceedAfterLinkError: [ErrorOperation] = [] - var shouldRemove: [Operation] = [] - var shouldProceedAfterRemoveError: [ErrorOperation] = [] - - var isEmpty: Bool { - self == DelegateCaptures() - } -} - -#if FOUNDATION_FRAMEWORK -class CapturingFileManagerDelegate : NSObject, FileManagerDelegate, @unchecked Sendable { - // Sendable note: This is only used on one thread during testing - fileprivate nonisolated(unsafe) var captures = DelegateCaptures() - - func fileManager(_ fileManager: FileManager, shouldCopyItemAtPath srcPath: String, toPath dstPath: String) -> Bool { - captures.shouldCopy.append(.init(srcPath, dstPath)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldProceedAfterError error: any Error, copyingItemAtPath srcPath: String, toPath dstPath: String) -> Bool { - captures.shouldProceedAfterCopyError.append(.init(srcPath, dstPath, code: (error as? CocoaError)?.code)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldMoveItemAtPath srcPath: String, toPath dstPath: String) -> Bool { - captures.shouldMove.append(.init(srcPath, dstPath)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldProceedAfterError error: any Error, movingItemAtPath srcPath: String, toPath dstPath: String) -> Bool { - captures.shouldProceedAfterMoveError.append(.init(srcPath, dstPath, code: (error as? CocoaError)?.code)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldLinkItemAtPath srcPath: String, toPath dstPath: String) -> Bool { - captures.shouldLink.append(.init(srcPath, dstPath)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldProceedAfterError error: any Error, linkingItemAtPath srcPath: String, toPath dstPath: String) -> Bool { - captures.shouldProceedAfterLinkError.append(.init(srcPath, dstPath, code: (error as? CocoaError)?.code)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldRemoveItemAtPath path: String) -> Bool { - captures.shouldRemove.append(.init(path)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldProceedAfterError error: any Error, removingItemAtPath path: String) -> Bool { - captures.shouldProceedAfterRemoveError.append(DelegateCaptures.ErrorOperation(path, code: (error as? CocoaError)?.code)) - return true - } -} -#else -final class CapturingFileManagerDelegate : FileManagerDelegate, Sendable { - // Sendable note: This is only used on one thread during testing - fileprivate nonisolated(unsafe) var captures = DelegateCaptures() - - func fileManager(_ fileManager: FileManager, shouldCopyItemAtPath srcPath: String, toPath dstPath: String) -> Bool { - captures.shouldCopy.append(.init(srcPath, dstPath)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldProceedAfterError error: any Error, copyingItemAtPath srcPath: String, toPath dstPath: String) -> Bool { - captures.shouldProceedAfterCopyError.append(.init(srcPath, dstPath, code: (error as? CocoaError)?.code)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldMoveItemAtPath srcPath: String, toPath dstPath: String) -> Bool { - captures.shouldMove.append(.init(srcPath, dstPath)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldProceedAfterError error: any Error, movingItemAtPath srcPath: String, toPath dstPath: String) -> Bool { - captures.shouldProceedAfterMoveError.append(.init(srcPath, dstPath, code: (error as? CocoaError)?.code)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldLinkItemAtPath srcPath: String, toPath dstPath: String) -> Bool { - captures.shouldLink.append(.init(srcPath, dstPath)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldProceedAfterError error: any Error, linkingItemAtPath srcPath: String, toPath dstPath: String) -> Bool { - captures.shouldProceedAfterLinkError.append(.init(srcPath, dstPath, code: (error as? CocoaError)?.code)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldRemoveItemAtPath path: String) -> Bool { - captures.shouldRemove.append(.init(path)) - return true - } - - func fileManager(_ fileManager: FileManager, shouldProceedAfterError error: any Error, removingItemAtPath path: String) -> Bool { - captures.shouldProceedAfterRemoveError.append(DelegateCaptures.ErrorOperation(path, code: (error as? CocoaError)?.code)) - return true - } -} -#endif - -final class FileManagerTests : XCTestCase { - private func randomData(count: Int = 10000) -> Data { - Data((0 ..< count).map { _ in UInt8.random(in: .min ..< .max) }) - } - - func testContentsAtPath() throws { - let data = randomData() - try FileManagerPlayground { - File("test", contents: data) - }.test { - XCTAssertEqual($0.contents(atPath: "test"), data) - } - } - - func testContentsEqualAtPaths() throws { - try FileManagerPlayground { - Directory("dir1") { - Directory("dir2") { - "Foo" - "Bar" - } - Directory("dir3") { - "Baz" - } - } - Directory("dir1_copy") { - Directory("dir2") { - "Foo" - "Bar" - } - Directory("dir3") { - "Baz" - } - } - Directory("dir1_diffdata") { - Directory("dir2") { - "Foo" - "Bar" - } - Directory("dir3") { - File("Baz", contents: randomData()) - } - } - Directory("symlinks") { - File("Foo", contents: randomData()) - SymbolicLink("LinkToFoo", destination: "Foo") - } - Directory("EmptyDirectory") {} - "EmptyFile" - }.test { - XCTAssertTrue($0.contentsEqual(atPath: "dir1", andPath: "dir1_copy")) - XCTAssertFalse($0.contentsEqual(atPath: "dir1/dir2", andPath: "dir1/dir3")) - XCTAssertFalse($0.contentsEqual(atPath: "dir1", andPath: "dir1_diffdata")) - XCTAssertFalse($0.contentsEqual(atPath: "symlinks/LinkToFoo", andPath: "symlinks/Foo"), "Symbolic link should not be equal to its destination") - XCTAssertFalse($0.contentsEqual(atPath: "symlinks/LinkToFoo", andPath: "EmptyFile"), "Symbolic link should not be equal to an empty file") - XCTAssertFalse($0.contentsEqual(atPath: "symlinks/LinkToFoo", andPath: "EmptyDirectory"), "Symbolic link should not be equal to an empty directory") - XCTAssertFalse($0.contentsEqual(atPath: "symlinks/EmptyDirectory", andPath: "EmptyFile"), "Empty directory should not be equal to empty file") - } - } - - func testDirectoryContentsAtPath() throws { - try FileManagerPlayground { - Directory("dir1") { - Directory("dir2") { - "Foo" - "Bar" - } - Directory("dir3") { - "Baz" - } - } - }.test { - XCTAssertEqual(try $0.contentsOfDirectory(atPath: "dir1").sorted(), ["dir2", "dir3"]) - XCTAssertEqual(try $0.contentsOfDirectory(atPath: "dir1/dir2").sorted(), ["Bar", "Foo"]) - XCTAssertEqual(try $0.contentsOfDirectory(atPath: "dir1/dir3").sorted(), ["Baz"]) - XCTAssertThrowsError(try $0.contentsOfDirectory(atPath: "does_not_exist")) { - XCTAssertEqual(($0 as? CocoaError)?.code, .fileReadNoSuchFile) - } - } - } - - func testSubpathsOfDirectoryAtPath() throws { - try FileManagerPlayground { - Directory("dir1") { - Directory("dir2") { - "Foo" - "Bar" - } - Directory("dir3") { - "Baz" - } - } - Directory("symlinks") { - "Foo" - SymbolicLink("Bar", destination: "Foo") - SymbolicLink("Parent", destination: "..") - } - }.test { - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: "dir1").sorted(), ["dir2", "dir2/Bar", "dir2/Foo", "dir3", "dir3/Baz"]) - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: "dir1/dir2").sorted(), ["Bar", "Foo"]) - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: "dir1/dir3").sorted(), ["Baz"]) - - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: "symlinks").sorted(), ["Bar", "Foo", "Parent"]) - - XCTAssertThrowsError(try $0.subpathsOfDirectory(atPath: "does_not_exist")) { - XCTAssertEqual(($0 as? CocoaError)?.code, .fileReadNoSuchFile) - } - - XCTAssertThrowsError(try $0.subpathsOfDirectory(atPath: "")) { - #if os(Windows) - XCTAssertEqual(($0 as? CocoaError)?.code, .fileReadInvalidFileName) - #else - XCTAssertEqual(($0 as? CocoaError)?.code, .fileReadNoSuchFile) - #endif - } - - let fullContents = ["dir1", "dir1/dir2", "dir1/dir2/Bar", "dir1/dir2/Foo", "dir1/dir3", "dir1/dir3/Baz", "symlinks", "symlinks/Bar", "symlinks/Foo", "symlinks/Parent"] - let cwd = $0.currentDirectoryPath - XCTAssertNotEqual(cwd.last, "/") - let paths = [cwd, "\(cwd)/", "\(cwd)//", ".", "./", ".//"] - for path in paths { - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: path).sorted(), fullContents) - } - - } - } - - func testCreateDirectoryAtPath() throws { - try FileManagerPlayground { - "preexisting_file" - }.test { - try $0.createDirectory(atPath: "create_dir_test", withIntermediateDirectories: false) - XCTAssertEqual(try $0.contentsOfDirectory(atPath: ".").sorted(), ["create_dir_test", "preexisting_file"]) - try $0.createDirectory(atPath: "create_dir_test2/nested", withIntermediateDirectories: true) - XCTAssertEqual(try $0.contentsOfDirectory(atPath: "create_dir_test2"), ["nested"]) - try $0.createDirectory(atPath: "create_dir_test2/nested2", withIntermediateDirectories: true) - XCTAssertEqual(try $0.contentsOfDirectory(atPath: "create_dir_test2").sorted(), ["nested", "nested2"]) - XCTAssertNoThrow(try $0.createDirectory(atPath: "create_dir_test2/nested2", withIntermediateDirectories: true)) - - #if os(Windows) - try $0.createDirectory(atPath: "create_dir_test3\\nested", withIntermediateDirectories: true) - XCTAssertEqual(try $0.contentsOfDirectory(atPath: "create_dir_test3"), ["nested"]) - #endif - - XCTAssertThrowsError(try $0.createDirectory(atPath: "create_dir_test", withIntermediateDirectories: false)) { - XCTAssertEqual(($0 as? CocoaError)?.code, .fileWriteFileExists) - } - XCTAssertThrowsError(try $0.createDirectory(atPath: "create_dir_test4/nested", withIntermediateDirectories: false)) { - XCTAssertEqual(($0 as? CocoaError)?.code, .fileNoSuchFile) - } - XCTAssertThrowsError(try $0.createDirectory(atPath: "preexisting_file", withIntermediateDirectories: false)) { - XCTAssertEqual(($0 as? CocoaError)?.code, .fileWriteFileExists) - } - XCTAssertThrowsError(try $0.createDirectory(atPath: "preexisting_file", withIntermediateDirectories: true)) { - XCTAssertEqual(($0 as? CocoaError)?.code, .fileWriteFileExists) - } - } - } - - func testLinkFileAtPathToPath() throws { - try FileManagerPlayground { - "foo" - }.test(captureDelegateCalls: true) { - XCTAssertTrue($0.delegateCaptures.isEmpty) - try $0.linkItem(atPath: "foo", toPath: "bar") - XCTAssertEqual($0.delegateCaptures.shouldLink, [.init("foo", "bar")]) - #if os(Android) // Hard links are not normally allowed on Android. - XCTAssertEqual($0.delegateCaptures.shouldProceedAfterLinkError, [.init("foo", "bar", code: .fileWriteNoPermission)]) - XCTAssertFalse($0.fileExists(atPath: "bar")) - #else - XCTAssertEqual($0.delegateCaptures.shouldProceedAfterLinkError, []) - XCTAssertTrue($0.fileExists(atPath: "bar")) - #endif - } - - try FileManagerPlayground { - "foo" - "bar" - }.test(captureDelegateCalls: true) { - XCTAssertTrue($0.delegateCaptures.isEmpty) - try $0.linkItem(atPath: "foo", toPath: "bar") - XCTAssertEqual($0.delegateCaptures.shouldLink, [.init("foo", "bar")]) - XCTAssertEqual($0.delegateCaptures.shouldProceedAfterLinkError, [.init("foo", "bar", code: .fileWriteFileExists)]) - } - } - - func testCopyFileAtPathToPath() throws { - try FileManagerPlayground { - "foo" - }.test(captureDelegateCalls: true) { - XCTAssertTrue($0.delegateCaptures.isEmpty) - try $0.copyItem(atPath: "foo", toPath: "bar") - XCTAssertEqual($0.delegateCaptures.shouldCopy, [.init("foo", "bar")]) - XCTAssertEqual($0.delegateCaptures.shouldProceedAfterCopyError, []) - XCTAssertTrue($0.fileExists(atPath: "bar")) - } - - try FileManagerPlayground { - "foo" - "bar" - }.test(captureDelegateCalls: true) { - XCTAssertTrue($0.delegateCaptures.isEmpty) - try $0.copyItem(atPath: "foo", toPath: "bar") - XCTAssertEqual($0.delegateCaptures.shouldCopy, [.init("foo", "bar")]) - XCTAssertEqual($0.delegateCaptures.shouldProceedAfterCopyError, [.init("foo", "bar", code: .fileWriteFileExists)]) - } - - try FileManagerPlayground { - "foo" - SymbolicLink("bar", destination: "foo") - }.test(captureDelegateCalls: true) { - XCTAssertTrue($0.delegateCaptures.isEmpty) - try $0.copyItem(atPath: "bar", toPath: "copy") - XCTAssertEqual($0.delegateCaptures.shouldCopy, [.init("bar", "copy")]) - XCTAssertEqual($0.delegateCaptures.shouldProceedAfterCopyError, []) - let copyDestination = try $0.destinationOfSymbolicLink(atPath: "copy") - XCTAssertEqual(copyDestination.lastPathComponent, "foo", "Copied symbolic link points at \(copyDestination) instead of foo") - } - - try FileManagerPlayground { - Directory("dir") { - "foo" - } - SymbolicLink("link", destination: "dir") - }.test(captureDelegateCalls: true) { - XCTAssertTrue($0.delegateCaptures.isEmpty) - try $0.copyItem(atPath: "link", toPath: "copy") - XCTAssertEqual($0.delegateCaptures.shouldCopy, [.init("link", "copy")]) - XCTAssertEqual($0.delegateCaptures.shouldProceedAfterCopyError, []) - let copyDestination = try $0.destinationOfSymbolicLink(atPath: "copy") - XCTAssertEqual(copyDestination.lastPathComponent, "dir", "Copied symbolic link points at \(copyDestination) instead of foo") - } - } - - func testCreateSymbolicLinkAtPath() throws { - try FileManagerPlayground { - "foo" - Directory("dir") {} - }.test { - try $0.createSymbolicLink(atPath: "bar", withDestinationPath: "foo") - XCTAssertEqual(try $0.destinationOfSymbolicLink(atPath: "bar"), "foo") - - try $0.createSymbolicLink(atPath: "dir_link", withDestinationPath: "dir") - XCTAssertEqual(try $0.destinationOfSymbolicLink(atPath: "dir_link"), "dir") - - XCTAssertThrowsError(try $0.createSymbolicLink(atPath: "bar", withDestinationPath: "foo")) { - XCTAssertEqual(($0 as? CocoaError)?.code, .fileWriteFileExists) - } - XCTAssertThrowsError(try $0.createSymbolicLink(atPath: "foo", withDestinationPath: "baz")) { - XCTAssertEqual(($0 as? CocoaError)?.code, .fileWriteFileExists) - } - XCTAssertThrowsError(try $0.destinationOfSymbolicLink(atPath: "foo")) { - XCTAssertEqual(($0 as? CocoaError)?.code, .fileReadUnknown) - } - } - - try FileManagerPlayground { - Directory("dir") { - Directory("other_dir") { - "file" - } - } - }.test { - // Create a relative symlink to other_dir from within dir (tests windows special dir symlink handling) - try $0.createSymbolicLink(atPath: "dir/link", withDestinationPath: "other_dir") - - // Ensure it is created successfully - XCTAssertEqual(try $0.destinationOfSymbolicLink(atPath: "dir/link"), "other_dir") - XCTAssertEqual(try $0.contentsOfDirectory(atPath: "dir/link"), ["file"]) - - do { - // Second symlink creation with an absolute path - let absolute = URL(filePath: "dir/link2", relativeTo: URL(filePath: $0.currentDirectoryPath, directoryHint: .isDirectory)).path - try $0.createSymbolicLink(atPath: absolute, withDestinationPath: "other_dir") - - // Ensure it is created successfully - XCTAssertEqual(try $0.destinationOfSymbolicLink(atPath: "dir/link2"), "other_dir") - XCTAssertEqual(try $0.contentsOfDirectory(atPath: "dir/link2"), ["file"]) - } - - do { - // And lastly a symlink to an absolute path - let absolute = URL(filePath: "dir/other_dir", relativeTo: URL(filePath: $0.currentDirectoryPath, directoryHint: .isDirectory)).path - try $0.createSymbolicLink(atPath: "dir/link3", withDestinationPath: absolute) - - // Ensure it is created successfully - XCTAssertEqual(try $0.destinationOfSymbolicLink(atPath: "dir/link3"), absolute.withFileSystemRepresentation { String(cString: $0!) }) - XCTAssertEqual(try $0.contentsOfDirectory(atPath: "dir/link3"), ["file"]) - } - } - } - - func testMoveItemAtPathToPath() throws { - let data = randomData() - try FileManagerPlayground { - Directory("dir") { - File("foo", contents: data) - "bar" - } - "other_file" - }.test(captureDelegateCalls: true) { - XCTAssertTrue($0.delegateCaptures.isEmpty) - try $0.moveItem(atPath: "dir", toPath: "dir2") - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: ".").sorted(), ["dir2", "dir2/bar", "dir2/foo", "other_file"]) - XCTAssertEqual($0.contents(atPath: "dir2/foo"), data) - - let rootDir = URL(fileURLWithPath: $0.currentDirectoryPath).path - XCTAssertEqual($0.delegateCaptures.shouldMove, [.init("\(rootDir)/dir", "\(rootDir)/dir2")]) - - try $0.moveItem(atPath: "does_not_exist", toPath: "dir3") - XCTAssertEqual($0.delegateCaptures.shouldProceedAfterMoveError, [.init("\(rootDir)/does_not_exist", "\(rootDir)/dir3", code: .fileNoSuchFile)]) - - try $0.moveItem(atPath: "dir2", toPath: "other_file") - XCTAssertTrue($0.delegateCaptures.shouldProceedAfterMoveError.contains(.init("\(rootDir)/dir2", "\(rootDir)/other_file", code: .fileWriteFileExists))) - } - } - - func testCopyItemAtPathToPath() throws { - let data = randomData() - try FileManagerPlayground { - Directory("dir", attributes: [.posixPermissions : 0o777]) { - File("foo", contents: data) - "bar" - } - "other_file" - }.test(captureDelegateCalls: true) { - XCTAssertTrue($0.delegateCaptures.isEmpty) - try $0.copyItem(atPath: "dir", toPath: "dir2") - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: ".").sorted(), ["dir", "dir/bar", "dir/foo", "dir2", "dir2/bar", "dir2/foo", "other_file"]) - XCTAssertEqual($0.contents(atPath: "dir/foo"), data) - XCTAssertEqual($0.contents(atPath: "dir2/foo"), data) -#if os(Windows) - XCTAssertEqual($0.delegateCaptures.shouldCopy, [.init("dir", "dir2"), .init("dir/bar", "dir2/bar"), .init("dir/foo", "dir2/foo")]) -#else - var shouldCopy = $0.delegateCaptures.shouldCopy - XCTAssertEqual(shouldCopy.removeFirst(), .init("dir", "dir2")) - XCTAssertEqual(shouldCopy.sorted(), [.init("dir/foo", "dir2/foo"), .init("dir/bar", "dir2/bar")].sorted()) - - // Specifically for non-Windows (where copying directory metadata takes a special path) double check that the metadata was copied exactly - XCTAssertEqual(try $0.attributesOfItem(atPath: "dir2")[.posixPermissions] as? UInt, 0o777) -#endif - XCTAssertThrowsError(try $0.copyItem(atPath: "does_not_exist", toPath: "dir3")) { - XCTAssertEqual(($0 as? CocoaError)?.code, .fileReadNoSuchFile) - } - - try $0.copyItem(atPath: "dir", toPath: "other_file") - XCTAssertTrue($0.delegateCaptures.shouldProceedAfterCopyError.contains(.init("dir", "other_file", code: .fileWriteFileExists))) - } - } - - func testRemoveItemAtPath() throws { - try FileManagerPlayground { - Directory("dir") { - "foo" - "bar" - } - "other" - }.test(captureDelegateCalls: true) { - XCTAssertTrue($0.delegateCaptures.isEmpty) - try $0.removeItem(atPath: "dir/bar") - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: ".").sorted(), ["dir", "dir/foo", "other"]) - XCTAssertEqual($0.delegateCaptures.shouldRemove, [.init("dir/bar")]) - XCTAssertEqual($0.delegateCaptures.shouldProceedAfterRemoveError, []) - - let rootDir = URL(fileURLWithPath: $0.currentDirectoryPath).path - try $0.removeItem(atPath: "dir") - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: ".").sorted(), ["other"]) - XCTAssertEqual($0.delegateCaptures.shouldRemove, [.init("dir/bar"), .init("\(rootDir)/dir"), .init("\(rootDir)/dir/foo")]) - XCTAssertEqual($0.delegateCaptures.shouldProceedAfterRemoveError, []) - - try $0.removeItem(atPath: "other") - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: ".").sorted(), []) - XCTAssertEqual($0.delegateCaptures.shouldRemove, [.init("dir/bar"), .init("\(rootDir)/dir"), .init("\(rootDir)/dir/foo"), .init("other")]) - XCTAssertEqual($0.delegateCaptures.shouldProceedAfterRemoveError, []) - - try $0.removeItem(atPath: "does_not_exist") - XCTAssertEqual($0.delegateCaptures.shouldRemove, [.init("dir/bar"), .init("\(rootDir)/dir"), .init("\(rootDir)/dir/foo"), .init("other"), .init("does_not_exist")]) - XCTAssertEqual($0.delegateCaptures.shouldProceedAfterRemoveError, [.init("does_not_exist", code: .fileNoSuchFile)]) - } - - try FileManagerPlayground { - Directory("dir") { - Directory("dir2") { - "file" - } - } - }.test(captureDelegateCalls: true) { - let rootDir = URL(fileURLWithPath: $0.currentDirectoryPath).path - - XCTAssertTrue($0.delegateCaptures.isEmpty) - try $0.removeItem(atPath: "dir") - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: ".").sorted(), []) - XCTAssertEqual($0.delegateCaptures.shouldRemove, [.init("\(rootDir)/dir"), .init("\(rootDir)/dir/dir2"), .init("\(rootDir)/dir/dir2/file")]) - XCTAssertEqual($0.delegateCaptures.shouldProceedAfterRemoveError, []) - } - - #if canImport(Darwin) - // not supported on linux as the test depends on FileManager.removeItem calling removefile(3) - try FileManagerPlayground { - }.test { - // Create hierarchy in which the leaf is a long path (length > PATH_MAX) - let rootDir = $0.currentDirectoryPath - let aas = Array(repeating: "a", count: Int(NAME_MAX) - 3).joined() - let bbs = Array(repeating: "b", count: Int(NAME_MAX) - 3).joined() - let ccs = Array(repeating: "c", count: Int(NAME_MAX) - 3).joined() - let dds = Array(repeating: "d", count: Int(NAME_MAX) - 3).joined() - let ees = Array(repeating: "e", count: Int(NAME_MAX) - 3).joined() - let leaf = "longpath" - - try $0.createDirectory(atPath: aas, withIntermediateDirectories: true) - XCTAssertTrue($0.changeCurrentDirectoryPath(aas)) - try $0.createDirectory(atPath: bbs, withIntermediateDirectories: true) - XCTAssertTrue($0.changeCurrentDirectoryPath(bbs)) - try $0.createDirectory(atPath: ccs, withIntermediateDirectories: true) - XCTAssertTrue($0.changeCurrentDirectoryPath(ccs)) - try $0.createDirectory(atPath: dds, withIntermediateDirectories: true) - XCTAssertTrue($0.changeCurrentDirectoryPath(dds)) - try $0.createDirectory(atPath: ees, withIntermediateDirectories: true) - XCTAssertTrue($0.changeCurrentDirectoryPath(ees)) - try $0.createDirectory(atPath: leaf, withIntermediateDirectories: true) - - XCTAssertTrue($0.changeCurrentDirectoryPath(rootDir)) - let fullPath = "\(aas)/\(bbs)/\(ccs)/\(dds)/\(ees)/\(leaf)" - XCTAssertThrowsError(try $0.removeItem(atPath: fullPath)) { - let underlyingPosixError = ($0 as? CocoaError)?.underlying as? POSIXError - XCTAssertEqual(underlyingPosixError?.code, .ENAMETOOLONG, "removeItem didn't fail with ENAMETOOLONG; produced error: \($0)") - } - - // Clean up - XCTAssertTrue($0.changeCurrentDirectoryPath(aas)) - XCTAssertTrue($0.changeCurrentDirectoryPath(bbs)) - XCTAssertTrue($0.changeCurrentDirectoryPath(ccs)) - XCTAssertTrue($0.changeCurrentDirectoryPath(dds)) - try $0.removeItem(atPath: ees) - XCTAssertTrue($0.changeCurrentDirectoryPath("..")) - try $0.removeItem(atPath: dds) - XCTAssertTrue($0.changeCurrentDirectoryPath("..")) - try $0.removeItem(atPath: ccs) - XCTAssertTrue($0.changeCurrentDirectoryPath("..")) - try $0.removeItem(atPath: bbs) - XCTAssertTrue($0.changeCurrentDirectoryPath("..")) - try $0.removeItem(atPath: aas) - } - #endif - } - - func testFileExistsAtPath() throws { - try FileManagerPlayground { - Directory("dir") { - "foo" - "bar" - } - "other" - SymbolicLink("link_to_file", destination: "other") - SymbolicLink("link_to_dir", destination: "dir") - SymbolicLink("link_to_nonexistent", destination: "does_not_exist") - }.test { - #if FOUNDATION_FRAMEWORK - var isDir: ObjCBool = false - func isDirBool() -> Bool { - isDir.boolValue - } - #else - var isDir: Bool = false - func isDirBool() -> Bool { - isDir - } - #endif - XCTAssertTrue($0.fileExists(atPath: "dir/foo", isDirectory: &isDir)) - XCTAssertFalse(isDirBool()) - XCTAssertTrue($0.fileExists(atPath: "dir/bar", isDirectory: &isDir)) - XCTAssertFalse(isDirBool()) - XCTAssertTrue($0.fileExists(atPath: "dir", isDirectory: &isDir)) - XCTAssertTrue(isDirBool()) - XCTAssertTrue($0.fileExists(atPath: "other", isDirectory: &isDir)) - XCTAssertFalse(isDirBool()) - XCTAssertTrue($0.fileExists(atPath: "link_to_file", isDirectory: &isDir)) - XCTAssertFalse(isDirBool()) - XCTAssertTrue($0.fileExists(atPath: "link_to_dir", isDirectory: &isDir)) - XCTAssertTrue(isDirBool()) - XCTAssertFalse($0.fileExists(atPath: "does_not_exist")) - XCTAssertFalse($0.fileExists(atPath: "link_to_nonexistent")) - } - } - - func testFileAccessAtPath() throws { - #if !os(Windows) - guard getuid() != 0 else { - // Root users can always access anything, so this test will not function when run as root - throw XCTSkip("This test is not available when running as the root user") - } - #endif - - try FileManagerPlayground { - File("000", attributes: [.posixPermissions: 0o000]) - File("111", attributes: [.posixPermissions: 0o111]) - File("222", attributes: [.posixPermissions: 0o222]) - File("333", attributes: [.posixPermissions: 0o333]) - File("444", attributes: [.posixPermissions: 0o444]) - File("555", attributes: [.posixPermissions: 0o555]) - File("666", attributes: [.posixPermissions: 0o666]) - File("777", attributes: [.posixPermissions: 0o777]) - }.test { - #if os(Windows) - // All files are readable on Windows - let readable = ["000", "111", "222", "333", "444", "555", "666", "777"] - // None of these files are executable on Windows - let executable: [String] = [] - #else - let readable = ["444", "555", "666", "777"] - let executable = ["111", "333", "555", "777"] - #endif - let writable = ["222", "333", "666", "777"] - for number in 0...7 { - let file = "\(number)\(number)\(number)" - XCTAssertEqual($0.isReadableFile(atPath: file), readable.contains(file), "'\(file)' failed readable check") - XCTAssertEqual($0.isWritableFile(atPath: file), writable.contains(file), "'\(file)' failed writable check") - XCTAssertEqual($0.isExecutableFile(atPath: file), executable.contains(file), "'\(file)' failed executable check") - #if os(Windows) - // Only writable files are deletable on Windows - XCTAssertEqual($0.isDeletableFile(atPath: file), writable.contains(file), "'\(file)' failed deletable check") - #else - XCTAssertTrue($0.isDeletableFile(atPath: file), "'\(file)' failed deletable check") - #endif - } - } - } - - func testFileSystemAttributesAtPath() throws { - try FileManagerPlayground { - "Foo" - }.test { - let dict = try $0.attributesOfFileSystem(forPath: "Foo") - XCTAssertNotNil(dict[.systemSize]) - XCTAssertThrowsError(try $0.attributesOfFileSystem(forPath: "does_not_exist")) { - XCTAssertEqual(($0 as? CocoaError)?.code, .fileReadNoSuchFile) - } - } - } - - func testCurrentWorkingDirectory() throws { - try FileManagerPlayground { - Directory("dir") { - "foo" - } - "bar" - }.test { - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: ".").sorted(), ["bar", "dir", "dir/foo"]) - XCTAssertTrue($0.changeCurrentDirectoryPath("dir")) - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: "."), ["foo"]) - XCTAssertFalse($0.changeCurrentDirectoryPath("foo")) - XCTAssertTrue($0.changeCurrentDirectoryPath("..")) - XCTAssertEqual(try $0.subpathsOfDirectory(atPath: ".").sorted(), ["bar", "dir", "dir/foo"]) - XCTAssertFalse($0.changeCurrentDirectoryPath("does_not_exist")) - - // Test get current directory path when it's parent directory was removed. - XCTAssertTrue($0.changeCurrentDirectoryPath("dir")) -#if os(Windows) - // Removing the current working directory fails on Windows because the directory is in use. - XCTAssertThrowsError(try $0.removeItem(atPath: $0.currentDirectoryPath)) { - XCTAssertEqual(($0 as? CocoaError)?.code, .fileWriteNoPermission) - } -#else - try $0.removeItem(atPath: $0.currentDirectoryPath) - XCTAssertEqual($0.currentDirectoryPath, "") -#endif - } - } - - func testBooleanFileAttributes() throws { - #if canImport(Darwin) - try FileManagerPlayground { - "none" - File("immutable", attributes: [.immutable: true]) - File("appendOnly", attributes: [.appendOnly: true]) - File("immutable_appendOnly", attributes: [.immutable: true, .appendOnly: true]) - }.test { - let tests: [(path: String, immutable: Bool, appendOnly: Bool)] = [ - ("none", false, false), - ("immutable", true, false), - ("appendOnly", false, true), - ("immutable_appendOnly", true, true) - ] - - for test in tests { - let result = try $0.attributesOfItem(atPath: test.path) - XCTAssertEqual(result[.immutable] as? Bool, test.immutable, "Item at path '\(test.path)' did not provide expected result for immutable key") - XCTAssertEqual(result[.appendOnly] as? Bool, test.appendOnly, "Item at path '\(test.path)' did not provide expected result for appendOnly key") - - XCTAssertNil(result[.busy], "Item at path '\(test.path)' has non-nil value for .busy attribute") // Should only be set when true - - // Manually clean up attributes so removal does not fail - try $0.setAttributes([.immutable: false, .appendOnly: false], ofItemAtPath: test.path) - } - } - #else - throw XCTSkip("This test is not applicable on this platform") - #endif - } - - func testMalformedModificationDateAttribute() throws { - let sentinelDate = Date(timeIntervalSince1970: 100) - try FileManagerPlayground { - File("foo", attributes: [.modificationDate: sentinelDate]) - }.test { - XCTAssertEqual(try $0.attributesOfItem(atPath: "foo")[.modificationDate] as? Date, sentinelDate) - for value in [Double.infinity, -Double.infinity, Double.nan] { - // Malformed modification dates should be dropped instead of throwing or crashing - try $0.setAttributes([.modificationDate : Date(timeIntervalSince1970: value)], ofItemAtPath: "foo") - } - XCTAssertEqual(try $0.attributesOfItem(atPath: "foo")[.modificationDate] as? Date, sentinelDate) - } - } - - func testImplicitlyConvertibleFileAttributes() throws { - try FileManagerPlayground { - File("foo", attributes: [.posixPermissions : UInt16(0o644)]) - }.test { - let attributes = try $0.attributesOfItem(atPath: "foo") - - // Ensure the unconventional UInt16 was accepted as input - #if os(Windows) - XCTAssertEqual(attributes[.posixPermissions] as? UInt, 0o600) - #else - XCTAssertEqual(attributes[.posixPermissions] as? UInt, 0o644) - #endif - - #if FOUNDATION_FRAMEWORK - // Where we have NSNumber, ensure that we can get the value back as an unconventional Double value - XCTAssertEqual(attributes[.posixPermissions] as? Double, Double(0o644)) - // Ensure that the file type can be converted to a String when it is an ObjC enum - XCTAssertEqual(attributes[.type] as? String, FileAttributeType.typeRegular.rawValue) - #endif - - // Ensure that the file type can be converted to a FileAttributeType when it is an ObjC enum and in swift-foundation - XCTAssertEqual(attributes[.type] as? FileAttributeType, .typeRegular) - - } - } - - func testStandardizingPathAutomount() throws { - #if canImport(Darwin) - let tests = [ - "/private/System" : "/private/System", - "/private/tmp" : "/tmp", - "/private/System/foo" : "/private/System/foo" - ] - for (input, expected) in tests { - XCTAssertEqual(input.standardizingPath, expected, "Standardizing the path '\(input)' did not produce the expected result") - } - #else - throw XCTSkip("This test is not applicable to this platform") - #endif - } - - func testResolveSymlinksViaGetAttrList() throws { - #if !canImport(Darwin) - throw XCTSkip("This test is not applicable on this platform") - #else - try FileManagerPlayground { - "destination" - }.test { - try $0.createSymbolicLink(atPath: "link", withDestinationPath: "destination") - let absolutePath = $0.currentDirectoryPath.appendingPathComponent("link") - let resolved = absolutePath._resolvingSymlinksInPath() // Call internal function to avoid path standardization - XCTAssertEqual(resolved, $0.currentDirectoryPath.appendingPathComponent("destination").withFileSystemRepresentation { String(cString: $0!) }) - } - #endif - } - - #if os(macOS) && FOUNDATION_FRAMEWORK - func testSpecialTrashDirectoryTruncation() throws { - try FileManagerPlayground {}.test { - if let trashURL = try? $0.url(for: .trashDirectory, in: .allDomainsMask, appropriateFor: nil, create: false) { - XCTAssertEqual(trashURL.pathComponents.last, ".Trash") - } - } - } - - func testSpecialTrashDirectoryDuplication() throws { - try FileManagerPlayground {}.test { fileManager in - let trashURLs = fileManager.urls(for: .trashDirectory, in: .userDomainMask) - XCTAssertEqual(trashURLs.count, 1, "There should only be one trash directory for the user domain, found \(trashURLs)") - } - } - #endif - - func testSearchPaths() throws { - func assertSearchPaths(_ directories: [FileManager.SearchPathDirectory], exists: Bool, file: StaticString = #filePath, line: UInt = #line) { - for directory in directories { - let paths = FileManager.default.urls(for: directory, in: .allDomainsMask) - XCTAssertEqual(!paths.isEmpty, exists, "Directory \(directory) produced an unexpected number of paths (expected to exist: \(exists), produced: \(paths))", file: file, line: line) - } - } - - // Cross platform paths that always exist - assertSearchPaths([ - .userDirectory, - .documentDirectory, - .autosavedInformationDirectory, - .autosavedInformationDirectory, - .desktopDirectory, - .cachesDirectory, - .applicationSupportDirectory, - .downloadsDirectory, - .moviesDirectory, - .musicDirectory, - .sharedPublicDirectory - ], exists: true) - - #if canImport(Darwin) - let isDarwin = true - #else - let isDarwin = false - #endif - - // Darwin-only paths - assertSearchPaths([ - .applicationDirectory, - .demoApplicationDirectory, - .developerApplicationDirectory, - .adminApplicationDirectory, - .libraryDirectory, - .developerDirectory, - .documentationDirectory, - .coreServiceDirectory, - .inputMethodsDirectory, - .preferencePanesDirectory, - .allApplicationsDirectory, - .allLibrariesDirectory, - .printerDescriptionDirectory - ], exists: isDarwin) - - #if os(macOS) - let isMacOS = true - #else - let isMacOS = false - #endif - - #if FOUNDATION_FRAMEWORK - let isFramework = true - #else - let isFramework = false - #endif - - #if os(Windows) - let isWindows = true - #else - let isWindows = false - #endif - - // .trashDirectory is unavailable on watchOS/tvOS and only produces paths on macOS (the framework build) + non-Darwin - #if !os(watchOS) && !os(tvOS) - assertSearchPaths([.trashDirectory], exists: (isMacOS && isFramework) || (!isDarwin && !isWindows)) - #endif - - // .picturesDirectory does not exist in CI, though it does exist in user - // desktop scenarios. - #if !os(Windows) - assertSearchPaths([.picturesDirectory], exists: true) - #endif - - // .applicationScriptsDirectory is only available on macOS and only produces paths in the framework build - #if os(macOS) - assertSearchPaths([.applicationScriptsDirectory], exists: isFramework) - #endif - - // .itemReplacementDirectory never exists - assertSearchPaths([.itemReplacementDirectory], exists: false) - } - - func testSearchPaths_XDGEnvironmentVariables() throws { - #if canImport(Darwin) || os(Windows) - throw XCTSkip("This test is not applicable on this platform") - #else - if let key = ProcessInfo.processInfo.environment.keys.first(where: { $0.starts(with: "XDG") }) { - throw XCTSkip("Skipping due to presence of '\(key)' environment variable which may affect this test") - } - - try FileManagerPlayground { - Directory("TestPath") {} - }.test { fileManager in - func validate(_ key: String, suffix: String? = nil, directory: FileManager.SearchPathDirectory, domain: FileManager.SearchPathDomainMask, file: StaticString = #filePath, line: UInt = #line) { - let oldValue = ProcessInfo.processInfo.environment[key] ?? "" - var knownPath = fileManager.currentDirectoryPath.appendingPathComponent("TestPath") - setenv(key, knownPath, 1) - defer { setenv(key, oldValue, 1) } - if let suffix { - // The suffix is not stored in the environment variable, it is just applied to the expectation - knownPath = knownPath.appendingPathComponent(suffix) - } - let knownURL = URL(filePath: knownPath, directoryHint: .isDirectory) - let results = fileManager.urls(for: directory, in: domain) - XCTAssertTrue(results.contains(knownURL), "Results \(results.map(\.path)) did not contain known directory \(knownURL.path) for \(directory)/\(domain) while setting the \(key) environment variable", file: file, line: line) - } - - validate("XDG_DATA_HOME", suffix: "Autosave Information", directory: .autosavedInformationDirectory, domain: .userDomainMask) - validate("HOME", suffix: ".local/share/Autosave Information", directory: .autosavedInformationDirectory, domain: .userDomainMask) - - validate("XDG_CACHE_HOME", directory: .cachesDirectory, domain: .userDomainMask) - validate("HOME", suffix: ".cache", directory: .cachesDirectory, domain: .userDomainMask) - - validate("XDG_DATA_HOME", directory: .applicationSupportDirectory, domain: .userDomainMask) - validate("HOME", suffix: ".local/share", directory: .applicationSupportDirectory, domain: .userDomainMask) - - validate("HOME", directory: .userDirectory, domain: .localDomainMask) - } - #endif - } - - func testGetSetAttributes() throws { - try FileManagerPlayground { - File("foo", contents: randomData()) - }.test { - let attrs = try $0.attributesOfItem(atPath: "foo") - try $0.setAttributes(attrs, ofItemAtPath: "foo") - } - } - - func testCurrentUserHomeDirectory() throws { - #if canImport(Darwin) && !os(macOS) - throw XCTSkip("This test is not applicable on this platform") - #else - let userName = ProcessInfo.processInfo.userName - XCTAssertEqual(FileManager.default.homeDirectory(forUser: userName), FileManager.default.homeDirectoryForCurrentUser) - #endif - } - - func testAttributesOfItemAtPath() throws { - try FileManagerPlayground { - "file" - File("fileWithContents", contents: randomData()) - Directory("directory") { - "file" - } - }.test { - do { - let attrs = try $0.attributesOfItem(atPath: "file") - XCTAssertEqual(attrs[.size] as? UInt, 0) - XCTAssertEqual(attrs[.type] as? FileAttributeType, FileAttributeType.typeRegular) - } - - do { - let attrs = try $0.attributesOfItem(atPath: "fileWithContents") - XCTAssertGreaterThan(try XCTUnwrap(attrs[.size] as? UInt), 0) - XCTAssertEqual(attrs[.type] as? FileAttributeType, FileAttributeType.typeRegular) - } - - do { - let attrs = try $0.attributesOfItem(atPath: "directory") - XCTAssertEqual(attrs[.type] as? FileAttributeType, FileAttributeType.typeDirectory) - } - - do { - try $0.createSymbolicLink(atPath: "symlink", withDestinationPath: "file") - let attrs = try $0.attributesOfItem(atPath: "symlink") - XCTAssertEqual(attrs[.type] as? FileAttributeType, FileAttributeType.typeSymbolicLink) - } - } - } - - func testHomeDirectoryForNonExistantUser() throws { - #if canImport(Darwin) && !os(macOS) - throw XCTSkip("This test is not applicable on this platform") - #else - XCTAssertNil(FileManager.default.homeDirectory(forUser: "")) - XCTAssertNil(FileManager.default.homeDirectory(forUser: UUID().uuidString)) - #endif - } - - func testSearchPathsWithoutExpandingTilde() throws { - #if !canImport(Darwin) - throw XCTSkip("This test is not applicable for this platform") - #else - for path in _DarwinSearchPaths(for: .libraryDirectory, in: .userDomainMask, expandTilde: false) { - XCTAssertTrue(path.starts(with: "~/"), "Path '\(path)' did not start with ~/ as expected") - } - #endif - } - - func testWindowsDirectoryCreationCrash() throws { - try FileManagerPlayground { - Directory("a\u{301}") { - - } - }.test { - XCTAssertTrue($0.fileExists(atPath: "a\u{301}")) - let data = randomData() - XCTAssertTrue($0.createFile(atPath: "a\u{301}/test", contents: data)) - XCTAssertTrue($0.fileExists(atPath: "a\u{301}/test")) - XCTAssertEqual($0.contents(atPath: "a\u{301}/test"), data) - } - } -} diff --git a/Tests/FoundationEssentialsTests/Formatting/BinaryInteger+FormatStyleTests.swift b/Tests/FoundationEssentialsTests/Formatting/BinaryInteger+FormatStyleTests.swift deleted file mode 100644 index 76cfd50e5..000000000 --- a/Tests/FoundationEssentialsTests/Formatting/BinaryInteger+FormatStyleTests.swift +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) 2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// RUN: %target-run-simple-swift -// REQUIRES: executable_test - -import XCTest - -#if canImport(FoundationEssentials) -@testable import FoundationEssentials -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#endif - -#if canImport(Numberick) // Not included by default as it's a 3rd party library; requires https://github.com/oscbyspro/Numberick.git be added the package dependencies. -import Numberick -#endif - -#if canImport(BigInt) // Not included by default as it's a 3rd party library; requires https://github.com/attaswift/BigInt.git be added the package dependencies. Proved useful in the past for finding bugs that only show up with large numbers. -import BigInt -#endif - -final class BinaryIntegerFormatStyleTests: XCTestCase { - // NSR == numericStringRepresentation - func checkNSR(value: some BinaryInteger, expected: String) { - XCTAssertEqual(String(decoding: value.numericStringRepresentation.utf8, as: Unicode.ASCII.self), expected) - } - - func testNumericStringRepresentation_builtinIntegersLimits() throws { - func check(type: I.Type = I.self, min: String, max: String) { - checkNSR(value: I.min, expected: min) - checkNSR(value: I.max, expected: max) - } - - check(type: Int8.self, min: "-128", max: "127") - check(type: Int16.self, min: "-32768", max: "32767") - check(type: Int32.self, min: "-2147483648", max: "2147483647") - check(type: Int64.self, min: "-9223372036854775808", max: "9223372036854775807") - check(type: Int128.self, min: "-170141183460469231731687303715884105728", max: "170141183460469231731687303715884105727") - - check(type: UInt8.self, min: "0", max: "255") - check(type: UInt16.self, min: "0", max: "65535") - check(type: UInt32.self, min: "0", max: "4294967295") - check(type: UInt64.self, min: "0", max: "18446744073709551615") - check(type: UInt128.self, min: "0", max: "340282366920938463463374607431768211455") - } - - func testNumericStringRepresentation_builtinIntegersAroundDecimalMagnitude() throws { - func check(type: I.Type = I.self, magnitude: String, oneLess: String, oneMore: String) { - var mag = I(1); while !mag.multipliedReportingOverflow(by: 10).overflow { mag *= 10 } - - checkNSR(value: mag, expected: magnitude) - checkNSR(value: mag - 1, expected: oneLess) - checkNSR(value: mag + 1, expected: oneMore) - } - - check(type: Int8.self, magnitude: "100", oneLess: "99", oneMore: "101") - check(type: Int16.self, magnitude: "10000", oneLess: "9999", oneMore: "10001") - check(type: Int32.self, magnitude: "1000000000", oneLess: "999999999", oneMore: "1000000001") - check(type: Int64.self, magnitude: "1000000000000000000", oneLess: "999999999999999999", oneMore: "1000000000000000001") - - check(type: UInt8.self, magnitude: "100", oneLess: "99", oneMore: "101") - check(type: UInt16.self, magnitude: "10000", oneLess: "9999", oneMore: "10001") - check(type: UInt32.self, magnitude: "1000000000", oneLess: "999999999", oneMore: "1000000001") - check(type: UInt64.self, magnitude: "10000000000000000000", oneLess: "9999999999999999999", oneMore: "10000000000000000001") - } - -#if canImport(Numberick) || canImport(BigInt) - // An initialiser has to be passed manually because BinaryInteger doesn't actually provide a way to initialise an instance from a string representation (that's functional for non-builtin integers). - func check(type: I.Type = I.self, initialiser: (String) -> I?) { - // Just some real basic sanity checks first. - checkNSR(value: I(0), expected: "0") - checkNSR(value: I(1), expected: "1") - - if I.isSigned { - checkNSR(value: I(-1), expected: "-1") - } - - for valueAsString in ["9223372036854775807", // Int64.max - "9223372036854775808", // Int64.max + 1 (and Int64.min when negated). - - "9999999999999999999", // Test around the magnitude. - "10000000000000000000", - "10000000000000000001", - - "18446744073709551615", // UInt64.max - "18446744073709551616", // UInt64.max + 1 - - "170141183460469231731687303715884105727", // Int128.max - "170141183460469231731687303715884105728", // Int128.max + 1 - "340282366920938463463374607431768211455", // UInt128.max - "340282366920938463463374607431768211456", // UInt128.max + 1 - - // Some arbitrary, *very* large numbers to ensure there's no egregious scaling issues nor fatal inaccuracies in things like sizing of preallocated buffers. - "1" + String(repeating: "0", count: 99), - "1" + String(repeating: "0", count: 999), - "1" + String(repeating: "0", count: 1406), // First power of ten value at which an earlier implementation crashed due to underestimating how many wordStrings would be needed. - String(repeating: "1234567890", count: 10), - String(repeating: "1234567890", count: 100)] { - if let value = initialiser(valueAsString) { // The test cases cover a wide range of values, that don't all fit into every type tested (i.e. the fixed-width types from Numberick). - XCTAssertEqual(value.description, valueAsString) // Sanity check that it initialised from the string correctly. - checkNSR(value: value, expected: valueAsString) - - if I.isSigned { - let negativeValueAsString = "-" + valueAsString - let negativeValue = initialiser(negativeValueAsString)! - - XCTAssertEqual(negativeValue.description, negativeValueAsString) // Sanity check that it initialised from the string correctly. - checkNSR(value: negativeValue, expected: negativeValueAsString) - } - } - } - } - -#if canImport(Numberick) - func testNumericStringRepresentation_largeIntegers() throws { - check(type: Int128.self, initialiser: { Int128($0) }) - check(type: UInt128.self, initialiser: { UInt128($0) }) - - check(type: Int256.self, initialiser: { Int256($0) }) - check(type: UInt256.self, initialiser: { UInt256($0) }) - } -#endif - -#if canImport(BigInt) - func testNumericStringRepresentation_arbitraryPrecisionIntegers() throws { - check(type: BigInt.self, initialiser: { BigInt($0)! }) - check(type: BigUInt.self, initialiser: { BigUInt($0)! }) - } -#endif -#endif // canImport(Numberick) || canImport(BigInt) -} - -final class BinaryIntegerFormatStyleTestsUsingBinaryIntegerWords: XCTestCase { - - // MARK: Tests - - func testInt32() { - check( Int32(truncatingIfNeeded: 0x00000000 as UInt32), expectation: "0") - check( Int32(truncatingIfNeeded: 0x03020100 as UInt32), expectation: "50462976") - check( Int32(truncatingIfNeeded: 0x7fffffff as UInt32), expectation: "2147483647") // Int32.max - check( Int32(truncatingIfNeeded: 0x80000000 as UInt32), expectation: "-2147483648") // Int32.min - check( Int32(truncatingIfNeeded: 0x81807f7e as UInt32), expectation: "-2122285186") - check( Int32(truncatingIfNeeded: 0xfffefdfc as UInt32), expectation: "-66052") - check( Int32(truncatingIfNeeded: 0xffffffff as UInt32), expectation: "-1") - } - - func testUInt32() { - check(UInt32(truncatingIfNeeded: 0x00000000 as UInt32), expectation: "0") // UInt32.min - check(UInt32(truncatingIfNeeded: 0x03020100 as UInt32), expectation: "50462976") - check(UInt32(truncatingIfNeeded: 0x7fffffff as UInt32), expectation: "2147483647") - check(UInt32(truncatingIfNeeded: 0x80000000 as UInt32), expectation: "2147483648") - check(UInt32(truncatingIfNeeded: 0x81807f7e as UInt32), expectation: "2172682110") - check(UInt32(truncatingIfNeeded: 0xfffefdfc as UInt32), expectation: "4294901244") - check(UInt32(truncatingIfNeeded: 0xffffffff as UInt32), expectation: "4294967295") // UInt32.max - } - - func testInt64() { - check( Int64(truncatingIfNeeded: 0x0000000000000000 as UInt64), expectation: "0") - check( Int64(truncatingIfNeeded: 0x0706050403020100 as UInt64), expectation: "506097522914230528") - check( Int64(truncatingIfNeeded: 0x7fffffffffffffff as UInt64), expectation: "9223372036854775807") // Int64.max - check( Int64(truncatingIfNeeded: 0x8000000000000000 as UInt64), expectation: "-9223372036854775808") // Int64.max - check( Int64(truncatingIfNeeded: 0x838281807f7e7d7c as UInt64), expectation: "-8970465118873813636") - check( Int64(truncatingIfNeeded: 0xfffefdfcfbfaf9f8 as UInt64), expectation: "-283686952306184") - check( Int64(truncatingIfNeeded: 0xffffffffffffffff as UInt64), expectation: "-1") - } - - func testUInt64() { - check(UInt64(truncatingIfNeeded: 0x0000000000000000 as UInt64), expectation: "0") // UInt64.min - check(UInt64(truncatingIfNeeded: 0x0706050403020100 as UInt64), expectation: "506097522914230528") - check(UInt64(truncatingIfNeeded: 0x7fffffffffffffff as UInt64), expectation: "9223372036854775807") - check(UInt64(truncatingIfNeeded: 0x8000000000000000 as UInt64), expectation: "9223372036854775808") - check(UInt64(truncatingIfNeeded: 0x838281807f7e7d7c as UInt64), expectation: "9476278954835737980") - check(UInt64(truncatingIfNeeded: 0xfffefdfcfbfaf9f8 as UInt64), expectation: "18446460386757245432") - check(UInt64(truncatingIfNeeded: 0xffffffffffffffff as UInt64), expectation: "18446744073709551615") // UInt64.max - } - - // MARK: Tests + Big Integer - - func testInt128() { - check(x64:[0x0000000000000000, 0x0000000000000000] as [UInt64], isSigned: true, expectation: "0") - check(x64:[0x0706050403020100, 0x0f0e0d0c0b0a0908] as [UInt64], isSigned: true, expectation: "20011376718272490338853433276725592320") - check(x64:[0xffffffffffffffff, 0x7fffffffffffffff] as [UInt64], isSigned: true, expectation: "170141183460469231731687303715884105727") // Int128.max - check(x64:[0x0000000000000000, 0x8000000000000000] as [UInt64], isSigned: true, expectation: "-170141183460469231731687303715884105728") // Int128.min - check(x64:[0xf7f6f5f4f3f2f1f0, 0xfffefdfcfbfaf9f8] as [UInt64], isSigned: true, expectation: "-5233100606242806050955395731361296") - check(x64:[0xffffffffffffffff, 0xffffffffffffffff] as [UInt64], isSigned: true, expectation: "-1") - } - - func testUInt128() { - check(x64:[0x0000000000000000, 0x0000000000000000] as [UInt64], isSigned: false, expectation: "0") // UInt128.min - check(x64:[0x0706050403020100, 0x0f0e0d0c0b0a0908] as [UInt64], isSigned: false, expectation: "20011376718272490338853433276725592320") - check(x64:[0x0000000000000000, 0x8000000000000000] as [UInt64], isSigned: false, expectation: "170141183460469231731687303715884105728") - check(x64:[0xf7f6f5f4f3f2f1f0, 0xfffefdfcfbfaf9f8] as [UInt64], isSigned: false, expectation: "340277133820332220657323652036036850160") - check(x64:[0xffffffffffffffff, 0x7fffffffffffffff] as [UInt64], isSigned: false, expectation: "170141183460469231731687303715884105727") - check(x64:[0xffffffffffffffff, 0xffffffffffffffff] as [UInt64], isSigned: false, expectation: "340282366920938463463374607431768211455") // UInt128.max - } - - // MARK: Tests + Big Integer + Miscellaneous - - func testWordsIsEmptyResultsInZero() { - check(words:[ ] as [UInt], isSigned: true, expectation: "0") - check(words:[ ] as [UInt], isSigned: false, expectation: "0") - } - - func testSignExtendingDoesNotChangeTheResult() { - check(words:[ 0 ] as [UInt], isSigned: true, expectation: "0") - check(words:[ 0, 0 ] as [UInt], isSigned: true, expectation: "0") - check(words:[ 0, 0, 0 ] as [UInt], isSigned: true, expectation: "0") - check(words:[ 0, 0, 0, 0] as [UInt], isSigned: true, expectation: "0") - - check(words:[~0 ] as [UInt], isSigned: true, expectation: "-1") - check(words:[~0, ~0 ] as [UInt], isSigned: true, expectation: "-1") - check(words:[~0, ~0, ~0 ] as [UInt], isSigned: true, expectation: "-1") - check(words:[~0, ~0, ~0, ~0] as [UInt], isSigned: true, expectation: "-1") - - check(words:[ 0 ] as [UInt], isSigned: false, expectation: "0") - check(words:[ 0, 0 ] as [UInt], isSigned: false, expectation: "0") - check(words:[ 0, 0, 0 ] as [UInt], isSigned: false, expectation: "0") - check(words:[ 0, 0, 0, 0] as [UInt], isSigned: false, expectation: "0") - } - - // MARK: Assertions - - func check(_ integer: some BinaryInteger, expectation: String, file: StaticString = #filePath, line: UInt = #line) { - XCTAssertEqual(integer.description, expectation, "integer description does not match expectation", file: file, line: line) - check(ascii: integer.numericStringRepresentation.utf8, expectation: expectation, file: file, line: line) - check(words: Array(integer.words), isSigned: type(of: integer).isSigned, expectation: expectation, file: file, line: line) - } - - func check(x64: [UInt64], isSigned: Bool, expectation: String, file: StaticString = #filePath, line: UInt = #line) { - check(words: x64.flatMap(\.words), isSigned: isSigned, expectation: expectation, file: file, line: line) - } - - func check(words: [UInt], isSigned: Bool, expectation: String, file: StaticString = #filePath, line: UInt = #line) { - let ascii = numericStringRepresentationForBinaryInteger(words: words, isSigned: isSigned).utf8 - check(ascii: ascii, expectation: expectation, file: file, line: line) - } - - func check(ascii: some Collection, expectation: String, file: StaticString = #filePath, line: UInt = #line) { - XCTAssertEqual(String(decoding: ascii, as: Unicode.ASCII.self), expectation, file: file, line: line) - } -} diff --git a/Tests/FoundationEssentialsTests/Formatting/HTTPFormatStyleFormattingTests.swift b/Tests/FoundationEssentialsTests/Formatting/HTTPFormatStyleFormattingTests.swift deleted file mode 100644 index 5d4b23a30..000000000 --- a/Tests/FoundationEssentialsTests/Formatting/HTTPFormatStyleFormattingTests.swift +++ /dev/null @@ -1,138 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(FoundationEssentials) -@testable import FoundationEssentials -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#endif - -final class HTTPFormatStyleFormattingTests: XCTestCase { - - func test_HTTPFormat() throws { - let date = Date.now - - let formatted = date.formatted(.http) // e.g. "Fri, 17 Jan 2025 19:03:05 GMT" - let parsed = try? Date(formatted, strategy: .http) - - let result = try XCTUnwrap(parsed) - XCTAssertEqual(date.timeIntervalSinceReferenceDate, result.timeIntervalSinceReferenceDate, accuracy: 1.0) - } - - func test_HTTPFormat_components() throws { - let date = Date.now - let formatted = date.formatted(.http) // e.g. "Fri, 17 Jan 2025 19:03:05 GMT" - - let parsed = try? DateComponents(formatted, strategy: .http) - - let result = try XCTUnwrap(parsed) - - let resultDate = Calendar(identifier: .gregorian).date(from: result) - let resultDateUnwrapped = try XCTUnwrap(resultDate) - - XCTAssertEqual(date.timeIntervalSinceReferenceDate, resultDateUnwrapped.timeIntervalSinceReferenceDate, accuracy: 1.0) - } - - func test_HTTPFormat_variousInputs() throws { - let tests = [ - "Mon, 20 Jan 2025 01:02:03 GMT", - "Tue, 20 Jan 2025 10:02:03 GMT", - "Wed, 20 Jan 2025 23:02:03 GMT", - "Thu, 20 Jan 2025 01:10:03 GMT", - "Fri, 20 Jan 2025 01:50:59 GMT", - "Sat, 20 Jan 2025 01:50:60 GMT", // 60 is valid, treated as 0 - "Sun, 20 Jan 2025 01:03:03 GMT", - "20 Jan 2025 01:02:03 GMT", // Missing weekdays is ok - "20 Jan 2025 10:02:03 GMT", - "20 Jan 2025 23:02:03 GMT", - "20 Jan 2025 01:10:03 GMT", - "20 Jan 2025 01:50:59 GMT", - "20 Jan 2025 01:50:60 GMT", - "20 Jan 2025 01:03:03 GMT", - "Mon, 20 Jan 2025 01:03:03 GMT", - "Mon, 03 Feb 2025 01:03:03 GMT", - "Mon, 03 Mar 2025 01:03:03 GMT", - "Mon, 14 Apr 2025 01:03:03 GMT", - "Mon, 05 May 2025 01:03:03 GMT", - "Mon, 21 Jul 2025 01:03:03 GMT", - "Mon, 04 Aug 2025 01:03:03 GMT", - "Mon, 22 Sep 2025 01:03:03 GMT", - "Mon, 30 Oct 2025 01:03:03 GMT", - "Mon, 24 Nov 2025 01:03:03 GMT", - "Mon, 22 Dec 2025 01:03:03 GMT", - "Tue, 29 Feb 2028 01:03:03 GMT", // leap day - ] - - for good in tests { - XCTAssertNotNil(try? Date(good, strategy: .http), "Input \(good) was nil") - XCTAssertNotNil(try? DateComponents(good, strategy: .http), "Input \(good) was nil") - } - } - - func test_HTTPFormat_badInputs() throws { - let tests = [ - "Xri, 17 Jan 2025 19:03:05 GMT", - "Fri, 17 Janu 2025 19:03:05 GMT", - "Fri, 17Jan 2025 19:03:05 GMT", - "Fri, 17 Xrz 2025 19:03:05 GMT", - "Fri, 17 Jan 2025 19:03:05", // missing GMT - "Fri, 1 Jan 2025 19:03:05 GMT", - "Fri, 17 Jan 2025 1:03:05 GMT", - "Fri, 17 Jan 2025 19:3:05 GMT", - "Fri, 17 Jan 2025 19:03:5 GMT", - "Fri, 17 Jan 2025 19:03:05 GmT", - "Fri, 17 Jan 20252 19:03:05 GMT", - "Fri, 17 Jan 252 19:03:05 GMT", - "fri, 17 Jan 2025 19:03:05 GMT", // miscapitalized - "Fri, 17 jan 2025 19:03:05 GMT", - "Fri, 16 Jan 2025 25:03:05 GMT", // nonsense date - "Fri, 30 Feb 2025 25:03:05 GMT", // nonsense date - ] - - for bad in tests { - XCTAssertNil(try? Date(bad, strategy: .http), "Input \(bad) was not nil") - XCTAssertNil(try? DateComponents(bad, strategy: .http), "Input \(bad) was not nil") - } - } - - func test_HTTPComponentsFormat() throws { - let input = "Fri, 17 Jan 2025 19:03:05 GMT" - let parsed = try? DateComponents(input, strategy: .http) - - XCTAssertEqual(parsed?.weekday, 6) - XCTAssertEqual(parsed?.day, 17) - XCTAssertEqual(parsed?.month, 1) - XCTAssertEqual(parsed?.year, 2025) - XCTAssertEqual(parsed?.hour, 19) - XCTAssertEqual(parsed?.minute, 3) - XCTAssertEqual(parsed?.second, 5) - XCTAssertEqual(parsed?.timeZone, TimeZone.gmt) - } - - func test_validatingResultOfParseVsString() throws { - // This date will parse correctly, but of course the value of 99 does not correspond to the actual day. - let strangeDate = "Mon, 99 Jan 2025 19:03:05 GMT" - let date = try XCTUnwrap(Date(strangeDate, strategy: .http)) - let components = try XCTUnwrap(DateComponents(strangeDate, strategy: .http)) - - let actualDay = Calendar(identifier: .gregorian).component(.day, from: date) - let componentDay = try XCTUnwrap(components.day) - XCTAssertNotEqual(actualDay, componentDay) - } -} - diff --git a/Tests/FoundationEssentialsTests/Formatting/ISO8601FormatStyleFormattingTests.swift b/Tests/FoundationEssentialsTests/Formatting/ISO8601FormatStyleFormattingTests.swift deleted file mode 100644 index c0ceccb0b..000000000 --- a/Tests/FoundationEssentialsTests/Formatting/ISO8601FormatStyleFormattingTests.swift +++ /dev/null @@ -1,215 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(FoundationEssentials) -@testable import FoundationEssentials -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#endif - -final class ISO8601FormatStyleFormattingTests: XCTestCase { - - func test_ISO8601Format() throws { - let date = Date(timeIntervalSinceReferenceDate: 665076946.0) - let fractionalSecondsDate = Date(timeIntervalSinceReferenceDate: 665076946.011) - let iso8601 = Date.ISO8601FormatStyle() - - // Date is: "2022-01-28 15:35:46" - XCTAssertEqual(iso8601.format(date), "2022-01-28T15:35:46Z") - - XCTAssertEqual(iso8601.time(includingFractionalSeconds: true).format(fractionalSecondsDate), "15:35:46.011") - - XCTAssertEqual(iso8601.year().month().day().time(includingFractionalSeconds: true).format(fractionalSecondsDate), "2022-01-28T15:35:46.011") - - // Day-only results: the default time is midnight for parsed date when the time piece is missing - // Date is: "2022-01-28 00:00:00" - XCTAssertEqual(iso8601.year().month().day().dateSeparator(.dash).format(date), "2022-01-28") - - // Date is: "2022-01-28 00:00:00" - XCTAssertEqual(iso8601.year().month().day().dateSeparator(.omitted).format(date), "20220128") - - // Time-only results: we use the default date of the format style, 1970-01-01, to supplement the parsed date without year, month or day - // Date is: "1970-01-23 00:00:00" - XCTAssertEqual(iso8601.weekOfYear().day().dateSeparator(.dash).format(date), "W04-05") - - // Date is: "1970-01-28 15:35:46" - XCTAssertEqual(iso8601.day().time(includingFractionalSeconds: false).timeSeparator(.colon).format(date), "028T15:35:46") - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(iso8601.time(includingFractionalSeconds: false).timeSeparator(.colon).format(date), "15:35:46") - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(iso8601.time(includingFractionalSeconds: false).timeZone(separator: .omitted).format(date), "15:35:46Z") - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(iso8601.time(includingFractionalSeconds: false).timeZone(separator: .colon).format(date), "15:35:46Z") - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(iso8601.timeZone(separator: .colon).time(includingFractionalSeconds: false).timeSeparator(.colon).format(date), "15:35:46Z") - - // Time zones - - var iso8601Pacific = iso8601 - iso8601Pacific.timeZone = TimeZone(secondsFromGMT: -3600 * 8)! - - // Has a seconds component (-28830) - var iso8601PacificIsh = iso8601 - iso8601PacificIsh.timeZone = TimeZone(secondsFromGMT: -3600 * 8 - 30)! - - XCTAssertEqual(iso8601Pacific.timeSeparator(.omitted).format(date), "2022-01-28T073546-0800") - XCTAssertEqual(iso8601Pacific.timeSeparator(.omitted).timeZoneSeparator(.colon).format(date), "2022-01-28T073546-08:00") - - XCTAssertEqual(iso8601PacificIsh.timeSeparator(.omitted).format(date), "2022-01-28T073516-080030") - XCTAssertEqual(iso8601PacificIsh.timeSeparator(.omitted).timeZoneSeparator(.colon).format(date), "2022-01-28T073516-08:00:30") - - var iso8601gmtP1 = iso8601 - iso8601gmtP1.timeZone = TimeZone(secondsFromGMT: 3600)! - XCTAssertEqual(iso8601gmtP1.timeSeparator(.omitted).format(date), "2022-01-28T163546+0100") - XCTAssertEqual(iso8601gmtP1.timeSeparator(.omitted).timeZoneSeparator(.colon).format(date), "2022-01-28T163546+01:00") - - } - - func test_ISO8601ComponentsFormatMissingPieces() throws { - // Example code from the proposal - let components = DateComponents(year: 1999, month: 12, day: 31) - let formatted = components.formatted(.iso8601) - XCTAssertEqual(formatted, "1999-12-31T00:00:00Z") - - - let emptyComponents = DateComponents() - let emptyFormatted = emptyComponents.formatted(.iso8601) - XCTAssertEqual(emptyFormatted, "1970-01-01T00:00:00Z") - } - - func test_ISO8601ComponentsFormat() throws { - let date = Date(timeIntervalSinceReferenceDate: 665076946.0) - // Be sure to use the ISO8601 calendar here to decompose to the right week of year components (the starting day is not the same as gregorian) - let componentsInGMT = Calendar(identifier: .iso8601).dateComponents(in: .gmt, from: date) - let fractionalSecondsDate = Date(timeIntervalSinceReferenceDate: 665076946.011) - let fractionalSecondsComponents = Calendar(identifier: .iso8601).dateComponents(in: .gmt, from: fractionalSecondsDate) - let iso8601 = DateComponents.ISO8601FormatStyle() - - // Date is: "2022-01-28 15:35:46" - XCTAssertEqual(iso8601.format(componentsInGMT), "2022-01-28T15:35:46Z") - - XCTAssertEqual(iso8601.time(includingFractionalSeconds: true).format(fractionalSecondsComponents), "15:35:46.011") - - XCTAssertEqual(iso8601.year().month().day().time(includingFractionalSeconds: true).format(fractionalSecondsComponents), "2022-01-28T15:35:46.011") - - // Day-only results: the default time is midnight for parsed date when the time piece is missing - // Date is: "2022-01-28 00:00:00" - XCTAssertEqual(iso8601.year().month().day().dateSeparator(.dash).format(componentsInGMT), "2022-01-28") - - // Date is: "2022-01-28 00:00:00" - XCTAssertEqual(iso8601.year().month().day().dateSeparator(.omitted).format(componentsInGMT), "20220128") - - // Time-only results: we use the default date of the format style, 1970-01-01, to supplement the parsed date without year, month or day - // Date is: "1970-01-23 00:00:00" - XCTAssertEqual(iso8601.weekOfYear().day().dateSeparator(.dash).format(componentsInGMT), "W04-05") - - // Date is: "1970-01-28 15:35:46" - XCTAssertEqual(iso8601.day().time(includingFractionalSeconds: false).timeSeparator(.colon).format(componentsInGMT), "028T15:35:46") - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(iso8601.time(includingFractionalSeconds: false).timeSeparator(.colon).format(componentsInGMT), "15:35:46") - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(iso8601.time(includingFractionalSeconds: false).timeZone(separator: .omitted).format(componentsInGMT), "15:35:46Z") - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(iso8601.time(includingFractionalSeconds: false).timeZone(separator: .colon).format(componentsInGMT), "15:35:46Z") - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(iso8601.timeZone(separator: .colon).time(includingFractionalSeconds: false).timeSeparator(.colon).format(componentsInGMT), "15:35:46Z") - - // Time zones - - var iso8601Pacific = iso8601 - let pacificTimeZone = TimeZone(secondsFromGMT: -3600 * 8)! - iso8601Pacific.timeZone = pacificTimeZone - let componentsInPacific = Calendar(identifier: .iso8601).dateComponents(in: pacificTimeZone, from: date) - - XCTAssertEqual(iso8601Pacific.timeSeparator(.omitted).format(componentsInPacific), "2022-01-28T073546-0800") - XCTAssertEqual(iso8601Pacific.timeSeparator(.omitted).timeZoneSeparator(.colon).format(componentsInPacific), "2022-01-28T073546-08:00") - - // Has a seconds component (-28830) - var iso8601PacificIsh = iso8601 - let pacificIshTimeZone = TimeZone(secondsFromGMT: -3600 * 8 - 30)! - iso8601PacificIsh.timeZone = pacificIshTimeZone - let componentsInPacificIsh = Calendar(identifier: .iso8601).dateComponents(in: pacificIshTimeZone, from: date) - - XCTAssertEqual(iso8601PacificIsh.timeSeparator(.omitted).format(componentsInPacificIsh), "2022-01-28T073516-080030") - XCTAssertEqual(iso8601PacificIsh.timeSeparator(.omitted).timeZoneSeparator(.colon).format(componentsInPacificIsh), "2022-01-28T073516-08:00:30") - - var iso8601gmtP1 = iso8601 - let gmtP1TimeZone = TimeZone(secondsFromGMT: 3600)! - iso8601gmtP1.timeZone = gmtP1TimeZone - let componentsInGMTP1 = Calendar(identifier: .iso8601).dateComponents(in: gmtP1TimeZone, from: date) - XCTAssertEqual(iso8601gmtP1.timeSeparator(.omitted).format(componentsInGMTP1), "2022-01-28T163546+0100") - XCTAssertEqual(iso8601gmtP1.timeSeparator(.omitted).timeZoneSeparator(.colon).format(componentsInGMTP1), "2022-01-28T163546+01:00") - } - - func test_codable() { - let iso8601Style = Date.ISO8601FormatStyle().year().month().day() - let encoder = JSONEncoder() - let encodedStyle = try! encoder.encode(iso8601Style) - let decoder = JSONDecoder() - let decodedStyle = try? decoder.decode(Date.ISO8601FormatStyle.self, from: encodedStyle) - XCTAssertNotNil(decodedStyle) - } - - func testLeadingDotSyntax() { - let _ = Date().formatted(.iso8601) - } - - func test_ISO8601FormatWithDate() throws { - // dateFormatter.date(from: "2021-07-01 15:56:32")! - let date = Date(timeIntervalSinceReferenceDate: 646847792.0) // Thursday - XCTAssertEqual(date.formatted(.iso8601), "2021-07-01T15:56:32Z") - XCTAssertEqual(date.formatted(.iso8601.dateSeparator(.omitted)), "20210701T15:56:32Z") - XCTAssertEqual(date.formatted(.iso8601.dateTimeSeparator(.space)), "2021-07-01 15:56:32Z") - XCTAssertEqual(date.formatted(.iso8601.timeSeparator(.omitted)), "2021-07-01T155632Z") - XCTAssertEqual(date.formatted(.iso8601.dateSeparator(.omitted).timeSeparator(.omitted)), "20210701T155632Z") - XCTAssertEqual(date.formatted(.iso8601.year().month().day().time(includingFractionalSeconds: false).timeZone(separator: .omitted)), "2021-07-01T15:56:32Z") - XCTAssertEqual(date.formatted(.iso8601.year().month().day().time(includingFractionalSeconds: true).timeZone(separator: .omitted).dateSeparator(.dash).dateTimeSeparator(.standard).timeSeparator(.colon)), "2021-07-01T15:56:32.000Z") - - XCTAssertEqual(date.formatted(.iso8601.year()), "2021") - XCTAssertEqual(date.formatted(.iso8601.year().month()), "2021-07") - XCTAssertEqual(date.formatted(.iso8601.year().month().day()), "2021-07-01") - XCTAssertEqual(date.formatted(.iso8601.year().month().day().dateSeparator(.omitted)), "20210701") - - XCTAssertEqual(date.formatted(.iso8601.year().weekOfYear()), "2021-W26") - XCTAssertEqual(date.formatted(.iso8601.year().weekOfYear().day()), "2021-W26-04") // day() is the weekday number - XCTAssertEqual(date.formatted(.iso8601.year().day()), "2021-182") // day() is the ordinal day - - XCTAssertEqual(date.formatted(.iso8601.time(includingFractionalSeconds: false)), "15:56:32") - XCTAssertEqual(date.formatted(.iso8601.time(includingFractionalSeconds: true)), "15:56:32.000") - XCTAssertEqual(date.formatted(.iso8601.time(includingFractionalSeconds: false).timeZone(separator: .omitted)), "15:56:32Z") - } - - func test_remoteDate() throws { - let date = Date(timeIntervalSince1970: 999999999999.0) // Remote date - XCTAssertEqual(date.formatted(.iso8601), "33658-09-27T01:46:39Z") - XCTAssertEqual(date.formatted(.iso8601.year().weekOfYear().day()), "33658-W39-05") // day() is the weekday number - } - - func test_internal_formatDateComponents() throws { - let dc = DateComponents(year: -2025, month: 1, day: 20, hour: 0, minute: 0, second: 0) - let str = Date.ISO8601FormatStyle().format(dc, appendingTimeZoneOffset: 0) - XCTAssertEqual(str, "-2025-01-20T00:00:00Z") - } - - func test_rounding() { - // Date is: "1970-01-01 15:35:45.9999" - let date = Date(timeIntervalSinceReferenceDate: -978251054.0 - 0.0001) - let str = Date.ISO8601FormatStyle().timeZone(separator: .colon).time(includingFractionalSeconds: true).timeSeparator(.colon).format(date) - XCTAssertEqual(str, "15:35:45.999Z") - } -} diff --git a/Tests/FoundationEssentialsTests/Formatting/ISO8601FormatStyleParsingTests.swift b/Tests/FoundationEssentialsTests/Formatting/ISO8601FormatStyleParsingTests.swift deleted file mode 100644 index 2c728093a..000000000 --- a/Tests/FoundationEssentialsTests/Formatting/ISO8601FormatStyleParsingTests.swift +++ /dev/null @@ -1,504 +0,0 @@ -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(FoundationEssentials) -@testable import FoundationEssentials -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#endif - -final class ISO8601FormatStyleParsingTests: XCTestCase { - - /// See also the format-only tests in DateISO8601FormatStyleEssentialsTests - func test_ISO8601Parse() throws { - let iso8601 = Date.ISO8601FormatStyle() - - // Date is: "2022-01-28 15:35:46" - XCTAssertEqual(try? iso8601.parse("2022-01-28T15:35:46Z"), Date(timeIntervalSinceReferenceDate: 665076946.0)) - - var iso8601Pacific = iso8601 - iso8601Pacific.timeZone = TimeZone(secondsFromGMT: -3600 * 8)! - XCTAssertEqual(try? iso8601Pacific.timeSeparator(.omitted).parse("2022-01-28T073546-0800"), Date(timeIntervalSinceReferenceDate: 665076946.0)) - - // Day-only results: the default time is midnight for parsed date when the time piece is missing - // Date is: "2022-01-28 00:00:00" - XCTAssertEqual(try? iso8601.year().month().day().dateSeparator(.dash).parse("2022-01-28"), Date(timeIntervalSinceReferenceDate: 665020800.0)) - // Date is: "2022-01-28 00:00:00" - XCTAssertEqual(try? iso8601.year().month().day().dateSeparator(.omitted).parse("20220128"), Date(timeIntervalSinceReferenceDate: 665020800.0)) - - // Time-only results: we use the default date of the format style, 1970-01-01, to supplement the parsed date without year, month or day - // Date is: "1970-01-23 00:00:00" - XCTAssertEqual(try? iso8601.weekOfYear().day().dateSeparator(.dash).parse("W04-05"), Date(timeIntervalSinceReferenceDate: -976406400.0)) - // Date is: "1970-01-28 15:35:46" - XCTAssertEqual(try? iso8601.day().time(includingFractionalSeconds: false).timeSeparator(.colon).parse("028T15:35:46"), Date(timeIntervalSinceReferenceDate: -975918254.0)) - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(try? iso8601.time(includingFractionalSeconds: false).timeSeparator(.colon).parse("15:35:46"), Date(timeIntervalSinceReferenceDate: -978251054.0)) - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(try? iso8601.time(includingFractionalSeconds: false).timeZone(separator: .omitted).parse("15:35:46Z"), Date(timeIntervalSinceReferenceDate: -978251054.0)) - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(try? iso8601.time(includingFractionalSeconds: false).timeZone(separator: .colon).parse("15:35:46Z"), Date(timeIntervalSinceReferenceDate: -978251054.0)) - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(try? iso8601.timeZone(separator: .colon).time(includingFractionalSeconds: false).timeSeparator(.colon).parse("15:35:46Z"), Date(timeIntervalSinceReferenceDate: -978251054.0)) - } - - func test_ISO8601ParseComponents_fromString() throws { - let components = try DateComponents.ISO8601FormatStyle().parse("2022-01-28T15:35:46Z") - XCTAssertEqual(components, DateComponents(calendar: Calendar(identifier: .iso8601), timeZone: .gmt, year: 2022, month: 1, day: 28, hour: 15, minute: 35, second: 46)) - XCTAssertNotNil(components.date) - } - - func test_ISO8601ParseComponents_missingComponents() throws { - // Default style requires time - XCTAssertThrowsError(try DateComponents.ISO8601FormatStyle().parse("2022-01-28")) - } - - /// See also the format-only tests in DateISO8601FormatStyleEssentialsTests - func test_ISO8601ParseComponents() throws { - let iso8601 = DateComponents.ISO8601FormatStyle() - - // Date is: "2022-01-28 15:35:46" - XCTAssertEqual(try? iso8601.parse("2022-01-28T15:35:46Z"), DateComponents(calendar: Calendar(identifier: .iso8601), timeZone: .gmt, year: 2022, month: 1, day: 28, hour: 15, minute: 35, second: 46)) - - var iso8601Pacific = iso8601 - let tz = TimeZone(secondsFromGMT: -3600 * 8)! - iso8601Pacific.timeZone = tz - XCTAssertEqual(try? iso8601Pacific.timeSeparator(.omitted).parse("2022-01-28T073546-0800"), DateComponents(calendar: Calendar(identifier: .iso8601), timeZone: tz, year: 2022, month: 1, day: 28, hour: 7, minute: 35, second: 46)) - - // Day-only results: the default time is midnight for parsed date when the time piece is missing - // Date is: "2022-01-28 00:00:00" - XCTAssertEqual(try? iso8601.year().month().day().dateSeparator(.dash).parse("2022-01-28"), DateComponents(calendar: Calendar(identifier: .iso8601), timeZone: .gmt, year: 2022, month: 1, day: 28)) - // Date is: "2022-01-28 00:00:00" - XCTAssertEqual(try? iso8601.year().month().day().dateSeparator(.omitted).parse("20220128"), DateComponents(calendar: Calendar(identifier: .iso8601), timeZone: .gmt, year: 2022, month: 1, day: 28)) - - // Time-only results: we use the default date of the format style, 1970-01-01, to supplement the parsed date without year, month or day - // Date is: "1970-01-23 00:00:00" - // note: weekday as understood by Calendar is not the same integer value as the one in the ISO8601 format - XCTAssertEqual(try? iso8601.weekOfYear().day().dateSeparator(.dash).parse("W04-05"), DateComponents(calendar: Calendar(identifier: .iso8601), timeZone: .gmt, weekday: 6, weekOfYear: 4)) - // Date is: "1970-01-28 15:35:46" - var expectedWithDayOfYear = DateComponents(calendar: Calendar(identifier: .iso8601), timeZone: .gmt, hour: 15, minute: 35, second: 46) - expectedWithDayOfYear.dayOfYear = 28 - XCTAssertEqual(try? iso8601.day().time(includingFractionalSeconds: false).timeSeparator(.colon).parse("028T15:35:46"), expectedWithDayOfYear) - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(try? iso8601.time(includingFractionalSeconds: false).timeSeparator(.colon).parse("15:35:46"), DateComponents(calendar: Calendar(identifier: .iso8601), timeZone: .gmt, hour: 15, minute: 35, second: 46)) - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(try? iso8601.time(includingFractionalSeconds: false).timeZone(separator: .omitted).parse("15:35:46Z"), DateComponents(calendar: Calendar(identifier: .iso8601), timeZone: .gmt, hour: 15, minute: 35, second: 46)) - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(try? iso8601.time(includingFractionalSeconds: false).timeZone(separator: .colon).parse("15:35:46Z"), DateComponents(calendar: Calendar(identifier: .iso8601), timeZone: .gmt, hour: 15, minute: 35, second: 46)) - // Date is: "1970-01-01 15:35:46" - XCTAssertEqual(try? iso8601.timeZone(separator: .colon).time(includingFractionalSeconds: false).timeSeparator(.colon).parse("15:35:46Z"), DateComponents(calendar: Calendar(identifier: .iso8601), timeZone: .gmt, hour: 15, minute: 35, second: 46)) - } - - func test_ISO8601FractionalSecondsAreOptional() { - let iso8601 = Date.ISO8601FormatStyle() - let iso8601WithFraction = Date.ISO8601FormatStyle(includingFractionalSeconds: true) - - let str = "2022-01-28T15:35:46Z" - let strWithFraction = "2022-01-28T15:35:46.123Z" - - XCTAssertNotNil(try? iso8601.parse(str)) - XCTAssertNotNil(try? iso8601.parse(strWithFraction)) - - XCTAssertNotNil(try? iso8601WithFraction.parse(str)) - XCTAssertNotNil(try? iso8601WithFraction.parse(strWithFraction)) - } - - func test_weekOfYear() throws { - let iso8601 = Date.ISO8601FormatStyle() - - // Test some dates around the 2019 - 2020 end of year, and 2026 which has W53 - let dates = [ - ("2019-W52-07", "2019-12-29"), - ("2020-W01-01", "2019-12-30"), - ("2020-W01-02", "2019-12-31"), - ("2020-W01-03", "2020-01-01"), - ("2026-W53-01", "2026-12-28"), - ("2026-W53-02", "2026-12-29"), - ("2026-W53-03", "2026-12-30"), - ("2026-W53-04", "2026-12-31"), - ("2026-W53-05", "2027-01-01"), - ("2026-W53-06", "2027-01-02"), - ("2026-W53-07", "2027-01-03"), - ("2027-W01-01", "2027-01-04"), - ("2027-W01-02", "2027-01-05") - ] - - for d in dates { - let parsedWoY = try iso8601.year().weekOfYear().day().parse(d.0) - let parsedY = try iso8601.year().month().day().parse(d.1) - XCTAssertEqual(parsedWoY, parsedY) - } - } - - func test_zeroLeadingDigits() { - // The parser allows for an arbitrary number of 0 pads in digits, including none. - let iso8601 = Date.ISO8601FormatStyle() - - // Date is: "2022-01-28 15:35:46" - XCTAssertEqual(try? iso8601.parse("2022-01-28T15:35:46Z"), Date(timeIntervalSinceReferenceDate: 665076946.0)) - XCTAssertEqual(try? iso8601.parse("002022-01-28T15:35:46Z"), Date(timeIntervalSinceReferenceDate: 665076946.0)) - XCTAssertEqual(try? iso8601.parse("2022-0001-28T15:35:46Z"), Date(timeIntervalSinceReferenceDate: 665076946.0)) - XCTAssertEqual(try? iso8601.parse("2022-01-0028T15:35:46Z"), Date(timeIntervalSinceReferenceDate: 665076946.0)) - XCTAssertEqual(try? iso8601.parse("2022-1-28T15:35:46Z"), Date(timeIntervalSinceReferenceDate: 665076946.0)) - XCTAssertEqual(try? iso8601.parse("2022-01-28T15:35:06Z"), Date(timeIntervalSinceReferenceDate: 665076906.0)) - XCTAssertEqual(try? iso8601.parse("2022-01-28T15:35:6Z"), Date(timeIntervalSinceReferenceDate: 665076906.0)) - XCTAssertEqual(try? iso8601.parse("2022-01-28T15:05:46Z"), Date(timeIntervalSinceReferenceDate: 665075146.0)) - XCTAssertEqual(try? iso8601.parse("2022-01-28T15:5:46Z"), Date(timeIntervalSinceReferenceDate: 665075146.0)) - } - - func test_timeZones() { - let iso8601 = Date.ISO8601FormatStyle() - let date = Date(timeIntervalSinceReferenceDate: 665076946.0) - - var iso8601Pacific = iso8601 - iso8601Pacific.timeZone = TimeZone(secondsFromGMT: -3600 * 8)! - - // Has a seconds component (-28830) - var iso8601PacificIsh = iso8601 - iso8601PacificIsh.timeZone = TimeZone(secondsFromGMT: -3600 * 8 - 30)! - - XCTAssertEqual(try? iso8601Pacific.timeSeparator(.omitted).parse("2022-01-28T073546-0800"), date) - XCTAssertEqual(try? iso8601Pacific.timeSeparator(.omitted).timeZoneSeparator(.colon).parse("2022-01-28T073546-08:00"), date) - - XCTAssertEqual(try? iso8601PacificIsh.timeSeparator(.omitted).parse("2022-01-28T073516-080030"), date) - XCTAssertEqual(try? iso8601PacificIsh.timeSeparator(.omitted).timeZoneSeparator(.colon).parse("2022-01-28T073516-08:00:30"), date) - - var iso8601gmtP1 = iso8601 - iso8601gmtP1.timeZone = TimeZone(secondsFromGMT: 3600)! - XCTAssertEqual(try? iso8601gmtP1.timeSeparator(.omitted).parse("2022-01-28T163546+0100"), date) - XCTAssertEqual(try? iso8601gmtP1.timeSeparator(.omitted).parse("2022-01-28T163546+010000"), date) - XCTAssertEqual(try? iso8601gmtP1.timeSeparator(.omitted).timeZoneSeparator(.colon).parse("2022-01-28T163546+01:00"), date) - XCTAssertEqual(try? iso8601gmtP1.timeSeparator(.omitted).timeZoneSeparator(.colon).parse("2022-01-28T163546+01:00:00"), date) - - // Due to a quirk of the original implementation, colons are allowed to be present in the time zone even if the time zone separator is omitted - XCTAssertEqual(try? iso8601gmtP1.timeSeparator(.omitted).parse("2022-01-28T163546+01:00"), date) - XCTAssertEqual(try? iso8601gmtP1.timeSeparator(.omitted).parse("2022-01-28T163546+01:00:00"), date) - } - - func test_fractionalSeconds() throws { - let expectedDate = Date(timeIntervalSinceReferenceDate: 646876592.34567) - var iso8601 = Date.ISO8601FormatStyle().year().month().day().time(includingFractionalSeconds: true) - iso8601.timeZone = .gmt - - let parsedWithFraction = try XCTUnwrap(try iso8601.parse("2021-07-01T23:56:32.34567")) - let parsedWithoutFraction = try XCTUnwrap(try iso8601.parse("2021-07-01T23:56:32")) - - let parsedWithFraction1 = try XCTUnwrap(try iso8601.parse("2021-07-01T23:56:32.3")) - let parsedWithFraction2 = try XCTUnwrap(try iso8601.parse("2021-07-01T23:56:32.34")) - let parsedWithFraction3 = try XCTUnwrap(try iso8601.parse("2021-07-01T23:56:32.345")) - let parsedWithFraction4 = try XCTUnwrap(try iso8601.parse("2021-07-01T23:56:32.3456")) - - XCTAssertEqual(parsedWithoutFraction.timeIntervalSinceReferenceDate, expectedDate.timeIntervalSinceReferenceDate, accuracy: 1.0) - - // More accurate due to inclusion of fraction - XCTAssertEqual(parsedWithFraction.timeIntervalSinceReferenceDate, expectedDate.timeIntervalSinceReferenceDate, accuracy: 0.01) - XCTAssertEqual(parsedWithFraction1.timeIntervalSinceReferenceDate, expectedDate.timeIntervalSinceReferenceDate, accuracy: 0.1) - XCTAssertEqual(parsedWithFraction2.timeIntervalSinceReferenceDate, expectedDate.timeIntervalSinceReferenceDate, accuracy: 0.1) - XCTAssertEqual(parsedWithFraction3.timeIntervalSinceReferenceDate, expectedDate.timeIntervalSinceReferenceDate, accuracy: 0.1) - XCTAssertEqual(parsedWithFraction4.timeIntervalSinceReferenceDate, expectedDate.timeIntervalSinceReferenceDate, accuracy: 0.1) - } - - func test_specialTimeZonesAndSpaces() { - let reference = try! Date("2020-03-05T12:00:00+00:00", strategy: .iso8601) - - let tests : [(String, Date.ISO8601FormatStyle)] = [ - ("2020-03-05T12:00:00+00:00", Date.ISO8601FormatStyle()), - ("2020-03-05T12:00:00+0000", Date.ISO8601FormatStyle()), - ("2020-03-05T12:00:00GMT", Date.ISO8601FormatStyle()), - ("2020-03-05T12:00:00UTC", Date.ISO8601FormatStyle()), - ("2020-03-05T11:00:00-01:00", Date.ISO8601FormatStyle().year().month().day().time(includingFractionalSeconds: false).timeSeparator(.colon).timeZone(separator: .colon)), - ("2020-03-05T12:00:00Z", Date.ISO8601FormatStyle().year().month().day().time(includingFractionalSeconds: false).timeSeparator(.colon).timeZone(separator: .colon)), // allow Z - ("2020-03-05T12:00:00z", Date.ISO8601FormatStyle().year().month().day().time(includingFractionalSeconds: false).timeSeparator(.colon).timeZone(separator: .colon)), // allow z - ("2020-03-05T12:00:00UTC", Date.ISO8601FormatStyle().year().month().day().time(includingFractionalSeconds: false).timeSeparator(.colon).timeZone(separator: .colon)), // allow UTC - ("2020-03-05T12:00:00GMT", Date.ISO8601FormatStyle().year().month().day().time(includingFractionalSeconds: false).timeSeparator(.colon).timeZone(separator: .colon)), // allow GMT - ("2020-03-05T13:00:00UTC+1:00", Date.ISO8601FormatStyle().year().month().day().time(includingFractionalSeconds: false).timeSeparator(.colon).timeZone(separator: .colon)), // allow UTC offsets - ("2020-03-05T13:00:00UTC+01", Date.ISO8601FormatStyle().year().month().day().time(includingFractionalSeconds: false).timeSeparator(.colon).timeZone(separator: .colon)), // allow hours-only (2 digit) - ("2020-03-05T11:00:00GMT-1:00", Date.ISO8601FormatStyle().year().month().day().time(includingFractionalSeconds: false).timeSeparator(.colon).timeZone(separator: .colon)), // allow GMT offsets - ("2020-03-05 12:00:00+0000", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .omitted)), - ("2020-03-05 11:00:00-0100", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .omitted)), - ("2020-03-05 11:00:00-0100", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .omitted)), // spaces allowed between date/time and time - ("2020-03-05 11:00:00 -0100", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .omitted)), // spaces allowed between date/time and time/timeZone - ("2020-03-05 11:00:00 -0100", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .omitted)), // spaces allowed between date/time and time/timeZone - ("2020-03-05 10:30:00 -0130", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .omitted)), // spaces allowed between date/time and time/timeZone - half hour offset - ("2020-03-05 10:30:00 -0130", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .colon)), // separator can be colon, or missing - ("2020-03-05 12:00:00 GMT", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .colon)), // spaces between time zone and GMT - ("2020-03-05 11:00:00 GMT-0100", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .colon)), // spaces between time zone and GMT, GMT has offset - ("2020-03-05 11:00:00 gMt-0100", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .colon)), // spaces between time zone and GMT, GMT has offset, GMT has different capitalization - ("2020-03-05 12:00:00 GMT -0100", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .colon)), // spaces after GMT cause rest of time to be ignored (note here time of 12:00:00 instead of 11:00:00) - ("2020-03-05 12:00:00 GMT +0100", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .colon)), // spaces after GMT cause rest of time to be ignored (note here time of 12:00:00 instead of 11:00:00) - ("2020-03-05 12:00:00 Z +0100", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .colon)), // values after Z are ignored, spaces - ("2020-03-05 12:00:00 Z+0100", Date.ISO8601FormatStyle().year().month().day().dateTimeSeparator(.space).time(includingFractionalSeconds: false).timeZone(separator: .colon)), // values after Z are ignored, no spaces - ] - - for (parseMe, style) in tests { - let parsed = try? style.parse(parseMe) - XCTAssertEqual(parsed, reference, """ - -parsing : \(parseMe) -expected: \(reference) \(reference.timeIntervalSinceReferenceDate) -result : \(parsed != nil ? parsed!.debugDescription : "nil") \(parsed != nil ? parsed!.timeIntervalSinceReferenceDate : 0) -""") - } - } - -#if canImport(FoundationInternationalization) || FOUNDATION_FRAMEWORK - func test_chileTimeZone() { - var iso8601Chile = Date.ISO8601FormatStyle().year().month().day() - iso8601Chile.timeZone = TimeZone(name: "America/Santiago")! - - let date = try? iso8601Chile.parse("2023-09-03") - XCTAssertNotNil(date) - } -#endif -} - -final class DateISO8601FormatStylePatternMatchingTests : XCTestCase { - - func _matchFullRange(_ str: String, formatStyle: Date.ISO8601FormatStyle, expectedUpperBound: String.Index?, expectedDate: Date?, file: StaticString = #filePath, line: UInt = #line) { - _matchRange(str, formatStyle: formatStyle, range: nil, expectedUpperBound: expectedUpperBound, expectedDate: expectedDate, file: file, line: line) - } - - func _matchFullRange(_ str: String, formatStyle: DateComponents.ISO8601FormatStyle, expectedUpperBound: String.Index?, expectedDateComponents: DateComponents?, file: StaticString = #filePath, line: UInt = #line) { - _matchRange(str, formatStyle: formatStyle, range: nil, expectedUpperBound: expectedUpperBound, expectedDateComponents: expectedDateComponents, file: file, line: line) - } - - func _matchRange(_ str: String, formatStyle: Date.ISO8601FormatStyle, range: Range?, expectedUpperBound: String.Index?, expectedDate: Date?, file: StaticString = #filePath, line: UInt = #line) { - // FIXME: Need tests that starts from somewhere else - let m = try? formatStyle.consuming(str, startingAt: str.startIndex, in: range ?? str.startIndex..?, expectedUpperBound: String.Index?, expectedDateComponents: DateComponents?, file: StaticString = #filePath, line: UInt = #line) { - // FIXME: Need tests that starts from somewhere else - let m = try? formatStyle.consuming(str, startingAt: str.startIndex, in: range ?? str.startIndex.. 1978-10-01 00:00 +0100 (DST, rewinds back to the start of the day in the same time zone) - let date = Date(timeIntervalSinceReferenceDate: -702180000) // 1978-10-01T23:00:00+0100 - testAdding(.init(hour: 1), to: date, wrap: true, expected: Date(timeIntervalSinceReferenceDate: -702266400.0)) - } - - do { - gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - let date = Date(timeIntervalSinceReferenceDate: 2557249259.5) // 2082-1-13 19:00:59.5 +0000 - testAdding(.init(day: 1), to: date, wrap: true, expected: Date(timeIntervalSinceReferenceDate: 2557335659.5)) - - let date2 = Date(timeIntervalSinceReferenceDate: 0) // 2000-12-31 16:00:00 PT - testAdding(.init(month: 2), to: date2, wrap: false, expected: Date(timeIntervalSince1970: 983404800)) // 2001-03-01 00:00:00 UTC, 2001-02-28 16:00:00 PT - } - } - - func testAddDateComponents_DST() { - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(identifier: "America/Los_Angeles")!, locale: nil, firstWeekday: 2, minimumDaysInFirstWeek: 4, gregorianStartDate: nil) - - func testAdding(_ comp: DateComponents, to date: Date, wrap: Bool, expected: Date, _ file: StaticString = #filePath, _ line: UInt = #line) { - let result = gregorianCalendar.date(byAdding: comp, to: date, wrappingComponents: wrap)! - XCTAssertEqual(result, expected, "result = \(result.timeIntervalSince1970)" , file: file, line: line) - } - - // 1996-03-01 23:35:00 UTC, 1996-03-01T15:35:00-0800 - let march1_1996 = Date(timeIntervalSince1970: 825723300) - testAdding(.init(day: -1, hour: 1), to: march1_1996, wrap: false, expected: Date(timeIntervalSince1970: 825640500.0)) - testAdding(.init(month: -1, hour: 1), to: march1_1996, wrap: false, expected: Date(timeIntervalSince1970: 823221300.0)) - testAdding(.init(month: -1, day: 30), to: march1_1996, wrap: false, expected: Date(timeIntervalSince1970: 825809700.0)) - testAdding(.init(year: 4, day: -1), to: march1_1996, wrap: false, expected: Date(timeIntervalSince1970: 951867300.0)) - testAdding(.init(day: -1, hour: 24), to: march1_1996, wrap: false, expected: Date(timeIntervalSince1970: 825723300.0)) - testAdding(.init(day: -1, weekday: 1), to: march1_1996, wrap: false, expected: Date(timeIntervalSince1970: 825723300.0)) - testAdding(.init(day: -7, weekOfYear: 1), to: march1_1996, wrap: false, expected: Date(timeIntervalSince1970: 825723300.0)) - testAdding(.init(day: -7, weekOfMonth: 1), to: march1_1996, wrap: false, expected: Date(timeIntervalSince1970: 825723300.0)) - testAdding(.init(day: -7, weekOfMonth: 1, weekOfYear: 1), to: march1_1996, wrap: false, expected: Date(timeIntervalSince1970: 826328100.0)) - - testAdding(.init(day: -1, hour: 1), to: march1_1996, wrap: true, expected: Date(timeIntervalSince1970: 828318900.0)) - testAdding(.init(month: -1, hour: 1), to: march1_1996, wrap: true, expected: Date(timeIntervalSince1970: 823221300.0)) - testAdding(.init(month: -1, day: 30), to: march1_1996, wrap: true, expected: Date(timeIntervalSince1970: 823304100.0)) - testAdding(.init(year: 4, day: -1), to: march1_1996, wrap: true, expected: Date(timeIntervalSince1970: 954545700.0)) - testAdding(.init(day: -1, hour: 24), to: march1_1996, wrap: true, expected: Date(timeIntervalSince1970: 828315300.0)) - testAdding(.init(day: -1, weekday: 1), to: march1_1996, wrap: true, expected: Date(timeIntervalSince1970: 827796900.0)) - testAdding(.init(day: -7, weekOfYear: 1), to: march1_1996, wrap: true, expected: march1_1996) - testAdding(.init(day: -7, weekOfMonth: 1), to: march1_1996, wrap: true, expected: march1_1996) - - testAdding(.init(day: -7, weekOfYear: 2), to: march1_1996, wrap: true, expected: Date(timeIntervalSince1970: 826328100.0)) // Expect: 1996-03-08 23:35:00 +0000 - testAdding(.init(day: -7, weekOfMonth: 2), to: march1_1996, wrap: true, expected: Date(timeIntervalSince1970: 826328100.0)) // Expect: 1996-03-08 23:35:00 +0000 - } - - func testAddDateComponents_DSTBoundaries() { - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(identifier: "America/Los_Angeles")!, locale: nil, firstWeekday: 3, minimumDaysInFirstWeek: 5, gregorianStartDate: nil) - - let fmt = Date.ISO8601FormatStyle(timeZone: gregorianCalendar.timeZone) - func testAdding(_ comp: DateComponents, to date: Date, expected: Date, _ file: StaticString = #filePath, _ line: UInt = #line) { - let result = gregorianCalendar.date(byAdding: comp, to: date, wrappingComponents: false)! - XCTAssertEqual(result, expected, "result: \(fmt.format(result)); expected: \(fmt.format(expected))", file: file, line: line) - } - - var date: Date - date = Date(timeIntervalSince1970: 814950000.0) // 1995-10-29T00:00:00-0700 - - // second equivalent - testAdding(.init(second: 1), to: date, expected: Date(timeIntervalSince1970: 814950001.0)) - testAdding(.init(minute: 60, second: -59), to: date, expected: Date(timeIntervalSince1970: 814953541.0)) - testAdding(.init(hour: 1, second: -59), to: date, expected: Date(timeIntervalSince1970: 814953541.0)) - testAdding(.init(hour: 2, minute: -59, second: -59), to: date, expected: Date(timeIntervalSince1970: 814953601.0)) - testAdding(.init(second: -1), to: date, expected: Date(timeIntervalSince1970: 814949999.0)) - testAdding(.init(minute: -60, second: 59), to: date, expected: Date(timeIntervalSince1970: 814946459.0)) - testAdding(.init(hour: -1, second: 59), to: date, expected: Date(timeIntervalSince1970: 814946459.0)) - testAdding(.init(hour: -2, minute: 59, second: 59), to: date, expected: Date(timeIntervalSince1970: 814946399.0)) - - // minute equivalent - testAdding(.init(minute: 1), to: date, expected: Date(timeIntervalSince1970: 814950060.0)) - testAdding(.init(second: 60), to: date, expected: Date(timeIntervalSince1970: 814950060.0)) - testAdding(.init(hour: 1, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814950060.0)) - testAdding(.init(day: 1, hour: -23, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(minute: -1), to: date, expected: Date(timeIntervalSince1970: 814949940.0)) - testAdding(.init(second: -60), to: date, expected: Date(timeIntervalSince1970: 814949940.0)) - testAdding(.init(hour: -1, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814949940.0)) - testAdding(.init(day: -1, hour: 23, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814949940.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815558400.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 815558400.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 815558400.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 819187200.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815558400.0)) - - date = Date(timeIntervalSince1970: 814953540.0) // 1995-10-29T00:59:00-0700 - - // second equivalent - testAdding(.init(second: 1), to: date, expected: Date(timeIntervalSince1970: 814953541.0)) - testAdding(.init(minute: 60, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957081.0)) - testAdding(.init(hour: 1, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957081.0)) - testAdding(.init(hour: 2, minute: -59, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957141.0)) - testAdding(.init(second: -1), to: date, expected: Date(timeIntervalSince1970: 814953539.0)) - testAdding(.init(minute: -60, second: 59), to: date, expected: Date(timeIntervalSince1970: 814949999.0)) - testAdding(.init(hour: -1, second: 59), to: date, expected: Date(timeIntervalSince1970: 814949999.0)) - testAdding(.init(hour: -2, minute: 59, second: 59), to: date, expected: Date(timeIntervalSince1970: 814949939.0)) - - // minute equivalent - testAdding(.init(minute: 1), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(second: 60), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(hour: 1, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(day: 1, hour: -23, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814957200.0)) - testAdding(.init(minute: -1), to: date, expected: Date(timeIntervalSince1970: 814953480.0)) - testAdding(.init(second: -60), to: date, expected: Date(timeIntervalSince1970: 814953480.0)) - testAdding(.init(hour: -1, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814953480.0)) - testAdding(.init(day: -1, hour: 23, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814953480.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815561940.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 815561940.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 815561940.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 819190740.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815561940.0)) - - date = Date(timeIntervalSince1970: 814953599.0) // 1995-10-29T00:59:59-0700 - - // second equivalent - testAdding(.init(second: 1), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(minute: 60, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957140.0)) - testAdding(.init(hour: 1, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957140.0)) - testAdding(.init(hour: 2, minute: -59, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957200.0)) - testAdding(.init(second: -1), to: date, expected: Date(timeIntervalSince1970: 814953598.0)) - testAdding(.init(minute: -60, second: 59), to: date, expected: Date(timeIntervalSince1970: 814950058.0)) - testAdding(.init(hour: -1, second: 59), to: date, expected: Date(timeIntervalSince1970: 814950058.0)) - testAdding(.init(hour: -2, minute: 59, second: 59), to: date, expected: Date(timeIntervalSince1970: 814949998.0)) - - // minute equivalent - testAdding(.init(minute: 1), to: date, expected: Date(timeIntervalSince1970: 814953659.0)) - testAdding(.init(second: 60), to: date, expected: Date(timeIntervalSince1970: 814953659.0)) - testAdding(.init(hour: 1, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814953659.0)) - testAdding(.init(day: 1, hour: -23, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814957259.0)) - testAdding(.init(minute: -1), to: date, expected: Date(timeIntervalSince1970: 814953539.0)) - testAdding(.init(second: -60), to: date, expected: Date(timeIntervalSince1970: 814953539.0)) - testAdding(.init(hour: -1, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814953539.0)) - testAdding(.init(day: -1, hour: 23, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814953539.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815561999.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 815561999.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 815561999.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 819190799.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815561999.0)) - - date = Date(timeIntervalSince1970: 814953600.0) // 1995-10-29T01:00:00-0700 - - // second equivalent - testAdding(.init(second: 1), to: date, expected: Date(timeIntervalSince1970: 814953601.0)) - testAdding(.init(minute: 60, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957141.0)) - testAdding(.init(hour: 1, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957141.0)) - testAdding(.init(hour: 2, minute: -59, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957201.0)) - testAdding(.init(second: -1), to: date, expected: Date(timeIntervalSince1970: 814953599.0)) - testAdding(.init(minute: -60, second: 59), to: date, expected: Date(timeIntervalSince1970: 814950059.0)) - testAdding(.init(hour: -1, second: 59), to: date, expected: Date(timeIntervalSince1970: 814950059.0)) - testAdding(.init(hour: -2, minute: 59, second: 59), to: date, expected: Date(timeIntervalSince1970: 814949999.0)) - - // minute equivalent - testAdding(.init(minute: 1), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(second: 60), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(hour: 1, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(day: 1, hour: -23, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814957260.0)) - testAdding(.init(minute: -1), to: date, expected: Date(timeIntervalSince1970: 814953540.0)) - testAdding(.init(second: -60), to: date, expected: Date(timeIntervalSince1970: 814953540.0)) - testAdding(.init(hour: -1, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814953540.0)) - testAdding(.init(day: -1, hour: 23, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814953540.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815562000.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 815562000.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 815562000.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 819190800.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815562000.0)) - - date = Date(timeIntervalSince1970: 814953660.0) // 1995-10-29T01:01:00-0700 - - // second equivalent - testAdding(.init(second: 1), to: date, expected: Date(timeIntervalSince1970: 814953661.0)) - testAdding(.init(minute: 60, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957201.0)) - testAdding(.init(hour: 1, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957201.0)) - testAdding(.init(hour: 2, minute: -59, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957261.0)) - testAdding(.init(second: -1), to: date, expected: Date(timeIntervalSince1970: 814953659.0)) - testAdding(.init(minute: -60, second: 59), to: date, expected: Date(timeIntervalSince1970: 814950119.0)) - testAdding(.init(hour: -1, second: 59), to: date, expected: Date(timeIntervalSince1970: 814950119.0)) - testAdding(.init(hour: -2, minute: 59, second: 59), to: date, expected: Date(timeIntervalSince1970: 814950059.0)) - - // minute equivalent - testAdding(.init(minute: 1), to: date, expected: Date(timeIntervalSince1970: 814953720.0)) - testAdding(.init(second: 60), to: date, expected: Date(timeIntervalSince1970: 814953720.0)) - testAdding(.init(hour: 1, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814953720.0)) - testAdding(.init(day: 1, hour: -23, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814957320.0)) - testAdding(.init(minute: -1), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(second: -60), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(hour: -1, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(day: -1, hour: 23, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815562060.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 815562060.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 815562060.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 819190860.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815562060.0)) - - date = Date(timeIntervalSince1970: 814953660.0) // 1995-10-29T01:01:00-0700 - - // hour equivalent - testAdding(.init(hour: 1), to: date, expected: Date(timeIntervalSince1970: 814957260.0)) - testAdding(.init(minute: 60), to: date, expected: Date(timeIntervalSince1970: 814957260.0)) - testAdding(.init(second: 3600), to: date, expected: Date(timeIntervalSince1970: 814957260.0)) - testAdding(.init(hour: 2, minute: -60), to: date, expected: Date(timeIntervalSince1970: 814957260.0)) - testAdding(.init(day: 1, hour: -23), to: date, expected: Date(timeIntervalSince1970: 814960860.0)) - testAdding(.init(day: 1, hour: -22, minute: -60), to: date, expected: Date(timeIntervalSince1970: 814960860.0)) - testAdding(.init(hour: -1), to: date, expected: Date(timeIntervalSince1970: 814950060.0)) - testAdding(.init(minute: -60), to: date, expected: Date(timeIntervalSince1970: 814950060.0)) - testAdding(.init(second: -3600), to: date, expected: Date(timeIntervalSince1970: 814950060.0)) - testAdding(.init(hour: -2, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814950060.0)) - testAdding(.init(day: -1, hour: 23), to: date, expected: Date(timeIntervalSince1970: 814950060.0)) - testAdding(.init(day: -1, hour: 22, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814950060.0)) - - // day equivalent - testAdding(.init(minute: 86400), to: date, expected: Date(timeIntervalSince1970: 820137660.0)) - testAdding(.init(hour: 24), to: date, expected: Date(timeIntervalSince1970: 815040060.0)) - testAdding(.init(day: 1), to: date, expected: Date(timeIntervalSince1970: 815043660.0)) - testAdding(.init(month: 1, day: -30), to: date, expected: Date(timeIntervalSince1970: 815043660.0)) - testAdding(.init(year: 1, month: -11, day: -30), to: date, expected: Date(timeIntervalSince1970: 815043660.0)) - testAdding(.init(weekday: 1), to: date, expected: Date(timeIntervalSince1970: 815043660.0)) - testAdding(.init(day: -1, weekday: 2), to: date, expected: Date(timeIntervalSince1970: 815043660.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815562060.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 815562060.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 815562060.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 819190860.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815562060.0)) - testAdding(.init(yearForWeekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 846403260.0)) - testAdding(.init(weekOfYear: 52), to: date, expected: Date(timeIntervalSince1970: 846403260.0)) - testAdding(.init(weekOfYear: 53), to: date, expected: Date(timeIntervalSince1970: 847011660.0)) - testAdding(.init(yearForWeekOfYear: -1), to: date, expected: Date(timeIntervalSince1970: 783507660.0)) - testAdding(.init(weekOfYear: -52), to: date, expected: Date(timeIntervalSince1970: 783504060.0)) - testAdding(.init(weekOfYear: -53), to: date, expected: Date(timeIntervalSince1970: 782899260.0)) - - date = Date(timeIntervalSince1970: 814957387.0) // 1995-10-29T01:03:07-0800 - - // hour equivalent - testAdding(.init(hour: 1), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(minute: 60), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(second: 3600), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(hour: 2, minute: -60), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(day: 1, hour: -23), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(day: 1, hour: -22, minute: -60), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(hour: -1), to: date, expected: Date(timeIntervalSince1970: 814953787.0)) - testAdding(.init(minute: -60), to: date, expected: Date(timeIntervalSince1970: 814953787.0)) - testAdding(.init(second: -3600), to: date, expected: Date(timeIntervalSince1970: 814953787.0)) - testAdding(.init(hour: -2, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814953787.0)) - testAdding(.init(day: -1, hour: 23), to: date, expected: Date(timeIntervalSince1970: 814950187.0)) - testAdding(.init(day: -1, hour: 22, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814950187.0)) - - // day equivalent - testAdding(.init(minute: 86400), to: date, expected: Date(timeIntervalSince1970: 820141387.0)) - testAdding(.init(hour: 24), to: date, expected: Date(timeIntervalSince1970: 815043787.0)) - testAdding(.init(day: 1), to: date, expected: Date(timeIntervalSince1970: 815043787.0)) - testAdding(.init(month: 1, day: -30), to: date, expected: Date(timeIntervalSince1970: 815043787.0)) - testAdding(.init(year: 1, month: -11, day: -30), to: date, expected: Date(timeIntervalSince1970: 815043787.0)) - testAdding(.init(weekday: 1), to: date, expected: Date(timeIntervalSince1970: 815043787.0)) - testAdding(.init(day: -1, weekday: 2), to: date, expected: Date(timeIntervalSince1970: 815043787.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815562187.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 815562187.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 815562187.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 819190987.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815562187.0)) - testAdding(.init(yearForWeekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 846403387.0)) - // Current result: 1996-10-27T01:03:07-0800 - // Calendar_ICU result: 1996-10-27T01:03:07-0700 - testAdding(.init(weekOfYear: 52), to: date, expected: Date(timeIntervalSince1970: 846403387.0)) - testAdding(.init(weekOfYear: 53), to: date, expected: Date(timeIntervalSince1970: 847011787.0)) - testAdding(.init(yearForWeekOfYear: -1), to: date, expected: Date(timeIntervalSince1970: 783507787.0)) - testAdding(.init(weekOfYear: -52), to: date, expected: Date(timeIntervalSince1970: 783507787.0)) - testAdding(.init(weekOfYear: -53), to: date, expected: Date(timeIntervalSince1970: 782899387.0)) - - date = Date(timeIntervalSince1970: 814960987.0) // 1995-10-29T02:03:07-0800 - - // hour equivalent - testAdding(.init(hour: 1), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(minute: 60), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(second: 3600), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(hour: 2, minute: -60), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(day: 1, hour: -23), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(day: 1, hour: -22, minute: -60), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(hour: -1), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(minute: -60), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(second: -3600), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(hour: -2, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(day: -1, hour: 23), to: date, expected: Date(timeIntervalSince1970: 814953787.0)) - testAdding(.init(day: -1, hour: 22, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814953787.0)) - - // day equivalent - testAdding(.init(minute: 86400), to: date, expected: Date(timeIntervalSince1970: 820144987.0)) - testAdding(.init(hour: 24), to: date, expected: Date(timeIntervalSince1970: 815047387.0)) - testAdding(.init(day: 1), to: date, expected: Date(timeIntervalSince1970: 815047387.0)) - testAdding(.init(month: 1, day: -30), to: date, expected: Date(timeIntervalSince1970: 815047387.0)) - testAdding(.init(year: 1, month: -11, day: -30), to: date, expected: Date(timeIntervalSince1970: 815047387.0)) - testAdding(.init(weekday: 1), to: date, expected: Date(timeIntervalSince1970: 815047387.0)) - testAdding(.init(day: -1, weekday: 2), to: date, expected: Date(timeIntervalSince1970: 815047387.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815565787.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 815565787.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 815565787.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 819194587.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815565787.0)) - testAdding(.init(yearForWeekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 846410587.0)) - testAdding(.init(weekOfYear: 52), to: date, expected: Date(timeIntervalSince1970: 846410587.0)) - testAdding(.init(weekOfYear: 53), to: date, expected: Date(timeIntervalSince1970: 847015387.0)) - testAdding(.init(yearForWeekOfYear: -1), to: date, expected: Date(timeIntervalSince1970: 783511387.0)) - testAdding(.init(weekOfYear: -52), to: date, expected: Date(timeIntervalSince1970: 783511387.0)) - testAdding(.init(weekOfYear: -53), to: date, expected: Date(timeIntervalSince1970: 782902987.0)) - - date = Date(timeIntervalSince1970: 814964587.0) // 1995-10-29T03:03:07-0800 - - // hour equivalent - testAdding(.init(hour: 1), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(minute: 60), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(second: 3600), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(hour: 2, minute: -60), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(day: 1, hour: -23), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(day: 1, hour: -22, minute: -60), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(hour: -1), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(minute: -60), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(second: -3600), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(hour: -2, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(day: -1, hour: 23), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(day: -1, hour: 22, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - - // day equivalent - testAdding(.init(minute: 86400), to: date, expected: Date(timeIntervalSince1970: 820148587.0)) - testAdding(.init(hour: 24), to: date, expected: Date(timeIntervalSince1970: 815050987.0)) - testAdding(.init(day: 1), to: date, expected: Date(timeIntervalSince1970: 815050987.0)) - testAdding(.init(month: 1, day: -30), to: date, expected: Date(timeIntervalSince1970: 815050987.0)) - testAdding(.init(year: 1, month: -11, day: -30), to: date, expected: Date(timeIntervalSince1970: 815050987.0)) - testAdding(.init(weekday: 1), to: date, expected: Date(timeIntervalSince1970: 815050987.0)) - testAdding(.init(day: -1, weekday: 2), to: date, expected: Date(timeIntervalSince1970: 815050987.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815569387.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 815569387.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 815569387.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 819198187.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815569387.0)) - testAdding(.init(yearForWeekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 846414187.0)) - testAdding(.init(weekOfYear: 52), to: date, expected: Date(timeIntervalSince1970: 846414187.0)) - testAdding(.init(weekOfYear: 53), to: date, expected: Date(timeIntervalSince1970: 847018987.0)) - testAdding(.init(yearForWeekOfYear: -1), to: date, expected: Date(timeIntervalSince1970: 783514987.0)) - testAdding(.init(weekOfYear: -52), to: date, expected: Date(timeIntervalSince1970: 783514987.0)) - testAdding(.init(weekOfYear: -53), to: date, expected: Date(timeIntervalSince1970: 782906587.0)) - - date = Date(timeIntervalSince1970: 814780860.0) // 1995-10-27T01:01:00-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815389260.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 815389260.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 815389260.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 819018060.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815389260.0)) - testAdding(.init(year: 1), to: date, expected: Date(timeIntervalSince1970: 846403260.0)) - testAdding(.init(month: 12), to: date, expected: Date(timeIntervalSince1970: 846403260.0)) - testAdding(.init(day: 364), to: date, expected: Date(timeIntervalSince1970: 846230460.0)) - testAdding(.init(day: 365), to: date, expected: Date(timeIntervalSince1970: 846316860.0)) - testAdding(.init(day: 366), to: date, expected: Date(timeIntervalSince1970: 846403260.0)) - testAdding(.init(year: -1), to: date, expected: Date(timeIntervalSince1970: 783244860.0)) - testAdding(.init(month: -12), to: date, expected: Date(timeIntervalSince1970: 783244860.0)) - testAdding(.init(day: -364), to: date, expected: Date(timeIntervalSince1970: 783331260.0)) - testAdding(.init(day: -365), to: date, expected: Date(timeIntervalSince1970: 783244860.0)) - testAdding(.init(day: -366), to: date, expected: Date(timeIntervalSince1970: 783158460.0)) - - date = Date(timeIntervalSince1970: 814784587.0) // 1995-10-27T02:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815392987.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 815392987.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 815392987.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 819021787.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815392987.0)) - testAdding(.init(year: 1), to: date, expected: Date(timeIntervalSince1970: 846410587.0)) - testAdding(.init(month: 12), to: date, expected: Date(timeIntervalSince1970: 846410587.0)) - testAdding(.init(day: 364), to: date, expected: Date(timeIntervalSince1970: 846234187.0)) - testAdding(.init(day: 365), to: date, expected: Date(timeIntervalSince1970: 846320587.0)) - testAdding(.init(day: 366), to: date, expected: Date(timeIntervalSince1970: 846410587.0)) - testAdding(.init(year: -1), to: date, expected: Date(timeIntervalSince1970: 783248587.0)) - testAdding(.init(month: -12), to: date, expected: Date(timeIntervalSince1970: 783248587.0)) - testAdding(.init(day: -364), to: date, expected: Date(timeIntervalSince1970: 783334987.0)) - testAdding(.init(day: -365), to: date, expected: Date(timeIntervalSince1970: 783248587.0)) - testAdding(.init(day: -366), to: date, expected: Date(timeIntervalSince1970: 783162187.0)) - - date = Date(timeIntervalSince1970: 814788187.0) // 1995-10-27T03:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815396587.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 815396587.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 815396587.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 819025387.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815396587.0)) - testAdding(.init(year: 1), to: date, expected: Date(timeIntervalSince1970: 846414187.0)) - testAdding(.init(month: 12), to: date, expected: Date(timeIntervalSince1970: 846414187.0)) - testAdding(.init(day: 364), to: date, expected: Date(timeIntervalSince1970: 846237787.0)) - testAdding(.init(day: 365), to: date, expected: Date(timeIntervalSince1970: 846324187.0)) - testAdding(.init(day: 366), to: date, expected: Date(timeIntervalSince1970: 846414187.0)) - testAdding(.init(year: -1), to: date, expected: Date(timeIntervalSince1970: 783252187.0)) - testAdding(.init(month: -12), to: date, expected: Date(timeIntervalSince1970: 783252187.0)) - testAdding(.init(day: -364), to: date, expected: Date(timeIntervalSince1970: 783338587.0)) - testAdding(.init(day: -365), to: date, expected: Date(timeIntervalSince1970: 783252187.0)) - testAdding(.init(day: -366), to: date, expected: Date(timeIntervalSince1970: 783165787.0)) - - date = Date(timeIntervalSince1970: 814791787.0) // 1995-10-27T04:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815400187.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 815400187.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 815400187.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 819028987.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815400187.0)) - testAdding(.init(year: 1), to: date, expected: Date(timeIntervalSince1970: 846417787.0)) - testAdding(.init(month: 12), to: date, expected: Date(timeIntervalSince1970: 846417787.0)) - testAdding(.init(day: 364), to: date, expected: Date(timeIntervalSince1970: 846241387.0)) - testAdding(.init(day: 365), to: date, expected: Date(timeIntervalSince1970: 846327787.0)) - testAdding(.init(day: 366), to: date, expected: Date(timeIntervalSince1970: 846417787.0)) - testAdding(.init(year: -1), to: date, expected: Date(timeIntervalSince1970: 783255787.0)) - testAdding(.init(month: -12), to: date, expected: Date(timeIntervalSince1970: 783255787.0)) - testAdding(.init(day: -364), to: date, expected: Date(timeIntervalSince1970: 783342187.0)) - testAdding(.init(day: -365), to: date, expected: Date(timeIntervalSince1970: 783255787.0)) - testAdding(.init(day: -366), to: date, expected: Date(timeIntervalSince1970: 783169387.0)) - - date = Date(timeIntervalSince1970: 812358000.0) // 1995-09-29T00:00:00-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 812962800.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812962800.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 812962800.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 816595200.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 812962800.0)) - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 815040000.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814777200.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815385600.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814777200.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815385600.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809679600.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 809766000.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 809679600.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 809938800.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 809334000.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 809938800.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809334000.0)) - - date = Date(timeIntervalSince1970: 812361600.0) // 1995-09-29T01:00:00-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 812966400.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812966400.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 812966400.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 816598800.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 812966400.0)) - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 815043600.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814780800.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815389200.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814780800.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815389200.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809683200.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 809769600.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 809683200.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 809942400.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 809337600.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 809942400.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809337600.0)) - - date = Date(timeIntervalSince1970: 812365387.0) // 1995-09-29T02:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 812970187.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812970187.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 812970187.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 816602587.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 812970187.0)) - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 815047387.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814784587.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815392987.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814784587.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815392987.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809686987.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 809773387.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 809686987.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 809946187.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 809341387.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 809946187.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809341387.0)) - - date = Date(timeIntervalSince1970: 812368987.0) // 1995-09-29T03:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 812973787.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812973787.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 812973787.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 816606187.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 812973787.0)) - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 815050987.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814788187.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815396587.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814788187.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815396587.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809690587.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 809776987.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 809690587.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 809949787.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 809344987.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 809949787.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809344987.0)) - - date = Date(timeIntervalSince1970: 812372587.0) // 1995-09-29T04:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 812977387.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812977387.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 812977387.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 816609787.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 812977387.0)) - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 815054587.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814791787.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815400187.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814791787.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815400187.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809694187.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 809780587.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 809694187.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 809953387.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 809348587.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 809953387.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809348587.0)) - - date = Date(timeIntervalSince1970: 812530800.0) // 1995-10-01T00:00:00-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 813135600.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 813135600.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 813135600.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 816768000.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 813135600.0)) - - date = Date(timeIntervalSince1970: 812534400.0) // 1995-10-01T01:00:00-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 813139200.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 813139200.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 813139200.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 816771600.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 813139200.0)) - - date = Date(timeIntervalSince1970: 812538187.0) // 1995-10-01T02:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 813142987.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 813142987.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 813142987.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 816775387.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 813142987.0)) - - date = Date(timeIntervalSince1970: 812541787.0) // 1995-10-01T03:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 813146587.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 813146587.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 813146587.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 816778987.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 813146587.0)) - - date = Date(timeIntervalSince1970: 812545387.0) // 1995-10-01T04:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 813150187.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 813150187.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 813150187.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 816782587.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 813150187.0)) - - date = Date(timeIntervalSince1970: 812530800.0) // 1995-10-01T00:00:00-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 815212800.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 815126400.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 815212800.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815558400.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815558400.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809938800.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 809938800.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 809852400.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 810111600.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 809506800.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 810111600.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809506800.0)) - - date = Date(timeIntervalSince1970: 812534400.0) // 1995-10-01T01:00:00-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 815216400.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 815130000.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 815216400.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815562000.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815562000.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809942400.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 809942400.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 809856000.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 810115200.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 809510400.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 810115200.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809510400.0)) - - date = Date(timeIntervalSince1970: 812538187.0) // 1995-10-01T02:03:07-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 815220187.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 815133787.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 815220187.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815565787.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815565787.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809946187.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 809946187.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 809859787.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 810118987.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 809514187.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 810118987.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809514187.0)) - - date = Date(timeIntervalSince1970: 812541787.0) // 1995-10-01T03:03:07-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 815223787.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 815137387.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 815223787.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815569387.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815569387.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809949787.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 809949787.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 809863387.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 810122587.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 809517787.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 810122587.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809517787.0)) - - date = Date(timeIntervalSince1970: 812545387.0) // 1995-10-01T04:03:07-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 815227387.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 815140987.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 815227387.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815572987.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815572987.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809953387.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 809953387.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 809866987.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 810126187.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 809521387.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 810126187.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809521387.0)) - - date = Date(timeIntervalSince1970: 814345200.0) // 1995-10-22T00:00:00-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 818582400.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - - date = Date(timeIntervalSince1970: 814348800.0) // 1995-10-22T01:00:00-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 818586000.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - - date = Date(timeIntervalSince1970: 814352587.0) // 1995-10-22T02:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 818589787.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - - date = Date(timeIntervalSince1970: 814356187.0) // 1995-10-22T03:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 818593387.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - - date = Date(timeIntervalSince1970: 814359787.0) // 1995-10-22T04:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 818596987.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - } - - func testAddDateComponents_Wrapping_DSTBoundaries() { - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(identifier: "America/Los_Angeles")!, locale: nil, firstWeekday: 3, minimumDaysInFirstWeek: 5, gregorianStartDate: nil) - - let fmt = Date.ISO8601FormatStyle(timeZone: gregorianCalendar.timeZone) - func testAdding(_ comp: DateComponents, to date: Date, expected: Date, _ file: StaticString = #filePath, _ line: UInt = #line) { - let result = gregorianCalendar.date(byAdding: comp, to: date, wrappingComponents: true)! - XCTAssertEqual(result, expected, "result: \(fmt.format(result)); expected: \(fmt.format(expected))", file: file, line: line) - } - - var date: Date - date = Date(timeIntervalSince1970: 814950000.0) // 1995-10-29T00:00:00-0700 - - // minute equivalent - testAdding(.init(minute: 1), to: date, expected: Date(timeIntervalSince1970: 814950060.0)) - testAdding(.init(second: 60), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(hour: 1, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(day: 1, hour: -23, minute: -59), to: date, expected: Date(timeIntervalSince1970: 815043660.0)) - testAdding(.init(minute: -1), to: date, expected: Date(timeIntervalSince1970: 814953540.0)) - testAdding(.init(second: -60), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(hour: -1, minute: 59), to: date, expected: Date(timeIntervalSince1970: 815036340.0)) - testAdding(.init(day: -1, hour: 23, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814949940.0)) - - date = Date(timeIntervalSince1970: 814953599.0) // 1995-10-29T00:59:59-0700 - - // second equivalent - testAdding(.init(second: 1), to: date, expected: Date(timeIntervalSince1970: 814953540.0)) - testAdding(.init(minute: 60, second: -59), to: date, expected: Date(timeIntervalSince1970: 814953540.0)) - testAdding(.init(hour: 1, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957140.0)) - testAdding(.init(hour: 2, minute: -59, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957200.0)) - testAdding(.init(second: -1), to: date, expected: Date(timeIntervalSince1970: 814953598.0)) - testAdding(.init(minute: -60, second: 59), to: date, expected: Date(timeIntervalSince1970: 814953598.0)) - testAdding(.init(hour: -1, second: 59), to: date, expected: Date(timeIntervalSince1970: 815036398.0)) - testAdding(.init(hour: -2, minute: 59, second: 59), to: date, expected: Date(timeIntervalSince1970: 815032738.0)) - - // minute equivalent - testAdding(.init(minute: 1), to: date, expected: Date(timeIntervalSince1970: 814950059.0)) - testAdding(.init(second: 60), to: date, expected: Date(timeIntervalSince1970: 814953599.0)) - testAdding(.init(hour: 1, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814953659.0)) - testAdding(.init(day: 1, hour: -23, minute: -59), to: date, expected: Date(timeIntervalSince1970: 815043659.0)) - testAdding(.init(minute: -1), to: date, expected: Date(timeIntervalSince1970: 814953539.0)) - testAdding(.init(second: -60), to: date, expected: Date(timeIntervalSince1970: 814953599.0)) - testAdding(.init(hour: -1, minute: 59), to: date, expected: Date(timeIntervalSince1970: 815036339.0)) - testAdding(.init(day: -1, hour: 23, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814949939.0)) - - date = Date(timeIntervalSince1970: 814953600.0) // 1995-10-29T01:00:00-0700 - - // minute equivalent - testAdding(.init(minute: 1), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(second: 60), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(hour: 1, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814957260.0)) - testAdding(.init(day: 1, hour: -23, minute: -59), to: date, expected: Date(timeIntervalSince1970: 815047260.0)) - testAdding(.init(minute: -1), to: date, expected: Date(timeIntervalSince1970: 814957140.0)) - testAdding(.init(second: -60), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(hour: -1, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814953540.0)) - testAdding(.init(day: -1, hour: 23, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814867140.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815130000.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812880000.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 813139200.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815562000.0)) - - date = Date(timeIntervalSince1970: 814953660.0) // 1995-10-29T01:01:00-0700 - - // second equivalent - testAdding(.init(second: 1), to: date, expected: Date(timeIntervalSince1970: 814953661.0)) - testAdding(.init(minute: 60, second: -59), to: date, expected: Date(timeIntervalSince1970: 814953661.0)) - testAdding(.init(hour: 1, second: -59), to: date, expected: Date(timeIntervalSince1970: 814957261.0)) - testAdding(.init(hour: 2, minute: -59, second: -59), to: date, expected: Date(timeIntervalSince1970: 814960921.0)) - testAdding(.init(second: -1), to: date, expected: Date(timeIntervalSince1970: 814953719.0)) - testAdding(.init(minute: -60, second: 59), to: date, expected: Date(timeIntervalSince1970: 814953719.0)) - testAdding(.init(hour: -1, second: 59), to: date, expected: Date(timeIntervalSince1970: 814950119.0)) - testAdding(.init(hour: -2, minute: 59, second: 59), to: date, expected: Date(timeIntervalSince1970: 815032859.0)) - - // minute equivalent - testAdding(.init(minute: 1), to: date, expected: Date(timeIntervalSince1970: 814953720.0)) - testAdding(.init(second: 60), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(hour: 1, minute: -59), to: date, expected: Date(timeIntervalSince1970: 814957320.0)) - testAdding(.init(day: 1, hour: -23, minute: -59), to: date, expected: Date(timeIntervalSince1970: 815047320.0)) - testAdding(.init(minute: -1), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(second: -60), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(hour: -1, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(day: -1, hour: 23, minute: 59), to: date, expected: Date(timeIntervalSince1970: 814863600.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815130060.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812880060.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 813139260.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815562060.0)) - - date = Date(timeIntervalSince1970: 814953660.0) // 1995-10-29T01:01:00-0700 - - // hour equivalent - testAdding(.init(hour: 1), to: date, expected: Date(timeIntervalSince1970: 814957260.0)) - testAdding(.init(minute: 60), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(second: 3600), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(hour: 2, minute: -60), to: date, expected: Date(timeIntervalSince1970: 814960860.0)) - testAdding(.init(day: 1, hour: -23), to: date, expected: Date(timeIntervalSince1970: 815047260.0)) - testAdding(.init(day: 1, hour: -22, minute: -60), to: date, expected: Date(timeIntervalSince1970: 815050860.0)) - testAdding(.init(hour: -1), to: date, expected: Date(timeIntervalSince1970: 814950060.0)) - testAdding(.init(minute: -60), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(second: -3600), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(hour: -2, minute: 60), to: date, expected: Date(timeIntervalSince1970: 815032860.0)) - testAdding(.init(day: -1, hour: 23), to: date, expected: Date(timeIntervalSince1970: 814863660.0)) - testAdding(.init(day: -1, hour: 22, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814946460.0)) - - // day equivalent - testAdding(.init(minute: 86400), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(hour: 24), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(day: 1), to: date, expected: Date(timeIntervalSince1970: 815043660.0)) - testAdding(.init(month: 1, day: -30), to: date, expected: Date(timeIntervalSince1970: 817635660.0)) - testAdding(.init(year: 1, month: -11, day: -30), to: date, expected: Date(timeIntervalSince1970: 849258060.0)) - testAdding(.init(weekday: 1), to: date, expected: Date(timeIntervalSince1970: 815040060.0)) - testAdding(.init(day: -1, weekday: 2), to: date, expected: Date(timeIntervalSince1970: 815040060.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815130060.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812880060.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 813139260.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815562060.0)) - testAdding(.init(yearForWeekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 846403260.0)) - testAdding(.init(weekOfYear: 52), to: date, expected: Date(timeIntervalSince1970: 814953660.0)) - testAdding(.init(weekOfYear: 53), to: date, expected: Date(timeIntervalSince1970: 815562060.0)) - testAdding(.init(yearForWeekOfYear: -1), to: date, expected: Date(timeIntervalSince1970: 783507660.0)) - // New: 1995-10-29T01:01:00-0700 - // Old: 1995-10-29T01:01:00-0800 - testAdding(.init(weekOfYear: -52), to: date, expected: Date(timeIntervalSince1970: 814957260.0)) - testAdding(.init(weekOfYear: -53), to: date, expected: Date(timeIntervalSince1970: 814348860.0)) - - date = Date(timeIntervalSince1970: 814957387.0) // 1995-10-29T01:03:07-0800 - - // hour equivalent - testAdding(.init(hour: 1), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(minute: 60), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(second: 3600), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(hour: 2, minute: -60), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(day: 1, hour: -23), to: date, expected: Date(timeIntervalSince1970: 815047387.0)) - testAdding(.init(day: 1, hour: -22, minute: -60), to: date, expected: Date(timeIntervalSince1970: 815050987.0)) - testAdding(.init(hour: -1), to: date, expected: Date(timeIntervalSince1970: 814953787.0)) - testAdding(.init(minute: -60), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(second: -3600), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(hour: -2, minute: 60), to: date, expected: Date(timeIntervalSince1970: 815036587.0)) - testAdding(.init(day: -1, hour: 23), to: date, expected: Date(timeIntervalSince1970: 814863787.0)) - testAdding(.init(day: -1, hour: 22, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814946587.0)) - - // day equivalent - testAdding(.init(minute: 86400), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(hour: 24), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(day: 1), to: date, expected: Date(timeIntervalSince1970: 815043787.0)) - testAdding(.init(month: 1, day: -30), to: date, expected: Date(timeIntervalSince1970: 817635787.0)) - testAdding(.init(year: 1, month: -11, day: -30), to: date, expected: Date(timeIntervalSince1970: 849258187.0)) - testAdding(.init(weekday: 1), to: date, expected: Date(timeIntervalSince1970: 815043787.0)) - testAdding(.init(day: -1, weekday: 2), to: date, expected: Date(timeIntervalSince1970: 815040187.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815130187.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812880187.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814953787.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 813142987.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815562187.0)) - testAdding(.init(yearForWeekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 846403387.0)) - testAdding(.init(weekOfYear: 52), to: date, expected: Date(timeIntervalSince1970: 814953787.0)) - testAdding(.init(weekOfYear: 53), to: date, expected: Date(timeIntervalSince1970: 815562187.0)) - testAdding(.init(yearForWeekOfYear: -1), to: date, expected: Date(timeIntervalSince1970: 783507787.0)) - testAdding(.init(weekOfYear: -52), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(weekOfYear: -53), to: date, expected: Date(timeIntervalSince1970: 814348987.0)) - - date = Date(timeIntervalSince1970: 814960987.0) // 1995-10-29T02:03:07-0800 - - // hour equivalent - testAdding(.init(hour: 1), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(minute: 60), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(second: 3600), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(hour: 2, minute: -60), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(day: 1, hour: -23), to: date, expected: Date(timeIntervalSince1970: 815050987.0)) - testAdding(.init(day: 1, hour: -22, minute: -60), to: date, expected: Date(timeIntervalSince1970: 815054587.0)) - testAdding(.init(hour: -1), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(minute: -60), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(second: -3600), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(hour: -2, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814953787.0)) - testAdding(.init(day: -1, hour: 23), to: date, expected: Date(timeIntervalSince1970: 814867387.0)) - testAdding(.init(day: -1, hour: 22, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814863787.0)) - - // day equivalent - testAdding(.init(minute: 86400), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(hour: 24), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(day: 1), to: date, expected: Date(timeIntervalSince1970: 815047387.0)) - testAdding(.init(month: 1, day: -30), to: date, expected: Date(timeIntervalSince1970: 817639387.0)) - testAdding(.init(year: 1, month: -11, day: -30), to: date, expected: Date(timeIntervalSince1970: 849261787.0)) - testAdding(.init(weekday: 1), to: date, expected: Date(timeIntervalSince1970: 815047387.0)) - testAdding(.init(day: -1, weekday: 2), to: date, expected: Date(timeIntervalSince1970: 815043787.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815133787.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812883787.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 813146587.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815565787.0)) - testAdding(.init(yearForWeekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 846410587.0)) - testAdding(.init(weekOfYear: 52), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(weekOfYear: 53), to: date, expected: Date(timeIntervalSince1970: 815565787.0)) - testAdding(.init(yearForWeekOfYear: -1), to: date, expected: Date(timeIntervalSince1970: 783511387.0)) - testAdding(.init(weekOfYear: -52), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(weekOfYear: -53), to: date, expected: Date(timeIntervalSince1970: 814352587.0)) - - date = Date(timeIntervalSince1970: 814964587.0) // 1995-10-29T03:03:07-0800 - - // hour equivalent - testAdding(.init(hour: 1), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(minute: 60), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(second: 3600), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(hour: 2, minute: -60), to: date, expected: Date(timeIntervalSince1970: 814971787.0)) - testAdding(.init(day: 1, hour: -23), to: date, expected: Date(timeIntervalSince1970: 815054587.0)) - testAdding(.init(day: 1, hour: -22, minute: -60), to: date, expected: Date(timeIntervalSince1970: 815058187.0)) - testAdding(.init(hour: -1), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(minute: -60), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(second: -3600), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(hour: -2, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814957387.0)) - testAdding(.init(day: -1, hour: 23), to: date, expected: Date(timeIntervalSince1970: 814870987.0)) - testAdding(.init(day: -1, hour: 22, minute: 60), to: date, expected: Date(timeIntervalSince1970: 814867387.0)) - - // day equivalent - testAdding(.init(minute: 86400), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(hour: 24), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(day: 1), to: date, expected: Date(timeIntervalSince1970: 815050987.0)) - testAdding(.init(month: 1, day: -30), to: date, expected: Date(timeIntervalSince1970: 817642987.0)) - testAdding(.init(year: 1, month: -11, day: -30), to: date, expected: Date(timeIntervalSince1970: 849265387.0)) - testAdding(.init(weekday: 1), to: date, expected: Date(timeIntervalSince1970: 815050987.0)) - testAdding(.init(day: -1, weekday: 2), to: date, expected: Date(timeIntervalSince1970: 815047387.0)) - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815137387.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812887387.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 813150187.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815569387.0)) - testAdding(.init(yearForWeekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 846414187.0)) - testAdding(.init(weekOfYear: 52), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(weekOfYear: 53), to: date, expected: Date(timeIntervalSince1970: 815569387.0)) - testAdding(.init(yearForWeekOfYear: -1), to: date, expected: Date(timeIntervalSince1970: 783514987.0)) - testAdding(.init(weekOfYear: -52), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(weekOfYear: -53), to: date, expected: Date(timeIntervalSince1970: 814356187.0)) - - date = Date(timeIntervalSince1970: 814780860.0) // 1995-10-27T01:01:00-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815130060.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812707260.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814780860.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 814176060.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815389260.0)) - testAdding(.init(year: 1), to: date, expected: Date(timeIntervalSince1970: 846403260.0)) - testAdding(.init(month: 12), to: date, expected: Date(timeIntervalSince1970: 814780860.0)) - testAdding(.init(day: 364), to: date, expected: Date(timeIntervalSince1970: 814089660.0)) - testAdding(.init(day: 365), to: date, expected: Date(timeIntervalSince1970: 814176060.0)) - testAdding(.init(day: 366), to: date, expected: Date(timeIntervalSince1970: 814262460.0)) - testAdding(.init(year: -1), to: date, expected: Date(timeIntervalSince1970: 783244860.0)) - testAdding(.init(month: -12), to: date, expected: Date(timeIntervalSince1970: 814780860.0)) - testAdding(.init(day: -364), to: date, expected: Date(timeIntervalSince1970: 812793660.0)) - testAdding(.init(day: -365), to: date, expected: Date(timeIntervalSince1970: 812707260.0)) - testAdding(.init(day: -366), to: date, expected: Date(timeIntervalSince1970: 812620860.0)) - - date = Date(timeIntervalSince1970: 814784587.0) // 1995-10-27T02:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815133787.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812710987.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814784587.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 814179787.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815392987.0)) - testAdding(.init(year: 1), to: date, expected: Date(timeIntervalSince1970: 846410587.0)) - testAdding(.init(month: 12), to: date, expected: Date(timeIntervalSince1970: 814784587.0)) - testAdding(.init(day: 364), to: date, expected: Date(timeIntervalSince1970: 814093387.0)) - testAdding(.init(day: 365), to: date, expected: Date(timeIntervalSince1970: 814179787.0)) - testAdding(.init(day: 366), to: date, expected: Date(timeIntervalSince1970: 814266187.0)) - testAdding(.init(year: -1), to: date, expected: Date(timeIntervalSince1970: 783248587.0)) - testAdding(.init(month: -12), to: date, expected: Date(timeIntervalSince1970: 814784587.0)) - testAdding(.init(day: -364), to: date, expected: Date(timeIntervalSince1970: 812797387.0)) - testAdding(.init(day: -365), to: date, expected: Date(timeIntervalSince1970: 812710987.0)) - testAdding(.init(day: -366), to: date, expected: Date(timeIntervalSince1970: 812624587.0)) - - date = Date(timeIntervalSince1970: 814788187.0) // 1995-10-27T03:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815137387.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812714587.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814788187.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 814183387.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815396587.0)) - testAdding(.init(year: 1), to: date, expected: Date(timeIntervalSince1970: 846414187.0)) - testAdding(.init(month: 12), to: date, expected: Date(timeIntervalSince1970: 814788187.0)) - testAdding(.init(day: 364), to: date, expected: Date(timeIntervalSince1970: 814096987.0)) - testAdding(.init(day: 365), to: date, expected: Date(timeIntervalSince1970: 814183387.0)) - testAdding(.init(day: 366), to: date, expected: Date(timeIntervalSince1970: 814269787.0)) - testAdding(.init(year: -1), to: date, expected: Date(timeIntervalSince1970: 783252187.0)) - testAdding(.init(month: -12), to: date, expected: Date(timeIntervalSince1970: 814788187.0)) - testAdding(.init(day: -364), to: date, expected: Date(timeIntervalSince1970: 812800987.0)) - testAdding(.init(day: -365), to: date, expected: Date(timeIntervalSince1970: 812714587.0)) - testAdding(.init(day: -366), to: date, expected: Date(timeIntervalSince1970: 812628187.0)) - - date = Date(timeIntervalSince1970: 814791787.0) // 1995-10-27T04:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 815140987.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 812718187.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814791787.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 814186987.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 815400187.0)) - testAdding(.init(year: 1), to: date, expected: Date(timeIntervalSince1970: 846417787.0)) - testAdding(.init(month: 12), to: date, expected: Date(timeIntervalSince1970: 814791787.0)) - testAdding(.init(day: 364), to: date, expected: Date(timeIntervalSince1970: 814100587.0)) - testAdding(.init(day: 365), to: date, expected: Date(timeIntervalSince1970: 814186987.0)) - testAdding(.init(day: 366), to: date, expected: Date(timeIntervalSince1970: 814273387.0)) - testAdding(.init(year: -1), to: date, expected: Date(timeIntervalSince1970: 783255787.0)) - testAdding(.init(month: -12), to: date, expected: Date(timeIntervalSince1970: 814791787.0)) - testAdding(.init(day: -364), to: date, expected: Date(timeIntervalSince1970: 812804587.0)) - testAdding(.init(day: -365), to: date, expected: Date(timeIntervalSince1970: 812718187.0)) - testAdding(.init(day: -366), to: date, expected: Date(timeIntervalSince1970: 812631787.0)) - - date = Date(timeIntervalSince1970: 812358000.0) // 1995-09-29T00:00:00-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 810543600.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 810370800.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 812358000.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 810543600.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 812962800.0)) - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 812358000.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 812444400.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 812358000.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 810543600.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814777200.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815385600.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809679600.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 812358000.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 812271600.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 812358000.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 811753200.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 809938800.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809334000.0)) - - date = Date(timeIntervalSince1970: 812361600.0) // 1995-09-29T01:00:00-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 812361600.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 812448000.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 812361600.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 810547200.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814780800.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815389200.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809683200.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 812361600.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 812275200.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 812361600.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 811756800.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 809942400.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809337600.0)) - - date = Date(timeIntervalSince1970: 812365387.0) // 1995-09-29T02:03:07-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 812365387.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 812451787.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 812365387.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 810550987.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814784587.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815392987.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809686987.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 812365387.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 812278987.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 812365387.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 811760587.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 809946187.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809341387.0)) - - date = Date(timeIntervalSince1970: 812368987.0) // 1995-09-29T03:03:07-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 812368987.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 812455387.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 812368987.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 810554587.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814788187.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815396587.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809690587.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 812368987.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 812282587.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 812368987.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 811764187.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 809949787.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809344987.0)) - - date = Date(timeIntervalSince1970: 812372587.0) // 1995-09-29T04:03:07-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 812372587.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 812458987.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 812372587.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 810558187.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814791787.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815400187.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809694187.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 812372587.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 812286187.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 812372587.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 811767787.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 809953387.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809348587.0)) - - date = Date(timeIntervalSince1970: 812534400.0) // 1995-10-01T01:00:00-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 813139200.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 813139200.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 812534400.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 813744000.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 813139200.0)) - - date = Date(timeIntervalSince1970: 812530800.0) // 1995-10-01T00:00:00-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 815212800.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 815126400.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 812530800.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815126400.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815558400.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809938800.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 812617200.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 812530800.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 813135600.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 815126400.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 810111600.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809506800.0)) - - date = Date(timeIntervalSince1970: 812534400.0) // 1995-10-01T01:00:00-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 815216400.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 815130000.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 812534400.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815130000.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815562000.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809942400.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 812620800.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 812534400.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 813139200.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 815130000.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 810115200.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809510400.0)) - - date = Date(timeIntervalSince1970: 812538187.0) // 1995-10-01T02:03:07-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 815220187.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 815133787.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 812538187.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815133787.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815565787.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809946187.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 812624587.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 812538187.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 813142987.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 815133787.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 810118987.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809514187.0)) - - date = Date(timeIntervalSince1970: 812541787.0) // 1995-10-01T03:03:07-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 815223787.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 815137387.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 812541787.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815137387.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815569387.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809949787.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 812628187.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 812541787.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 813146587.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 815137387.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 810122587.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809517787.0)) - - date = Date(timeIntervalSince1970: 812545387.0) // 1995-10-01T04:03:07-0700 - - // month equivalent - testAdding(.init(month: 1), to: date, expected: Date(timeIntervalSince1970: 815227387.0)) - testAdding(.init(day: 30), to: date, expected: Date(timeIntervalSince1970: 815140987.0)) - testAdding(.init(day: 31), to: date, expected: Date(timeIntervalSince1970: 812545387.0)) - testAdding(.init(weekOfMonth: 4), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(weekOfMonth: 5), to: date, expected: Date(timeIntervalSince1970: 815140987.0)) - testAdding(.init(weekOfYear: 4), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(weekOfYear: 5), to: date, expected: Date(timeIntervalSince1970: 815572987.0)) - testAdding(.init(month: -1), to: date, expected: Date(timeIntervalSince1970: 809953387.0)) - testAdding(.init(day: -30), to: date, expected: Date(timeIntervalSince1970: 812631787.0)) - testAdding(.init(day: -31), to: date, expected: Date(timeIntervalSince1970: 812545387.0)) - testAdding(.init(weekOfMonth: -4), to: date, expected: Date(timeIntervalSince1970: 813150187.0)) - testAdding(.init(weekOfMonth: -5), to: date, expected: Date(timeIntervalSince1970: 815140987.0)) - testAdding(.init(weekOfYear: -4), to: date, expected: Date(timeIntervalSince1970: 810126187.0)) - testAdding(.init(weekOfYear: -5), to: date, expected: Date(timeIntervalSince1970: 809521387.0)) - - date = Date(timeIntervalSince1970: 814345200.0) // 1995-10-22T00:00:00-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814345200.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 812530800.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 814950000.0)) - - date = Date(timeIntervalSince1970: 814348800.0) // 1995-10-22T01:00:00-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814348800.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 812534400.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 814953600.0)) - - date = Date(timeIntervalSince1970: 814352587.0) // 1995-10-22T02:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814352587.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 812538187.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 814960987.0)) - - date = Date(timeIntervalSince1970: 814356187.0) // 1995-10-22T03:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814356187.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 812541787.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 814964587.0)) - - date = Date(timeIntervalSince1970: 814359787.0) // 1995-10-22T04:03:07-0700 - - // week equivalent - testAdding(.init(weekOfMonth: 1), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(day: 7), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - testAdding(.init(weekday: 7), to: date, expected: Date(timeIntervalSince1970: 814359787.0)) - testAdding(.init(weekdayOrdinal: 7), to: date, expected: Date(timeIntervalSince1970: 812545387.0)) - testAdding(.init(weekOfYear: 1), to: date, expected: Date(timeIntervalSince1970: 814968187.0)) - } - - func testAdd_DST() { - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(identifier: "America/Los_Angeles")!, locale: nil, firstWeekday: 3, minimumDaysInFirstWeek: 5, gregorianStartDate: nil) - - let fmt = Date.ISO8601FormatStyle(timeZone: gregorianCalendar.timeZone) - func test(addField field: Calendar.Component, value: Int, to addingToDate: Date, expectedDate: Date, _ file: StaticString = #filePath, _ line: UInt = #line) { - let components = DateComponents(component: field, value: value)! - let result = gregorianCalendar.date(byAdding: components, to: addingToDate, wrappingComponents: false)! - let actualDiff = result.timeIntervalSince(addingToDate) - let expectedDiff = expectedDate.timeIntervalSince(addingToDate) - - let msg = "actual diff: \(actualDiff), expected: \(expectedDiff), actual ti = \(result.timeIntervalSince1970), expected ti = \(expectedDate.timeIntervalSince1970), actual = \(fmt.format(result)), expected = \(fmt.format(expectedDate))" - XCTAssertEqual(result, expectedDate, msg, file: file, line: line) - } - - var date: Date - - date = Date(timeIntervalSince1970: 828867787.0) // 1996-04-07T01:03:07-0800 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828867787.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828867787.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 860400187.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 797241787.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 860317387.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 797414587.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 831456187.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 826189387.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828950587.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828781387.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828871387.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828864187.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828867847.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828867727.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828867788.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828867786.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828950587.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828781387.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829468987.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828262987.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829468987.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828262987.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829468987.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828262987.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828867787.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828867787.0)) - - date = Date(timeIntervalSince1970: 828871387.0) // 1996-04-07T03:03:07-0700 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828871387.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828871387.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 860407387.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 797248987.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 860320987.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 797421787.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 831463387.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 826196587.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828957787.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828788587.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828874987.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828867787.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828871447.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828871327.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828871388.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828871386.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828957787.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828788587.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829476187.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828270187.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829476187.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828270187.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829476187.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828270187.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828871387.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828871387.0)) - - date = Date(timeIntervalSince1970: 828874987.0) // 1996-04-07T04:03:07-0700 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828874987.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828874987.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 860410987.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 797252587.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 860324587.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 797425387.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 831466987.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 826200187.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828961387.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828792187.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828878587.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828871387.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828875047.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828874927.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828874988.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828874986.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828961387.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828792187.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829479787.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828273787.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829479787.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828273787.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829479787.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828273787.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828874987.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828874987.0)) - - date = Date(timeIntervalSince1970: 846403387.0) // 1996-10-27T01:03:07-0700 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846403387.0)) - // Previously this returns 1996-10-27T01:03:07-0800 - // New behavior just returns the date unchanged, like other non-DST transition dates - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846403387.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877942987.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814780987.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877852987.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814957387.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 849085387.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 843811387.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846493387.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846316987.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846406987.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846399787.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846403447.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846403327.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846403388.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846403386.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846493387.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846316987.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847011787.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845798587.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847011787.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845798587.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847011787.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845798587.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846403387.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846403387.0)) - - date = Date(timeIntervalSince1970: 846406987.0) // 1996-10-27T01:03:07-0800 - // Previously this returns 1996-10-27T01:03:07-0700 - // Now it returns date unchanged, as other non-DST transition dates. - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846406987.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846406987.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877942987.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814780987.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877852987.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814957387.0)) // 1995-10-29T01:03:07-0800 - - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 849085387.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 843811387.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846493387.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846316987.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846410587.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846403387.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846407047.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846406927.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846406988.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846406986.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846493387.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846316987.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847011787.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845798587.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847011787.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845798587.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847011787.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845798587.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846406987.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846406987.0)) - - date = Date(timeIntervalSince1970: 846410587.0) // 1996-10-27T02:03:07-0800 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846410587.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846410587.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877946587.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814784587.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877860187.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814960987.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 849088987.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 843814987.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846496987.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846320587.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846414187.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846406987.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846410647.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846410527.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846410588.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846410586.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846496987.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846320587.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847015387.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845802187.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847015387.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845802187.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847015387.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845802187.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846410587.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846410587.0)) - - date = Date(timeIntervalSince1970: 846414187.0) // 1996-10-27T03:03:07-0800 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846414187.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846414187.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877950187.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814788187.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877863787.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814964587.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 849092587.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 843818587.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846500587.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846324187.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846417787.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846410587.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846414247.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846414127.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846414188.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846414186.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846500587.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846324187.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847018987.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845805787.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847018987.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845805787.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847018987.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845805787.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846414187.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846414187.0)) - - date = Date(timeIntervalSince1970: 814953787.0) // 1995-10-29T01:03:07-0700 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814953787.0)) - // Previously this returns 1995-10-29T01:03:07-0800 - // New behavior just returns the date unchanged, like other non-DST transition dates - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814953787.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846579787.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 783417787.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846403387.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 783507787.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 817635787.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 812361787.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815043787.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814867387.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814957387.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814950187.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814953847.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814953727.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814953788.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814953786.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815043787.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814867387.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815562187.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814348987.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815562187.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814348987.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815562187.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814348987.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814953787.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814953787.0)) - - date = Date(timeIntervalSince1970: 814957387.0) // 1995-10-29T01:03:07-0800 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814957387.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814957387.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846579787.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 783417787.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846403387.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 783507787.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 817635787.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 812361787.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815043787.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814867387.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814960987.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814953787.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814957447.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814957327.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814957388.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814957386.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815043787.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814867387.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815562187.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814348987.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815562187.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814348987.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815562187.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814348987.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814957387.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814957387.0)) - - date = Date(timeIntervalSince1970: 814960987.0) // 1995-10-29T02:03:07-0800 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814960987.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814960987.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846583387.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 783421387.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846410587.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 783511387.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 817639387.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 812365387.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815047387.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814870987.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814964587.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814957387.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814961047.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814960927.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814960988.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814960986.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815047387.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814870987.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815565787.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814352587.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815565787.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814352587.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815565787.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814352587.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814960987.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814960987.0)) - - date = Date(timeIntervalSince1970: 814964587.0) // 1995-10-29T03:03:07-0800 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814964587.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814964587.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846586987.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 783424987.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846414187.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 783514987.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 817642987.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 812368987.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815050987.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814874587.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814968187.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814960987.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814964647.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814964527.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814964588.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814964586.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815050987.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814874587.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815569387.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814356187.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815569387.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814356187.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 815569387.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814356187.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 814964587.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814964587.0)) - } - - func testAdd_Wrap_DST() { - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(identifier: "America/Los_Angeles")!, locale: nil, firstWeekday: 3, minimumDaysInFirstWeek: 5, gregorianStartDate: nil) - - let fmt = Date.ISO8601FormatStyle(timeZone: gregorianCalendar.timeZone) - func test(addField field: Calendar.Component, value: Int, to addingToDate: Date, expectedDate: Date, _ file: StaticString = #filePath, _ line: UInt = #line) { - let components = DateComponents(component: field, value: value)! - let result = gregorianCalendar.date(byAdding: components, to: addingToDate, wrappingComponents: true)! - let msg = "actual = \(fmt.format(result)), expected = \(fmt.format(expectedDate))" - XCTAssertEqual(result, expectedDate, msg, file: file, line: line) - } - - var date: Date - date = Date(timeIntervalSince1970: 828867787.0) // 1996-04-07T01:03:07-0800 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828867787.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828867787.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 860400187.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 797241787.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 860317387.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 797414587.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 831456187.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 826189387.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828950587.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828781387.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828871387.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828864187.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828867847.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828867727.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828867788.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828867786.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828954187.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828781387.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829472587.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 830682187.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829468987.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828262987.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829468987.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 830851387.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828867787.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828867787.0)) - - date = Date(timeIntervalSince1970: 828871387.0) // 1996-04-07T03:03:07-0700 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828871387.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828871387.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 860407387.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 797248987.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 860320987.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 797421787.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 831463387.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 826196587.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828957787.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828788587.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828874987.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828867787.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828871447.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828871327.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828871388.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828871386.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828957787.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828784987.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829476187.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 830685787.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829476187.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828270187.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829476187.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 830858587.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828871387.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828871387.0)) - - date = Date(timeIntervalSince1970: 828874987.0) // 1996-04-07T04:03:07-0700 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828874987.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828874987.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 860410987.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 797252587.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 860324587.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 797425387.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 831466987.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 826200187.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828961387.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828792187.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828878587.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828871387.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828875047.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828874927.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828874988.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828874986.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828961387.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828788587.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829479787.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 830689387.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829479787.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828273787.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 829479787.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 830862187.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 828874987.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 828874987.0)) - - date = Date(timeIntervalSince1970: 846406987.0) // 1996-10-27T01:03:07-0800 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846406987.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846406987.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877942987.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814780987.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877852987.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814957387.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 849085387.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 843811387.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846493387.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846316987.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846410587.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846403387.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846407047.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846406927.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846406988.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846406986.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846493387.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846320587.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 844592587.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845802187.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847011787.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845798587.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846752587.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845798587.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846406987.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846406987.0)) - - date = Date(timeIntervalSince1970: 846410587.0) // 1996-10-27T02:03:07-0800 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846410587.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846410587.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877946587.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814784587.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877860187.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814960987.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 849088987.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 843814987.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846496987.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846320587.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846414187.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846406987.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846410647.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846410527.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846410588.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846410586.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846496987.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846324187.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 844596187.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845805787.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847015387.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845802187.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846756187.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845802187.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846410587.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846410587.0)) - - date = Date(timeIntervalSince1970: 846414187.0) // 1996-10-27T03:03:07-0800 - test(addField: .era, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846414187.0)) - test(addField: .era, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846414187.0)) - test(addField: .year, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877950187.0)) - test(addField: .year, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814788187.0)) - test(addField: .yearForWeekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 877863787.0)) - test(addField: .yearForWeekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 814964587.0)) - test(addField: .month, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 849092587.0)) - test(addField: .month, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 843818587.0)) - test(addField: .day, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846500587.0)) - test(addField: .day, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846324187.0)) - test(addField: .hour, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846417787.0)) - test(addField: .hour, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846410587.0)) - test(addField: .minute, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846414247.0)) - test(addField: .minute, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846414127.0)) - test(addField: .second, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846414188.0)) - test(addField: .second, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846414186.0)) - test(addField: .weekday, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846500587.0)) - test(addField: .weekday, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846327787.0)) - test(addField: .weekdayOrdinal, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 844599787.0)) - test(addField: .weekdayOrdinal, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845809387.0)) - test(addField: .weekOfYear, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 847018987.0)) - test(addField: .weekOfYear, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845805787.0)) - test(addField: .weekOfMonth, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846759787.0)) - test(addField: .weekOfMonth, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 845805787.0)) - test(addField: .nanosecond, value: 1, to: date, expectedDate: Date(timeIntervalSince1970: 846414187.0)) - test(addField: .nanosecond, value: -1, to: date, expectedDate: Date(timeIntervalSince1970: 846414187.0)) - } - - // MARK: - Ordinality - - // This test requires 64-bit integers - #if arch(x86_64) || arch(arm64) - func testOrdinality() { - let cal = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(secondsFromGMT: 3600)!, locale: nil, firstWeekday: 5, minimumDaysInFirstWeek: 4, gregorianStartDate: nil) - - func test(_ small: Calendar.Component, in large: Calendar.Component, for date: Date, expected: Int?, file: StaticString = #filePath, line: UInt = #line) { - let result = cal.ordinality(of: small, in: large, for: date) - XCTAssertEqual(result, expected, "small: \(small), large: \(large)", file: file, line: line) - } - - var date: Date - date = Date(timeIntervalSince1970: 852045787.0) // 1996-12-31T15:23:07Z - test(.year, in: .era, for: date, expected: 1996) - test(.month, in: .era, for: date, expected: 23952) - test(.day, in: .era, for: date, expected: 729024) - test(.weekday, in: .era, for: date, expected: 104147) - test(.weekdayOrdinal, in: .era, for: date, expected: 104147) - test(.quarter, in: .era, for: date, expected: 7984) - test(.weekOfMonth, in: .era, for: date, expected: 104146) - test(.month, in: .year, for: date, expected: 12) - test(.day, in: .year, for: date, expected: 366) - test(.weekday, in: .year, for: date, expected: 53) - test(.weekdayOrdinal, in: .year, for: date, expected: 53) - test(.quarter, in: .year, for: date, expected: 4) - test(.weekOfYear, in: .year, for: date, expected: 52) - test(.day, in: .month, for: date, expected: 31) - test(.weekday, in: .month, for: date, expected: 5) - test(.weekdayOrdinal, in: .month, for: date, expected: 5) - test(.weekOfMonth, in: .month, for: date, expected: 5) - test(.day, in: .weekOfMonth, for: date, expected: 6) - test(.weekday, in: .weekOfMonth, for: date, expected: 6) - test(.month, in: .quarter, for: date, expected: 3) - test(.day, in: .quarter, for: date, expected: 92) - test(.weekday, in: .quarter, for: date, expected: 14) - test(.weekdayOrdinal, in: .quarter, for: date, expected: 14) - test(.weekOfMonth, in: .quarter, for: date, expected: 13) - test(.weekOfYear, in: .quarter, for: date, expected: 13) - test(.day, in: .weekOfYear, for: date, expected: 6) - test(.weekday, in: .weekOfYear, for: date, expected: 6) - test(.minute, in: .hour, for: date, expected: 24) - test(.second, in: .hour, for: date, expected: 1388) - test(.nanosecond, in: .hour, for: date, expected: 1387000000001) - test(.second, in: .minute, for: date, expected: 8) - test(.nanosecond, in: .minute, for: date, expected: 7000000001) - test(.nanosecond, in: .second, for: date, expected: 1) - - date = Date(timeIntervalSince1970: 828838987.0) // 1996-04-07T01:03:07Z - test(.day, in: .weekOfMonth, for: date, expected: 4) - test(.weekday, in: .weekOfMonth, for: date, expected: 4) - test(.day, in: .weekOfYear, for: date, expected: 4) - test(.weekday, in: .weekOfYear, for: date, expected: 4) - test(.year, in: .era, for: date, expected: 1996) - test(.month, in: .era, for: date, expected: 23944) - test(.day, in: .era, for: date, expected: 728756) - test(.weekday, in: .era, for: date, expected: 104108) - test(.weekdayOrdinal, in: .era, for: date, expected: 104108) - test(.quarter, in: .era, for: date, expected: 7982) - test(.month, in: .year, for: date, expected: 4) - test(.day, in: .year, for: date, expected: 98) - test(.weekday, in: .year, for: date, expected: 14) - test(.weekdayOrdinal, in: .year, for: date, expected: 14) - test(.quarter, in: .year, for: date, expected: 2) - test(.weekOfYear, in: .year, for: date, expected: 14) - test(.day, in: .month, for: date, expected: 7) - test(.weekday, in: .month, for: date, expected: 1) - test(.weekdayOrdinal, in: .month, for: date, expected: 1) - test(.weekOfMonth, in: .month, for: date, expected: 1) - test(.month, in: .quarter, for: date, expected: 1) - test(.day, in: .quarter, for: date, expected: 7) - test(.weekday, in: .quarter, for: date, expected: 1) - test(.weekdayOrdinal, in: .quarter, for: date, expected: 1) - test(.weekOfMonth, in: .quarter, for: date, expected: 1) - test(.weekOfYear, in: .quarter, for: date, expected: 1) - test(.minute, in: .hour, for: date, expected: 4) - test(.second, in: .hour, for: date, expected: 188) - test(.nanosecond, in: .hour, for: date, expected: 187000000001) - test(.second, in: .minute, for: date, expected: 8) - test(.nanosecond, in: .minute, for: date, expected: 7000000001) - test(.nanosecond, in: .second, for: date, expected: 1) - - - date = Date(timeIntervalSince1970: -62135765813.0) // 0001-01-01T01:03:07Z - test(.month, in: .year, for: date, expected: 1) - test(.day, in: .year, for: date, expected: 1) - test(.weekday, in: .year, for: date, expected: 1) - test(.weekdayOrdinal, in: .year, for: date, expected: 1) - test(.quarter, in: .year, for: date, expected: 1) - test(.weekOfYear, in: .year, for: date, expected: 1) - test(.day, in: .weekOfMonth, for: date, expected: 3) - test(.weekday, in: .weekOfMonth, for: date, expected: 3) - test(.day, in: .month, for: date, expected: 1) - test(.weekday, in: .month, for: date, expected: 1) - test(.weekdayOrdinal, in: .month, for: date, expected: 1) - test(.weekOfMonth, in: .month, for: date, expected: 1) - test(.day, in: .weekOfYear, for: date, expected: 3) - test(.weekday, in: .weekOfYear, for: date, expected: 3) - test(.month, in: .quarter, for: date, expected: 1) - test(.day, in: .quarter, for: date, expected: 1) - test(.weekday, in: .quarter, for: date, expected: 1) - test(.weekdayOrdinal, in: .quarter, for: date, expected: 1) - test(.weekOfMonth, in: .quarter, for: date, expected: 1) - test(.weekOfYear, in: .quarter, for: date, expected: 1) - test(.year, in: .era, for: date, expected: 1) - test(.month, in: .era, for: date, expected: 1672389) - test(.day, in: .era, for: date, expected: 50903315) - test(.weekday, in: .era, for: date, expected: 7271902) - test(.weekdayOrdinal, in: .era, for: date, expected: 7271902) - test(.quarter, in: .era, for: date, expected: 1) - test(.weekOfMonth, in: .era, for: date, expected: 7271903) - test(.minute, in: .hour, for: date, expected: 4) - test(.second, in: .hour, for: date, expected: 188) - test(.nanosecond, in: .hour, for: date, expected: 187000000001) - test(.second, in: .minute, for: date, expected: 8) - test(.nanosecond, in: .minute, for: date, expected: 7000000001) - test(.nanosecond, in: .second, for: date, expected: 1) - } - #endif - - func testOrdinality_DST() { - let cal = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(identifier: "America/Los_Angeles")!, locale: nil, firstWeekday: 5, minimumDaysInFirstWeek: 4, gregorianStartDate: nil) - - func test(_ small: Calendar.Component, in large: Calendar.Component, for date: Date, expected: Int?, file: StaticString = #filePath, line: UInt = #line) { - let result = cal.ordinality(of: small, in: large, for: date) - XCTAssertEqual(result, expected, "small: \(small), large: \(large)", file: file, line: line) - } - - var date: Date - - date = Date(timeIntervalSince1970: 851990400.0) // 1996-12-30T16:00:00-0800 (1996-12-31T00:00:00Z) - test(.hour, in: .month, for: date, expected: 713) - test(.minute, in: .month, for: date, expected: 42721) - test(.hour, in: .day, for: date, expected: 17) - test(.minute, in: .day, for: date, expected: 961) - test(.minute, in: .hour, for: date, expected: 1) - - date = Date(timeIntervalSince1970: 820483200.0) // 1996-01-01T00:00:00-0800 (1996-01-01T08:00:00Z) - test(.hour, in: .month, for: date, expected: 1) - test(.minute, in: .month, for: date, expected: 1) - test(.hour, in: .day, for: date, expected: 1) - test(.minute, in: .day, for: date, expected: 1) - test(.minute, in: .hour, for: date, expected: 1) - - date = Date(timeIntervalSince1970: 828867787.0) // 1996-04-07T01:03:07-0800 (1996-04-07T09:03:07Z) - test(.hour, in: .month, for: date, expected: 146) - test(.minute, in: .month, for: date, expected: 8704) - test(.hour, in: .day, for: date, expected: 2) - test(.minute, in: .day, for: date, expected: 64) - test(.minute, in: .hour, for: date, expected: 4) - - date = Date(timeIntervalSince1970: 828871387.0) // 1996-04-07T03:03:07-0700 (1996-04-07T10:03:07Z) - test(.hour, in: .month, for: date, expected: 148) - test(.minute, in: .month, for: date, expected: 8824) - test(.hour, in: .day, for: date, expected: 4) - test(.minute, in: .day, for: date, expected: 184) - test(.minute, in: .hour, for: date, expected: 4) - - date = Date(timeIntervalSince1970: 828874987.0) // 1996-04-07T04:03:07-0700 (1996-04-07T11:03:07Z) - test(.hour, in: .month, for: date, expected: 149) - test(.minute, in: .month, for: date, expected: 8884) - test(.hour, in: .day, for: date, expected: 5) - test(.minute, in: .day, for: date, expected: 244) - test(.minute, in: .hour, for: date, expected: 4) - - date = Date(timeIntervalSince1970: 846414187.0) // 1996-10-27T03:03:07-0800 (1996-10-27T11:03:07Z) - test(.hour, in: .day, for: date, expected: 4) - test(.minute, in: .day, for: date, expected: 184) - test(.hour, in: .month, for: date, expected: 628) - test(.minute, in: .month, for: date, expected: 37624) - test(.minute, in: .hour, for: date, expected: 4) - - date = Date(timeIntervalSince1970: 845121787.0) // 1996-10-12T05:03:07-0700 (1996-10-12T12:03:07Z) - test(.hour, in: .day, for: date, expected: 6) - test(.minute, in: .day, for: date, expected: 304) - test(.hour, in: .month, for: date, expected: 270) - test(.minute, in: .month, for: date, expected: 16144) - test(.minute, in: .hour, for: date, expected: 4) - } - - - // This test requires 64-bit integers - #if arch(x86_64) || arch(arm64) - func testOrdinality_DST2() { - let calendar = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(identifier: "America/Los_Angeles")!, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let date = Date(timeIntervalSinceReferenceDate: 682898558.712307) - XCTAssertEqual(calendar.ordinality(of: .era, in: .era, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .era, in: .year, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .era, in: .month, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .era, in: .day, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .era, in: .hour, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .era, in: .minute, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .era, in: .second, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .era, in: .weekday, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .era, in: .weekdayOrdinal, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .era, in: .quarter, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .era, in: .weekOfMonth, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .era, in: .weekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .era, in: .yearForWeekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .era, in: .nanosecond, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .year, in: .era, for: date), 2022) - XCTAssertEqual(calendar.ordinality(of: .year, in: .year, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .year, in: .month, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .year, in: .day, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .year, in: .hour, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .year, in: .minute, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .year, in: .second, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .year, in: .weekday, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .year, in: .weekdayOrdinal, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .year, in: .quarter, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .year, in: .weekOfMonth, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .year, in: .weekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .year, in: .yearForWeekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .year, in: .nanosecond, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .month, in: .era, for: date), 24260) - XCTAssertEqual(calendar.ordinality(of: .month, in: .year, for: date), 8) - XCTAssertEqual(calendar.ordinality(of: .month, in: .month, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .month, in: .day, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .month, in: .hour, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .month, in: .minute, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .month, in: .second, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .month, in: .weekday, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .month, in: .weekdayOrdinal, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .month, in: .quarter, for: date), 2) - XCTAssertEqual(calendar.ordinality(of: .month, in: .weekOfMonth, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .month, in: .weekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .month, in: .yearForWeekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .month, in: .nanosecond, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .day, in: .era, for: date), 738389) - XCTAssertEqual(calendar.ordinality(of: .day, in: .year, for: date), 234) - XCTAssertEqual(calendar.ordinality(of: .day, in: .month, for: date), 22) - XCTAssertEqual(calendar.ordinality(of: .day, in: .day, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .day, in: .hour, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .day, in: .minute, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .day, in: .second, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .day, in: .weekday, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .day, in: .weekdayOrdinal, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .day, in: .quarter, for: date), 53) - XCTAssertEqual(calendar.ordinality(of: .day, in: .weekOfMonth, for: date), 2) - XCTAssertEqual(calendar.ordinality(of: .day, in: .weekOfYear, for: date), 2) - XCTAssertEqual(calendar.ordinality(of: .day, in: .yearForWeekOfYear, for: date), 240) - XCTAssertEqual(calendar.ordinality(of: .day, in: .nanosecond, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .hour, in: .era, for: date), 17721328) - XCTAssertEqual(calendar.ordinality(of: .hour, in: .year, for: date), 5608) - XCTAssertEqual(calendar.ordinality(of: .hour, in: .month, for: date), 520) - XCTAssertEqual(calendar.ordinality(of: .hour, in: .day, for: date), 16) - XCTAssertEqual(calendar.ordinality(of: .hour, in: .hour, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .hour, in: .minute, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .hour, in: .second, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .hour, in: .weekday, for: date), 16) - XCTAssertEqual(calendar.ordinality(of: .hour, in: .weekdayOrdinal, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .hour, in: .quarter, for: date), 1264) - XCTAssertEqual(calendar.ordinality(of: .hour, in: .weekOfMonth, for: date), 40) - XCTAssertEqual(calendar.ordinality(of: .hour, in: .weekOfYear, for: date), 40) - XCTAssertEqual(calendar.ordinality(of: .hour, in: .yearForWeekOfYear, for: date), 5737) - XCTAssertEqual(calendar.ordinality(of: .hour, in: .nanosecond, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .minute, in: .era, for: date), 1063279623) - XCTAssertEqual(calendar.ordinality(of: .minute, in: .year, for: date), 336423) - XCTAssertEqual(calendar.ordinality(of: .minute, in: .month, for: date), 31143) - XCTAssertEqual(calendar.ordinality(of: .minute, in: .day, for: date), 903) - XCTAssertEqual(calendar.ordinality(of: .minute, in: .hour, for: date), 3) - XCTAssertEqual(calendar.ordinality(of: .minute, in: .minute, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .minute, in: .second, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .minute, in: .weekday, for: date), 903) - XCTAssertEqual(calendar.ordinality(of: .minute, in: .weekdayOrdinal, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .minute, in: .quarter, for: date), 75783) - XCTAssertEqual(calendar.ordinality(of: .minute, in: .weekOfMonth, for: date), 2343) - XCTAssertEqual(calendar.ordinality(of: .minute, in: .weekOfYear, for: date), 2343) - - XCTAssertEqual(calendar.ordinality(of: .minute, in: .yearForWeekOfYear, for: date), 344161) - XCTAssertEqual(calendar.ordinality(of: .minute, in: .nanosecond, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .second, in: .era, for: date), 63796777359) - XCTAssertEqual(calendar.ordinality(of: .second, in: .year, for: date), 20185359) - XCTAssertEqual(calendar.ordinality(of: .second, in: .month, for: date), 1868559) - XCTAssertEqual(calendar.ordinality(of: .second, in: .day, for: date), 54159) - XCTAssertEqual(calendar.ordinality(of: .second, in: .hour, for: date), 159) - XCTAssertEqual(calendar.ordinality(of: .second, in: .minute, for: date), 39) - XCTAssertEqual(calendar.ordinality(of: .second, in: .second, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .second, in: .weekday, for: date), 54159) - XCTAssertEqual(calendar.ordinality(of: .second, in: .weekdayOrdinal, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .second, in: .quarter, for: date), 4546959) - XCTAssertEqual(calendar.ordinality(of: .second, in: .weekOfMonth, for: date), 140559) - XCTAssertEqual(calendar.ordinality(of: .second, in: .weekOfYear, for: date), 140559) - XCTAssertEqual(calendar.ordinality(of: .second, in: .yearForWeekOfYear, for: date), 20649601) - XCTAssertEqual(calendar.ordinality(of: .second, in: .nanosecond, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .era, for: date), 105484) - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .year, for: date), 34) - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .month, for: date), 4) - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .day, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .hour, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .minute, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .second, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .weekday, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .weekdayOrdinal, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .quarter, for: date), 8) - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .weekOfMonth, for: date), 2) - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .weekOfYear, for: date), 2) - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .yearForWeekOfYear, for: date), 35) - XCTAssertEqual(calendar.ordinality(of: .weekday, in: .nanosecond, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .era, for: date), 105484) - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .year, for: date), 34) - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .month, for: date), 4) - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .day, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .hour, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .minute, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .second, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .weekday, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .weekdayOrdinal, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .quarter, for: date), 8) - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .weekOfMonth, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .weekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .yearForWeekOfYear, for: date), 35) - XCTAssertEqual(calendar.ordinality(of: .weekdayOrdinal, in: .nanosecond, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .era, for: date), 8087) - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .year, for: date), 3) - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .month, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .day, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .hour, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .minute, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .second, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .weekday, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .weekdayOrdinal, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .quarter, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .weekOfMonth, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .weekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .yearForWeekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .quarter, in: .nanosecond, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .era, for: date), 105485) - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .year, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .month, for: date), 4) - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .day, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .hour, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .minute, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .second, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .weekday, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .weekdayOrdinal, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .quarter, for: date), 9) - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .weekOfMonth, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .weekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .yearForWeekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfMonth, in: .nanosecond, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .era, for: date), 105485) - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .year, for: date), 35) - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .month, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .day, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .hour, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .minute, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .second, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .weekday, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .weekdayOrdinal, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .quarter, for: date), 9) - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .weekOfMonth, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .weekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .yearForWeekOfYear, for: date), 35) - XCTAssertEqual(calendar.ordinality(of: .weekOfYear, in: .nanosecond, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .era, for: date), 2022) - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .year, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .month, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .day, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .hour, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .minute, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .second, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .weekday, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .weekdayOrdinal, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .quarter, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .weekOfMonth, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .weekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .yearForWeekOfYear, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .yearForWeekOfYear, in: .nanosecond, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .nanosecond, in: .era, for: date), nil) - XCTAssertEqual(calendar.ordinality(of: .nanosecond, in: .year, for: date), 20185358712306977) - XCTAssertEqual(calendar.ordinality(of: .nanosecond, in: .month, for: date), 1868558712306977) - XCTAssertEqual(calendar.ordinality(of: .nanosecond, in: .day, for: date), 54158712306977) - XCTAssertEqual(calendar.ordinality(of: .nanosecond, in: .hour, for: date), 158712306977) - XCTAssertEqual(calendar.ordinality(of: .nanosecond, in: .minute, for: date), 38712306977) - XCTAssertEqual(calendar.ordinality(of: .nanosecond, in: .second, for: date), 712306977) - XCTAssertEqual(calendar.ordinality(of: .nanosecond, in: .weekday, for: date), 54158712306977) - XCTAssertEqual(calendar.ordinality(of: .nanosecond, in: .weekdayOrdinal, for: date), nil) - - XCTAssertEqual(calendar.ordinality(of: .nanosecond, in: .quarter, for: date), 4546958712306977) - XCTAssertEqual(calendar.ordinality(of: .nanosecond, in: .weekOfMonth, for: date), 140558712306977) - XCTAssertEqual(calendar.ordinality(of: .nanosecond, in: .weekOfYear, for: date), 140558712306977) - - let actual = calendar.ordinality(of: .nanosecond, in: .yearForWeekOfYear, for: date) - XCTAssertEqual(actual, 20649600712306977) - XCTAssertEqual(calendar.ordinality(of: .nanosecond, in: .nanosecond, for: date), nil) - } - #endif - - func testStartOf() { - let firstWeekday = 2 - let minimumDaysInFirstWeek = 4 - let timeZone = TimeZone(secondsFromGMT: -3600 * 8)! - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - func test(_ unit: Calendar.Component, at date: Date, expected: Date, file: StaticString = #filePath, line: UInt = #line) { - let new = gregorianCalendar.start(of: unit, at: date)! - XCTAssertEqual(new, expected, file: file, line: line) - } - - var date: Date - date = Date(timeIntervalSince1970: 820483200.0) // 1996-01-01T00:00:00-0800 (1996-01-01T08:00:00Z) - test(.hour, at: date, expected: date) - test(.day, at: date, expected: date) - test(.month, at: date, expected: date) - test(.year, at: date, expected: date) - test(.yearForWeekOfYear, at: date, expected: date) - test(.weekOfYear, at: date, expected: date) - - date = Date(timeIntervalSince1970: 845121787.0) // 1996-10-12T05:03:07-0700 (1996-10-12T12:03:07Z) - test(.second, at: date, expected: Date(timeIntervalSince1970: 845121787.0)) // expect: 1996-10-12 12:03:07 +0000 - test(.minute, at: date, expected: Date(timeIntervalSince1970: 845121780.0)) // expect: 1996-10-12 12:03:00 +0000 - test(.hour, at: date, expected: Date(timeIntervalSince1970: 845121600.0)) // expect: 1996-10-12 12:00:00 +0000 - test(.day, at: date, expected: Date(timeIntervalSince1970: 845107200.0)) // expect: 1996-10-12 08:00:00 +0000 - test(.month, at: date, expected: Date(timeIntervalSince1970: 844156800.0)) // expect: 1996-10-01 08:00:00 +0000 - test(.year, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.yearForWeekOfYear, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.weekOfYear, at: date, expected: Date(timeIntervalSince1970: 844675200.0)) // expect: 1996-10-07 08:00:00 +0000 - test(.weekOfMonth, at: date, expected: Date(timeIntervalSince1970: 844675200.0)) // expect: 1996-10-07 08:00:00 +0000 - test(.weekday, at: date, expected: Date(timeIntervalSince1970: 845107200.0)) // expect: 1996-10-12 08:00:00 +0000 - test(.quarter, at: date, expected: Date(timeIntervalSince1970: 844156800.0)) // expect: 1996-10-01 08:00:00 +0000 - } - - func testStartOf_DST() { - let firstWeekday = 2 - let minimumDaysInFirstWeek = 4 - let timeZone = TimeZone(identifier: "America/Los_Angeles")! - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - func test(_ unit: Calendar.Component, at date: Date, expected: Date, file: StaticString = #filePath, line: UInt = #line) { - let new = gregorianCalendar.start(of: unit, at: date)! - XCTAssertEqual(new, expected, file: file, line: line) - } - - var date: Date - date = Date(timeIntervalSince1970: 820483200.0) // 1996-01-01T00:00:00-0800 (1996-01-01T08:00:00Z) - test(.hour, at: date, expected: date) - test(.day, at: date, expected: date) - test(.month, at: date, expected: date) - test(.year, at: date, expected: date) - test(.yearForWeekOfYear, at: date, expected: date) - test(.weekOfYear, at: date, expected: date) - - date = Date(timeIntervalSince1970: 828867787.0) // 1996-04-07 09:03:07 +0000 - test(.second, at: date, expected: Date(timeIntervalSince1970: 828867787.0)) // expect: 1996-04-07 09:03:07 +0000 - test(.minute, at: date, expected: Date(timeIntervalSince1970: 828867780.0)) // expect: 1996-04-07 09:03:00 +0000 - test(.hour, at: date, expected: Date(timeIntervalSince1970: 828867600.0)) // expect: 1996-04-07 09:00:00 +0000 - test(.day, at: date, expected: Date(timeIntervalSince1970: 828864000.0)) // expect: 1996-04-07 08:00:00 +0000 - test(.month, at: date, expected: Date(timeIntervalSince1970: 828345600.0)) // expect: 1996-04-01 08:00:00 +0000 - test(.year, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.yearForWeekOfYear, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.weekOfYear, at: date, expected: Date(timeIntervalSince1970: 828345600.0)) // expect: 1996-04-01 08:00:00 +0000 - test(.weekOfMonth, at: date, expected: Date(timeIntervalSince1970: 828345600.0)) // expect: 1996-04-01 08:00:00 +0000 - test(.weekday, at: date, expected: Date(timeIntervalSince1970: 828864000.0)) // expect: 1996-04-07 08:00:00 +0000 - test(.quarter, at: date, expected: Date(timeIntervalSince1970: 828345600.0)) // expect: 1996-04-01 08:00:00 +0000 - - date = Date(timeIntervalSince1970: 828871387.0) // 1996-04-07 10:03:07 +0000 - test(.second, at: date, expected: Date(timeIntervalSince1970: 828871387.0)) // expect: 1996-04-07 10:03:07 +0000 - test(.minute, at: date, expected: Date(timeIntervalSince1970: 828871380.0)) // expect: 1996-04-07 10:03:00 +0000 - test(.hour, at: date, expected: Date(timeIntervalSince1970: 828871200.0)) // expect: 1996-04-07 10:00:00 +0000 - test(.day, at: date, expected: Date(timeIntervalSince1970: 828864000.0)) // expect: 1996-04-07 08:00:00 +0000 - test(.month, at: date, expected: Date(timeIntervalSince1970: 828345600.0)) // expect: 1996-04-01 08:00:00 +0000 - test(.year, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.yearForWeekOfYear, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.weekOfYear, at: date, expected: Date(timeIntervalSince1970: 828345600.0)) // expect: 1996-04-01 08:00:00 +0000 - test(.weekOfMonth, at: date, expected: Date(timeIntervalSince1970: 828345600.0)) // expect: 1996-04-01 08:00:00 +0000 - test(.weekday, at: date, expected: Date(timeIntervalSince1970: 828864000.0)) // expect: 1996-04-07 08:00:00 +0000 - test(.quarter, at: date, expected: Date(timeIntervalSince1970: 828345600.0)) // expect: 1996-04-01 08:00:00 +0000 - - date = Date(timeIntervalSince1970: 828874987.0) // 1996-04-07 11:03:07 +0000 - test(.second, at: date, expected: Date(timeIntervalSince1970: 828874987.0)) // expect: 1996-04-07 11:03:07 +0000 - test(.minute, at: date, expected: Date(timeIntervalSince1970: 828874980.0)) // expect: 1996-04-07 11:03:00 +0000 - test(.hour, at: date, expected: Date(timeIntervalSince1970: 828874800.0)) // expect: 1996-04-07 11:00:00 +0000 - test(.day, at: date, expected: Date(timeIntervalSince1970: 828864000.0)) // expect: 1996-04-07 08:00:00 +0000 - test(.month, at: date, expected: Date(timeIntervalSince1970: 828345600.0)) // expect: 1996-04-01 08:00:00 +0000 - test(.year, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.yearForWeekOfYear, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.weekOfYear, at: date, expected: Date(timeIntervalSince1970: 828345600.0)) // expect: 1996-04-01 08:00:00 +0000 - test(.weekOfMonth, at: date, expected: Date(timeIntervalSince1970: 828345600.0)) // expect: 1996-04-01 08:00:00 +0000 - test(.weekday, at: date, expected: Date(timeIntervalSince1970: 828864000.0)) // expect: 1996-04-07 08:00:00 +0000 - test(.quarter, at: date, expected: Date(timeIntervalSince1970: 828345600.0)) // expect: 1996-04-01 08:00:00 +0000 - - date = Date(timeIntervalSince1970: 846414187.0) // 1996-10-27 11:03:07 +0000 - test(.second, at: date, expected: Date(timeIntervalSince1970: 846414187.0)) // expect: 1996-10-27 11:03:07 +0000 - test(.minute, at: date, expected: Date(timeIntervalSince1970: 846414180.0)) // expect: 1996-10-27 11:03:00 +0000 - test(.hour, at: date, expected: Date(timeIntervalSince1970: 846414000.0)) // expect: 1996-10-27 11:00:00 +0000 - test(.day, at: date, expected: Date(timeIntervalSince1970: 846399600.0)) // expect: 1996-10-27 07:00:00 +0000 - test(.month, at: date, expected: Date(timeIntervalSince1970: 844153200.0)) // expect: 1996-10-01 07:00:00 +0000 - test(.year, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.yearForWeekOfYear, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.weekOfYear, at: date, expected: Date(timeIntervalSince1970: 845881200.0)) // expect: 1996-10-21 07:00:00 +0000 - test(.weekOfMonth, at: date, expected: Date(timeIntervalSince1970: 845881200.0)) // expect: 1996-10-21 07:00:00 +0000 - test(.weekday, at: date, expected: Date(timeIntervalSince1970: 846399600.0)) // expect: 1996-10-27 07:00:00 +0000 - test(.quarter, at: date, expected: Date(timeIntervalSince1970: 844153200.0)) // expect: 1996-10-01 07:00:00 +0000 - - date = Date(timeIntervalSince1970: 846410587.0) // 1996-10-27 10:03:07 +0000 - test(.second, at: date, expected: Date(timeIntervalSince1970: 846410587.0)) // expect: 1996-10-27 10:03:07 +0000 - test(.minute, at: date, expected: Date(timeIntervalSince1970: 846410580.0)) // expect: 1996-10-27 10:03:00 +0000 - test(.hour, at: date, expected: Date(timeIntervalSince1970: 846410400.0)) // expect: 1996-10-27 10:00:00 +0000 - test(.day, at: date, expected: Date(timeIntervalSince1970: 846399600.0)) // expect: 1996-10-27 07:00:00 +0000 - test(.month, at: date, expected: Date(timeIntervalSince1970: 844153200.0)) // expect: 1996-10-01 07:00:00 +0000 - test(.year, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.yearForWeekOfYear, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.weekOfYear, at: date, expected: Date(timeIntervalSince1970: 845881200.0)) // expect: 1996-10-21 07:00:00 +0000 - test(.weekOfMonth, at: date, expected: Date(timeIntervalSince1970: 845881200.0)) // expect: 1996-10-21 07:00:00 +0000 - test(.weekday, at: date, expected: Date(timeIntervalSince1970: 846399600.0)) // expect: 1996-10-27 07:00:00 +0000 - test(.quarter, at: date, expected: Date(timeIntervalSince1970: 844153200.0)) // expect: 1996-10-01 07:00:00 +0000 - - date = Date(timeIntervalSince1970: 846406987.0) // 1996-10-27 09:03:07 +0000 - test(.second, at: date, expected: Date(timeIntervalSince1970: 846406987.0)) // expect: 1996-10-27 09:03:07 +0000 - test(.minute, at: date, expected: Date(timeIntervalSince1970: 846406980.0)) // expect: 1996-10-27 09:03:00 +0000 - test(.hour, at: date, expected: Date(timeIntervalSince1970: 846406800.0)) // expect: 1996-10-27 09:00:00 +0000 - test(.day, at: date, expected: Date(timeIntervalSince1970: 846399600.0)) // expect: 1996-10-27 07:00:00 +0000 - test(.month, at: date, expected: Date(timeIntervalSince1970: 844153200.0)) // expect: 1996-10-01 07:00:00 +0000 - test(.year, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.yearForWeekOfYear, at: date, expected: Date(timeIntervalSince1970: 820483200.0)) // expect: 1996-01-01 08:00:00 +0000 - test(.weekOfYear, at: date, expected: Date(timeIntervalSince1970: 845881200.0)) // expect: 1996-10-21 07:00:00 +0000 - test(.weekOfMonth, at: date, expected: Date(timeIntervalSince1970: 845881200.0)) // expect: 1996-10-21 07:00:00 +0000 - test(.weekday, at: date, expected: Date(timeIntervalSince1970: 846399600.0)) // expect: 1996-10-27 07:00:00 +0000 - test(.quarter, at: date, expected: Date(timeIntervalSince1970: 844153200.0)) // expect: 1996-10-01 07:00:00 +0000 - } - - // MARK: - Weekend - - func testIsDateInWeekend() { - let c = _CalendarGregorian(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: 1, minimumDaysInFirstWeek: 1, gregorianStartDate: nil) - - let sat0000_mon0000 = WeekendRange(onsetTime: 0, ceaseTime: 0, start: 7, end: 2) // Sat 00:00:00 ..< Mon 00:00:00 - let sat1200_sun1200 = WeekendRange(onsetTime: 43200, ceaseTime: 43200, start: 7, end: 1) // Sat 12:00:00 ..< Sun 12:00:00 - let sat_sun = WeekendRange(onsetTime: 0, ceaseTime: 86400, start: 7, end: 1) // Sat 00:00:00 ... Sun 23:59:59 - let mon = WeekendRange(onsetTime: 0, ceaseTime: 86400, start: 2, end: 2) - let sunPM = WeekendRange(onsetTime: 43200, ceaseTime: 86400, start: 1, end: 1) // Sun 12:00:00 ... Sun 23:59:59 - let mon_tue = WeekendRange(onsetTime: 0, ceaseTime: 86400, start: 2, end: 3) // Mon 00:00:00 ... Tue 23:59:59 - - var date = Date(timeIntervalSince1970: 846320587) // 1996-10-26, Sat 09:03:07 - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat0000_mon0000)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: sat1200_sun1200)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat_sun)) - - date = Date(timeIntervalSince1970: 846406987.0) // 1996-10-27, Sun 09:03:07 - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat0000_mon0000)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat1200_sun1200)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat_sun)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: sunPM)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: mon)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: mon_tue)) - - date = Date(timeIntervalSince1970: 846450187) // 1996-10-27, Sun 19:03:07 - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat0000_mon0000)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: sat1200_sun1200)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat_sun)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sunPM)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: mon)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: mon_tue)) - - date = Date(timeIntervalSince1970: 846536587) // 1996-10-28, Mon 19:03:07 - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: sat0000_mon0000)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: sat1200_sun1200)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: sat_sun)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: sunPM)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: mon)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: mon_tue)) - } - - func testIsDateInWeekend_wholeDays() { - let c = _CalendarGregorian(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: 1, minimumDaysInFirstWeek: 1, gregorianStartDate: nil) - - let sat_mon = WeekendRange(start: 7, end: 2) - let sat_sun = WeekendRange(start: 7, end: 1) - let mon = WeekendRange(start: 2, end: 2) - let sun = WeekendRange(start: 1, end: 1) - let mon_tue = WeekendRange(start: 2, end: 3) - - var date = Date(timeIntervalSince1970: 846320587) // 1996-10-26, Sat 09:03:07 - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat_mon)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat_sun)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: sun)) - - date = Date(timeIntervalSince1970: 846406987.0) // 1996-10-27, Sun 09:03:07 - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat_mon)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat_sun)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sun)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: mon)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: mon_tue)) - - date = Date(timeIntervalSince1970: 846450187) // 1996-10-27, Sun 19:03:07 - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat_mon)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat_sun)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sun)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: mon)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: mon_tue)) - - date = Date(timeIntervalSince1970: 846536587) // 1996-10-28, Mon 19:03:07 - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: sat_mon)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: sat_sun)) - XCTAssertFalse(c.isDateInWeekend(date, weekendRange: sun)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: mon)) - XCTAssertTrue(c.isDateInWeekend(date, weekendRange: mon_tue)) - } - - // MARK: - DateInterval - - func testDateInterval() { - let calendar = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(secondsFromGMT: -28800)!, locale: nil, firstWeekday: 3, minimumDaysInFirstWeek: 5, gregorianStartDate: nil) - - func test(_ c: Calendar.Component, _ date: Date, expectedStart start: Date?, end: Date?, file: StaticString = #filePath, line: UInt = #line) { - let new = calendar.dateInterval(of: c, for: date) - let new_start = new?.start - let new_end = new?.end - - XCTAssertEqual(new_start, start, "interval start did not match", file: file, line: line) - XCTAssertEqual(new_end, end, "interval end did not match", file: file, line: line) - } - - var date: Date - date = Date(timeIntervalSince1970: 820454400.0) // 1995-12-31T16:00:00-0800 (1996-01-01T00:00:00Z) - test(.era, date, expectedStart: Date(timeIntervalSince1970: -62135596800.0), end: Date(timeIntervalSince1970: 4335910914304.0)) - test(.year, date, expectedStart: Date(timeIntervalSince1970: 788947200.0), end: Date(timeIntervalSince1970: 820483200.0)) - test(.month, date, expectedStart: Date(timeIntervalSince1970: 817804800.0), end: Date(timeIntervalSince1970: 820483200.0)) - test(.day, date, expectedStart: Date(timeIntervalSince1970: 820396800.0), end: Date(timeIntervalSince1970: 820483200.0)) - test(.hour, date, expectedStart: Date(timeIntervalSince1970: 820454400.0), end: Date(timeIntervalSince1970: 820458000.0)) - test(.minute, date, expectedStart: Date(timeIntervalSince1970: 820454400.0), end: Date(timeIntervalSince1970: 820454460.0)) - test(.second, date, expectedStart: Date(timeIntervalSince1970: 820454400.0), end: Date(timeIntervalSince1970: 820454401.0)) - test(.nanosecond, date, expectedStart: Date(timeIntervalSince1970: 820454400.0), end: Date(timeIntervalSince1970: 820454400.0)) - test(.weekday, date, expectedStart: Date(timeIntervalSince1970: 820396800.0), end: Date(timeIntervalSince1970: 820483200.0)) - test(.weekdayOrdinal, date, expectedStart: Date(timeIntervalSince1970: 820396800.0), end: Date(timeIntervalSince1970: 820483200.0)) - test(.quarter, date, expectedStart: Date(timeIntervalSince1970: 812534400.0), end: Date(timeIntervalSince1970: 820483200.0)) - test(.weekOfMonth, date, expectedStart: Date(timeIntervalSince1970: 819964800.0), end: Date(timeIntervalSince1970: 820569600.0)) - test(.weekOfYear, date, expectedStart: Date(timeIntervalSince1970: 819964800.0), end: Date(timeIntervalSince1970: 820569600.0)) - test(.yearForWeekOfYear, date, expectedStart: Date(timeIntervalSince1970: 789120000.0), end: Date(timeIntervalSince1970: 820569600.0)) - - date = Date(timeIntervalSince1970: 857174400.0) // 1997-02-28T16:00:00-0800 (1997-03-01T00:00:00Z) - test(.era, date, expectedStart: Date(timeIntervalSince1970: -62135596800.0), end: Date(timeIntervalSince1970: 4335910914304.0)) - test(.year, date, expectedStart: Date(timeIntervalSince1970: 852105600.0), end: Date(timeIntervalSince1970: 883641600.0)) - test(.month, date, expectedStart: Date(timeIntervalSince1970: 854784000.0), end: Date(timeIntervalSince1970: 857203200.0)) - test(.day, date, expectedStart: Date(timeIntervalSince1970: 857116800.0), end: Date(timeIntervalSince1970: 857203200.0)) - test(.hour, date, expectedStart: Date(timeIntervalSince1970: 857174400.0), end: Date(timeIntervalSince1970: 857178000.0)) - test(.minute, date, expectedStart: Date(timeIntervalSince1970: 857174400.0), end: Date(timeIntervalSince1970: 857174460.0)) - test(.second, date, expectedStart: Date(timeIntervalSince1970: 857174400.0), end: Date(timeIntervalSince1970: 857174401.0)) - test(.weekday, date, expectedStart: Date(timeIntervalSince1970: 857116800.0), end: Date(timeIntervalSince1970: 857203200.0)) - test(.weekdayOrdinal, date, expectedStart: Date(timeIntervalSince1970: 857116800.0), end: Date(timeIntervalSince1970: 857203200.0)) - test(.quarter, date, expectedStart: Date(timeIntervalSince1970: 852105600.0), end: Date(timeIntervalSince1970: 859881600.0)) - test(.weekOfMonth, date, expectedStart: Date(timeIntervalSince1970: 856857600.0), end: Date(timeIntervalSince1970: 857462400.0)) - test(.weekOfYear, date, expectedStart: Date(timeIntervalSince1970: 856857600.0), end: Date(timeIntervalSince1970: 857462400.0)) - test(.yearForWeekOfYear, date, expectedStart: Date(timeIntervalSince1970: 852019200.0), end: Date(timeIntervalSince1970: 883468800.0)) - - date = Date(timeIntervalSince1970: -62135769600.0) // 0001-12-31T16:00:00-0800 (0001-01-01T00:00:00Z) - test(.era, date, expectedStart: Date(timeIntervalSince1970: -4460182107904.0), end: Date(timeIntervalSince1970: -62135596800.0)) - test(.year, date, expectedStart: Date(timeIntervalSince1970: -62167363200.0), end: Date(timeIntervalSince1970: -62135740800.0)) - test(.month, date, expectedStart: Date(timeIntervalSince1970: -62138419200.0), end: Date(timeIntervalSince1970: -62135740800.0)) - test(.day, date, expectedStart: Date(timeIntervalSince1970: -62135827200.0), end: Date(timeIntervalSince1970: -62135740800.0)) - test(.hour, date, expectedStart: Date(timeIntervalSince1970: -62135769600.0), end: Date(timeIntervalSince1970: -62135766000.0)) - test(.minute, date, expectedStart: Date(timeIntervalSince1970: -62135769600.0), end: Date(timeIntervalSince1970: -62135769540.0)) - test(.second, date, expectedStart: Date(timeIntervalSince1970: -62135769600.0), end: Date(timeIntervalSince1970: -62135769599.0)) - test(.nanosecond, date, expectedStart: Date(timeIntervalSince1970: -62135769600.00001), end: Date(timeIntervalSince1970: -62135769600.00001)) - test(.weekday, date, expectedStart: Date(timeIntervalSince1970: -62135827200.0), end: Date(timeIntervalSince1970: -62135740800.0)) - test(.weekdayOrdinal, date, expectedStart: Date(timeIntervalSince1970: -62135827200.0), end: Date(timeIntervalSince1970: -62135740800.0)) - test(.quarter, date, expectedStart: Date(timeIntervalSince1970: -62143689600.0), end: Date(timeIntervalSince1970: -62135740800.0)) - test(.weekOfMonth, date, expectedStart: Date(timeIntervalSince1970: -62136086400.0), end: Date(timeIntervalSince1970: -62135481600.0)) - test(.weekOfYear, date, expectedStart: Date(timeIntervalSince1970: -62136086400.0), end: Date(timeIntervalSince1970: -62135481600.0)) - test(.yearForWeekOfYear, date, expectedStart: nil, end: nil) - } - - func testDateInterval_DST() { - let calendar = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(identifier: "America/Los_Angeles")!, locale: nil, firstWeekday: 3, minimumDaysInFirstWeek: 5, gregorianStartDate: nil) - func test(_ c: Calendar.Component, _ date: Date, expectedStart start: Date, end: Date, file: StaticString = #filePath, line: UInt = #line) { - let new = calendar.dateInterval(of: c, for: date)! - let new_start = new.start - let new_end = new.end - let delta = 0.005 - XCTAssertEqual(Double(new_start.timeIntervalSinceReferenceDate), Double(start.timeIntervalSinceReferenceDate), accuracy: delta, file: file, line: line) - XCTAssertEqual(Double(new_end.timeIntervalSinceReferenceDate), Double(end.timeIntervalSinceReferenceDate), accuracy: delta, file: file, line: line) - } - var date: Date - date = Date(timeIntervalSince1970: 828867787.0) // 1996-04-07T01:03:07-0800 (1996-04-07T09:03:07Z) - test(.era, date, expectedStart: Date(timeIntervalSince1970: -62135596800.0), end: Date(timeIntervalSince1970: 4335910914304.0)) - test(.year, date, expectedStart: Date(timeIntervalSince1970: 820483200.0), end: Date(timeIntervalSince1970: 852105600.0)) - test(.month, date, expectedStart: Date(timeIntervalSince1970: 828345600.0), end: Date(timeIntervalSince1970: 830934000.0)) - test(.day, date, expectedStart: Date(timeIntervalSince1970: 828864000.0), end: Date(timeIntervalSince1970: 828946800.0)) - test(.hour, date, expectedStart: Date(timeIntervalSince1970: 828867600.0), end: Date(timeIntervalSince1970: 828871200.0)) - test(.minute, date, expectedStart: Date(timeIntervalSince1970: 828867780.0), end: Date(timeIntervalSince1970: 828867840.0)) - test(.second, date, expectedStart: Date(timeIntervalSince1970: 828867787.0), end: Date(timeIntervalSince1970: 828867788.0)) - test(.nanosecond, date, expectedStart: Date(timeIntervalSince1970: 828867787.0), end: Date(timeIntervalSince1970: 828867787.0)) - test(.weekday, date, expectedStart: Date(timeIntervalSince1970: 828864000.0), end: Date(timeIntervalSince1970: 828946800.0)) - test(.weekdayOrdinal, date, expectedStart: Date(timeIntervalSince1970: 828864000.0), end: Date(timeIntervalSince1970: 828946800.0)) - test(.quarter, date, expectedStart: Date(timeIntervalSince1970: 828345600.0), end: Date(timeIntervalSince1970: 836204400.0)) - test(.weekOfMonth, date, expectedStart: Date(timeIntervalSince1970: 828432000.0), end: Date(timeIntervalSince1970: 829033200.0)) - test(.weekOfYear, date, expectedStart: Date(timeIntervalSince1970: 828432000.0), end: Date(timeIntervalSince1970: 829033200.0)) - test(.yearForWeekOfYear, date, expectedStart: Date(timeIntervalSince1970: 820569600.0), end: Date(timeIntervalSince1970: 852019200.0)) - - date = Date(timeIntervalSince1970: 828871387.0) // 1996-04-07T03:03:07-0700 (1996-04-07T10:03:07Z) - test(.era, date, expectedStart: Date(timeIntervalSince1970: -62135596800.0), end: Date(timeIntervalSince1970: 4335910914304.0)) - test(.year, date, expectedStart: Date(timeIntervalSince1970: 820483200.0), end: Date(timeIntervalSince1970: 852105600.0)) - test(.month, date, expectedStart: Date(timeIntervalSince1970: 828345600.0), end: Date(timeIntervalSince1970: 830934000.0)) - test(.day, date, expectedStart: Date(timeIntervalSince1970: 828864000.0), end: Date(timeIntervalSince1970: 828946800.0)) - test(.hour, date, expectedStart: Date(timeIntervalSince1970: 828871200.0), end: Date(timeIntervalSince1970: 828874800.0)) - test(.minute, date, expectedStart: Date(timeIntervalSince1970: 828871380.0), end: Date(timeIntervalSince1970: 828871440.0)) - test(.second, date, expectedStart: Date(timeIntervalSince1970: 828871387.0), end: Date(timeIntervalSince1970: 828871388.0)) - test(.nanosecond, date, expectedStart: Date(timeIntervalSince1970: 828871387.0), end: Date(timeIntervalSince1970: 828871387.0)) - test(.weekday, date, expectedStart: Date(timeIntervalSince1970: 828864000.0), end: Date(timeIntervalSince1970: 828946800.0)) - test(.weekdayOrdinal, date, expectedStart: Date(timeIntervalSince1970: 828864000.0), end: Date(timeIntervalSince1970: 828946800.0)) - test(.quarter, date, expectedStart: Date(timeIntervalSince1970: 828345600.0), end: Date(timeIntervalSince1970: 836204400.0)) - test(.weekOfMonth, date, expectedStart: Date(timeIntervalSince1970: 828432000.0), end: Date(timeIntervalSince1970: 829033200.0)) - test(.weekOfYear, date, expectedStart: Date(timeIntervalSince1970: 828432000.0), end: Date(timeIntervalSince1970: 829033200.0)) - test(.yearForWeekOfYear, date, expectedStart: Date(timeIntervalSince1970: 820569600.0), end: Date(timeIntervalSince1970: 852019200.0)) - - date = Date(timeIntervalSince1970: 828874987.0) // 1996-04-07T04:03:07-0700 (1996-04-07T11:03:07Z) - test(.era, date, expectedStart: Date(timeIntervalSince1970: -62135596800.0), end: Date(timeIntervalSince1970: 4335910914304.0)) - test(.year, date, expectedStart: Date(timeIntervalSince1970: 820483200.0), end: Date(timeIntervalSince1970: 852105600.0)) - test(.month, date, expectedStart: Date(timeIntervalSince1970: 828345600.0), end: Date(timeIntervalSince1970: 830934000.0)) - test(.day, date, expectedStart: Date(timeIntervalSince1970: 828864000.0), end: Date(timeIntervalSince1970: 828946800.0)) - test(.hour, date, expectedStart: Date(timeIntervalSince1970: 828874800.0), end: Date(timeIntervalSince1970: 828878400.0)) - test(.minute, date, expectedStart: Date(timeIntervalSince1970: 828874980.0), end: Date(timeIntervalSince1970: 828875040.0)) - test(.second, date, expectedStart: Date(timeIntervalSince1970: 828874987.0), end: Date(timeIntervalSince1970: 828874988.0)) - test(.nanosecond, date, expectedStart: Date(timeIntervalSince1970: 828874987.0), end: Date(timeIntervalSince1970: 828874987.0)) - test(.weekday, date, expectedStart: Date(timeIntervalSince1970: 828864000.0), end: Date(timeIntervalSince1970: 828946800.0)) - test(.weekdayOrdinal, date, expectedStart: Date(timeIntervalSince1970: 828864000.0), end: Date(timeIntervalSince1970: 828946800.0)) - test(.quarter, date, expectedStart: Date(timeIntervalSince1970: 828345600.0), end: Date(timeIntervalSince1970: 836204400.0)) - test(.weekOfMonth, date, expectedStart: Date(timeIntervalSince1970: 828432000.0), end: Date(timeIntervalSince1970: 829033200.0)) - test(.weekOfYear, date, expectedStart: Date(timeIntervalSince1970: 828432000.0), end: Date(timeIntervalSince1970: 829033200.0)) - test(.yearForWeekOfYear, date, expectedStart: Date(timeIntervalSince1970: 820569600.0), end: Date(timeIntervalSince1970: 852019200.0)) - - date = Date(timeIntervalSince1970: 846406987.0) // 1996-10-27T01:03:07-0800 (1996-10-27T09:03:07Z) - test(.era, date, expectedStart: Date(timeIntervalSince1970: -62135596800.0), end: Date(timeIntervalSince1970: 4335910914304.0)) - test(.year, date, expectedStart: Date(timeIntervalSince1970: 820483200.0), end: Date(timeIntervalSince1970: 852105600.0)) - test(.month, date, expectedStart: Date(timeIntervalSince1970: 844153200.0), end: Date(timeIntervalSince1970: 846835200.0)) - test(.day, date, expectedStart: Date(timeIntervalSince1970: 846399600.0), end: Date(timeIntervalSince1970: 846489600.0)) - test(.hour, date, expectedStart: Date(timeIntervalSince1970: 846406800.0), end: Date(timeIntervalSince1970: 846410400.0)) - test(.minute, date, expectedStart: Date(timeIntervalSince1970: 846406980.0), end: Date(timeIntervalSince1970: 846407040.0)) - test(.second, date, expectedStart: Date(timeIntervalSince1970: 846406987.0), end: Date(timeIntervalSince1970: 846406988.0)) - test(.nanosecond, date, expectedStart: Date(timeIntervalSince1970: 846406987.0), end: Date(timeIntervalSince1970: 846406987.0)) - test(.weekday, date, expectedStart: Date(timeIntervalSince1970: 846399600.0), end: Date(timeIntervalSince1970: 846489600.0)) - test(.weekdayOrdinal, date, expectedStart: Date(timeIntervalSince1970: 846399600.0), end: Date(timeIntervalSince1970: 846489600.0)) - test(.quarter, date, expectedStart: Date(timeIntervalSince1970: 844153200.0), end: Date(timeIntervalSince1970: 852105600.0)) - test(.weekOfMonth, date, expectedStart: Date(timeIntervalSince1970: 845967600.0), end: Date(timeIntervalSince1970: 846576000.0)) - test(.weekOfYear, date, expectedStart: Date(timeIntervalSince1970: 845967600.0), end: Date(timeIntervalSince1970: 846576000.0)) - test(.yearForWeekOfYear, date, expectedStart: Date(timeIntervalSince1970: 820569600.0), end: Date(timeIntervalSince1970: 852019200.0)) - - date = Date(timeIntervalSince1970: 846410587.0) // 1996-10-27T02:03:07-0800 (1996-10-27T10:03:07Z) - test(.era, date, expectedStart: Date(timeIntervalSince1970: -62135596800.0), end: Date(timeIntervalSince1970: 4335910914304.0)) - test(.year, date, expectedStart: Date(timeIntervalSince1970: 820483200.0), end: Date(timeIntervalSince1970: 852105600.0)) - test(.month, date, expectedStart: Date(timeIntervalSince1970: 844153200.0), end: Date(timeIntervalSince1970: 846835200.0)) - test(.day, date, expectedStart: Date(timeIntervalSince1970: 846399600.0), end: Date(timeIntervalSince1970: 846489600.0)) - test(.hour, date, expectedStart: Date(timeIntervalSince1970: 846410400.0), end: Date(timeIntervalSince1970: 846414000.0)) - test(.minute, date, expectedStart: Date(timeIntervalSince1970: 846410580.0), end: Date(timeIntervalSince1970: 846410640.0)) - test(.second, date, expectedStart: Date(timeIntervalSince1970: 846410587.0), end: Date(timeIntervalSince1970: 846410588.0)) - test(.nanosecond, date, expectedStart: Date(timeIntervalSince1970: 846410587.0), end: Date(timeIntervalSince1970: 846410587.0)) - test(.weekday, date, expectedStart: Date(timeIntervalSince1970: 846399600.0), end: Date(timeIntervalSince1970: 846489600.0)) - test(.weekdayOrdinal, date, expectedStart: Date(timeIntervalSince1970: 846399600.0), end: Date(timeIntervalSince1970: 846489600.0)) - test(.quarter, date, expectedStart: Date(timeIntervalSince1970: 844153200.0), end: Date(timeIntervalSince1970: 852105600.0)) - test(.weekOfMonth, date, expectedStart: Date(timeIntervalSince1970: 845967600.0), end: Date(timeIntervalSince1970: 846576000.0)) - test(.weekOfYear, date, expectedStart: Date(timeIntervalSince1970: 845967600.0), end: Date(timeIntervalSince1970: 846576000.0)) - test(.yearForWeekOfYear, date, expectedStart: Date(timeIntervalSince1970: 820569600.0), end: Date(timeIntervalSince1970: 852019200.0)) - - date = Date(timeIntervalSince1970: 846414187.0) // 1996-10-27T03:03:07-0800 (1996-10-27T11:03:07Z) - test(.era, date, expectedStart: Date(timeIntervalSince1970: -62135596800.0), end: Date(timeIntervalSince1970: 4335910914304.0)) - test(.year, date, expectedStart: Date(timeIntervalSince1970: 820483200.0), end: Date(timeIntervalSince1970: 852105600.0)) - test(.month, date, expectedStart: Date(timeIntervalSince1970: 844153200.0), end: Date(timeIntervalSince1970: 846835200.0)) - test(.day, date, expectedStart: Date(timeIntervalSince1970: 846399600.0), end: Date(timeIntervalSince1970: 846489600.0)) - test(.hour, date, expectedStart: Date(timeIntervalSince1970: 846414000.0), end: Date(timeIntervalSince1970: 846417600.0)) - test(.minute, date, expectedStart: Date(timeIntervalSince1970: 846414180.0), end: Date(timeIntervalSince1970: 846414240.0)) - test(.second, date, expectedStart: Date(timeIntervalSince1970: 846414187.0), end: Date(timeIntervalSince1970: 846414188.0)) - test(.nanosecond, date, expectedStart: Date(timeIntervalSince1970: 846414187.0), end: Date(timeIntervalSince1970: 846414187.0)) - test(.weekday, date, expectedStart: Date(timeIntervalSince1970: 846399600.0), end: Date(timeIntervalSince1970: 846489600.0)) - test(.weekdayOrdinal, date, expectedStart: Date(timeIntervalSince1970: 846399600.0), end: Date(timeIntervalSince1970: 846489600.0)) - test(.quarter, date, expectedStart: Date(timeIntervalSince1970: 844153200.0), end: Date(timeIntervalSince1970: 852105600.0)) - test(.weekOfMonth, date, expectedStart: Date(timeIntervalSince1970: 845967600.0), end: Date(timeIntervalSince1970: 846576000.0)) - test(.weekOfYear, date, expectedStart: Date(timeIntervalSince1970: 845967600.0), end: Date(timeIntervalSince1970: 846576000.0)) - test(.yearForWeekOfYear, date, expectedStart: Date(timeIntervalSince1970: 820569600.0), end: Date(timeIntervalSince1970: 852019200.0)) - - date = Date(timeIntervalSince1970: 845121787.0) // 1996-10-12T05:03:07-0700 (1996-10-12T12:03:07Z) - test(.era, date, expectedStart: Date(timeIntervalSince1970: -62135596800.0), end: Date(timeIntervalSince1970: 4335910914304.0)) - test(.year, date, expectedStart: Date(timeIntervalSince1970: 820483200.0), end: Date(timeIntervalSince1970: 852105600.0)) - test(.month, date, expectedStart: Date(timeIntervalSince1970: 844153200.0), end: Date(timeIntervalSince1970: 846835200.0)) - test(.day, date, expectedStart: Date(timeIntervalSince1970: 845103600.0), end: Date(timeIntervalSince1970: 845190000.0)) - test(.hour, date, expectedStart: Date(timeIntervalSince1970: 845121600.0), end: Date(timeIntervalSince1970: 845125200.0)) - test(.minute, date, expectedStart: Date(timeIntervalSince1970: 845121780.0), end: Date(timeIntervalSince1970: 845121840.0)) - test(.second, date, expectedStart: Date(timeIntervalSince1970: 845121787.0), end: Date(timeIntervalSince1970: 845121788.0)) - test(.nanosecond, date, expectedStart: Date(timeIntervalSince1970: 845121787.0), end: Date(timeIntervalSince1970: 845121787.0)) - test(.weekday, date, expectedStart: Date(timeIntervalSince1970: 845103600.0), end: Date(timeIntervalSince1970: 845190000.0)) - test(.weekdayOrdinal, date, expectedStart: Date(timeIntervalSince1970: 845103600.0), end: Date(timeIntervalSince1970: 845190000.0)) - test(.quarter, date, expectedStart: Date(timeIntervalSince1970: 844153200.0), end: Date(timeIntervalSince1970: 852105600.0)) - test(.weekOfMonth, date, expectedStart: Date(timeIntervalSince1970: 844758000.0), end: Date(timeIntervalSince1970: 845362800.0)) - test(.weekOfYear, date, expectedStart: Date(timeIntervalSince1970: 844758000.0), end: Date(timeIntervalSince1970: 845362800.0)) - test(.yearForWeekOfYear, date, expectedStart: Date(timeIntervalSince1970: 820569600.0), end: Date(timeIntervalSince1970: 852019200.0)) - } - - // MARK: - Day Of Year - func test_dayOfYear() throws { - // An arbitrary date, for which we know the answers - let date = Date(timeIntervalSinceReferenceDate: 682898558) // 2022-08-22 22:02:38 UTC, day 234 - let leapYearDate = Date(timeIntervalSinceReferenceDate: 745891200) // 2024-08-21 00:00:00 UTC, day 234 - let cal = _CalendarGregorian(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - // Ordinality - XCTAssertEqual(cal.ordinality(of: .dayOfYear, in: .year, for: date), 234) - XCTAssertEqual(cal.ordinality(of: .hour, in: .dayOfYear, for: date), 23) - XCTAssertEqual(cal.ordinality(of: .minute, in: .dayOfYear, for: date), 1323) - XCTAssertEqual(cal.ordinality(of: .second, in: .dayOfYear, for: date), 79359) - - // Nonsense ordinalities. Since day of year is already relative, we don't count the Nth day of year in an era. - XCTAssertEqual(cal.ordinality(of: .dayOfYear, in: .era, for: date), nil) - XCTAssertEqual(cal.ordinality(of: .year, in: .dayOfYear, for: date), nil) - - // Interval - let interval = cal.dateInterval(of: .dayOfYear, for: date) - XCTAssertEqual(interval, DateInterval(start: Date(timeIntervalSinceReferenceDate: 682819200), duration: 86400)) - - // Specific component values - XCTAssertEqual(cal.dateComponent(.dayOfYear, from: date), 234) - - - // Ranges - let min = cal.minimumRange(of: .dayOfYear) - let max = cal.maximumRange(of: .dayOfYear) - XCTAssertEqual(min, 1..<366) // hard coded for gregorian - XCTAssertEqual(max, 1..<367) - - XCTAssertEqual(cal.range(of: .dayOfYear, in: .year, for: date), 1..<366) - XCTAssertEqual(cal.range(of: .dayOfYear, in: .year, for: leapYearDate), 1..<367) - - // Addition - let d1 = try cal.add(.dayOfYear, to: date, amount: 1, inTimeZone: .gmt) - XCTAssertEqual(d1, date + 86400) - - let d2 = try cal.addAndWrap(.dayOfYear, to: date, amount: 365, inTimeZone: .gmt) - XCTAssertEqual(d2, date) - - // Conversion from DateComponents - var dc = DateComponents(year: 2022, hour: 22, minute: 2, second: 38) - dc.dayOfYear = 234 - let d = cal.date(from: dc) - XCTAssertEqual(d, date) - - var subtractMe = DateComponents() - subtractMe.dayOfYear = -1 - let firstDay = Date(timeIntervalSinceReferenceDate: 662688000) - let previousDay = cal.date(byAdding: subtractMe, to:firstDay, wrappingComponents: false) - XCTAssertNotNil(previousDay) - let previousDayComps = cal.dateComponents([.year, .dayOfYear], from: previousDay!) - var previousDayExpectationComps = DateComponents() - previousDayExpectationComps.year = 2021 - previousDayExpectationComps.dayOfYear = 365 - XCTAssertEqual(previousDayComps, previousDayExpectationComps) - } - - // MARK: - Range of - - func testRangeOf() { - let calendar = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(secondsFromGMT: -28800)!, locale: nil, firstWeekday: 1, minimumDaysInFirstWeek: 4, gregorianStartDate: nil) - - func test(_ small: Calendar.Component, in large: Calendar.Component, for date: Date, expected: Range?, file: StaticString = #filePath, line: UInt = #line) { - let new = calendar.range(of: small, in: large, for: date) - XCTAssertEqual(new, expected, file: file, line: line) - } - - var date: Date - date = Date(timeIntervalSince1970: 820454400.0) // 1995-12-31T16:00:00-0800 (1996-01-01T00:00:00Z) - test(.month, in: .quarter, for: date, expected: 10..<13) - test(.day, in: .quarter, for: date, expected: 1..<93) - test(.weekday, in: .quarter, for: date, expected: 1..<8) - test(.weekdayOrdinal, in: .quarter, for: date, expected: 1..<16) - test(.weekOfMonth, in: .quarter, for: date, expected: 0..<15) - test(.weekOfYear, in: .quarter, for: date, expected: 40..<54) - test(.day, in: .weekOfYear, for: date, expected: nil) - test(.month, in: .yearForWeekOfYear, for: date, expected: nil) - test(.quarter, in: .yearForWeekOfYear, for: date, expected: nil) - test(.weekOfYear, in: .yearForWeekOfYear, for: date, expected: 1..<53) - test(.weekOfMonth, in: .yearForWeekOfYear, for: date, expected: nil) - test(.weekdayOrdinal, in: .yearForWeekOfYear, for: date, expected: 1..<66) - test(.day, in: .yearForWeekOfYear, for: date, expected: 1..<398) - test(.day, in: .year, for: date, expected: 1..<366) - test(.weekday, in: .year, for: date, expected: 1..<8) - test(.weekdayOrdinal, in: .year, for: date, expected: 1..<60) - test(.quarter, in: .year, for: date, expected: 1..<5) - test(.weekOfYear, in: .year, for: date, expected: 1..<54) - test(.weekOfMonth, in: .year, for: date, expected: 0..<58) - test(.day, in: .month, for: date, expected: 1..<32) - test(.weekdayOrdinal, in: .month, for: date, expected: 1..<6) - test(.weekOfMonth, in: .month, for: date, expected: 0..<6) - test(.weekOfYear, in: .month, for: date, expected: 48..<54) - test(.day, in: .weekOfMonth, for: date, expected: 31..<32) - - date = Date(timeIntervalSince1970: 823132800.0) // 1996-01-31T16:00:00-0800 (1996-02-01T00:00:00Z) - test(.month, in: .quarter, for: date, expected: 1..<4) - test(.day, in: .quarter, for: date, expected: 1..<92) - test(.weekday, in: .quarter, for: date, expected: 1..<8) - test(.weekdayOrdinal, in: .quarter, for: date, expected: 1..<16) - test(.weekOfMonth, in: .quarter, for: date, expected: 0..<14) - test(.weekOfYear, in: .quarter, for: date, expected: 1..<15) - test(.day, in: .weekOfYear, for: date, expected: nil) - test(.month, in: .yearForWeekOfYear, for: date, expected: nil) - test(.quarter, in: .yearForWeekOfYear, for: date, expected: nil) - test(.weekOfYear, in: .yearForWeekOfYear, for: date, expected: 1..<53) - test(.weekOfMonth, in: .yearForWeekOfYear, for: date, expected: nil) - test(.weekdayOrdinal, in: .yearForWeekOfYear, for: date, expected: 1..<66) - test(.day, in: .yearForWeekOfYear, for: date, expected: 1..<398) - test(.day, in: .year, for: date, expected: 1..<367) - test(.weekday, in: .year, for: date, expected: 1..<8) - test(.weekdayOrdinal, in: .year, for: date, expected: 1..<61) - test(.quarter, in: .year, for: date, expected: 1..<5) - test(.weekOfYear, in: .year, for: date, expected: 1..<54) - test(.weekOfMonth, in: .year, for: date, expected: 0..<57) - test(.day, in: .month, for: date, expected: 1..<32) - test(.weekdayOrdinal, in: .month, for: date, expected: 1..<6) - test(.weekOfMonth, in: .month, for: date, expected: 1..<6) - test(.weekOfYear, in: .month, for: date, expected: 1..<6) - test(.day, in: .weekOfMonth, for: date, expected: 28..<32) - - date = Date(timeIntervalSince1970: 825638400.0) // 1996-02-29T16:00:00-0800 (1996-03-01T00:00:00Z) - test(.month, in: .quarter, for: date, expected: 1..<4) - test(.day, in: .quarter, for: date, expected: 1..<92) - test(.weekday, in: .quarter, for: date, expected: 1..<8) - test(.weekdayOrdinal, in: .quarter, for: date, expected: 1..<16) - test(.weekOfMonth, in: .quarter, for: date, expected: 0..<14) - test(.weekOfYear, in: .quarter, for: date, expected: 1..<15) - test(.day, in: .weekOfYear, for: date, expected: nil) - test(.month, in: .yearForWeekOfYear, for: date, expected: nil) - test(.quarter, in: .yearForWeekOfYear, for: date, expected: nil) - test(.weekOfYear, in: .yearForWeekOfYear, for: date, expected: 1..<53) - test(.weekOfMonth, in: .yearForWeekOfYear, for: date, expected: nil) - test(.weekdayOrdinal, in: .yearForWeekOfYear, for: date, expected: 1..<66) - test(.day, in: .yearForWeekOfYear, for: date, expected: 1..<398) - test(.day, in: .year, for: date, expected: 1..<367) - test(.weekday, in: .year, for: date, expected: 1..<8) - test(.weekdayOrdinal, in: .year, for: date, expected: 1..<61) - test(.quarter, in: .year, for: date, expected: 1..<5) - test(.weekOfYear, in: .year, for: date, expected: 1..<54) - test(.weekOfMonth, in: .year, for: date, expected: 0..<57) - test(.day, in: .month, for: date, expected: 1..<30) - test(.weekdayOrdinal, in: .month, for: date, expected: 1..<6) - test(.weekOfMonth, in: .month, for: date, expected: 0..<5) - test(.weekOfYear, in: .month, for: date, expected: 5..<10) - test(.day, in: .weekOfMonth, for: date, expected: 25..<30) - - date = Date(timeIntervalSince1970: 851990400.0) // 1996-12-30T16:00:00-0800 (1996-12-31T00:00:00Z) - test(.month, in: .quarter, for: date, expected: 10..<13) - test(.day, in: .quarter, for: date, expected: 1..<93) - test(.weekday, in: .quarter, for: date, expected: 1..<8) - test(.weekdayOrdinal, in: .quarter, for: date, expected: 1..<16) - test(.weekOfMonth, in: .quarter, for: date, expected: 0..<14) - test(.weekOfYear, in: .quarter, for: date, expected: 40..<54) - test(.day, in: .weekOfYear, for: date, expected: nil) - test(.month, in: .yearForWeekOfYear, for: date, expected: nil) - test(.quarter, in: .yearForWeekOfYear, for: date, expected: nil) - test(.weekOfYear, in: .yearForWeekOfYear, for: date, expected: 1..<54) - test(.weekOfMonth, in: .yearForWeekOfYear, for: date, expected: nil) - test(.weekdayOrdinal, in: .yearForWeekOfYear, for: date, expected: 1..<70) - test(.day, in: .yearForWeekOfYear, for: date, expected: 1..<428) - test(.day, in: .year, for: date, expected: 1..<367) - test(.weekday, in: .year, for: date, expected: 1..<8) - test(.weekdayOrdinal, in: .year, for: date, expected: 1..<61) - test(.quarter, in: .year, for: date, expected: 1..<5) - test(.weekOfYear, in: .year, for: date, expected: 1..<54) - test(.weekOfMonth, in: .year, for: date, expected: 0..<57) - test(.day, in: .month, for: date, expected: 1..<32) - test(.weekdayOrdinal, in: .month, for: date, expected: 1..<6) - test(.weekOfMonth, in: .month, for: date, expected: 1..<6) - test(.weekOfYear, in: .month, for: date, expected: 49..<54) - test(.day, in: .weekOfMonth, for: date, expected: 29..<32) - - date = Date(timeIntervalSince1970: 857174400.0) // 1997-02-28T16:00:00-0800 (1997-03-01T00:00:00Z) - test(.month, in: .quarter, for: date, expected: 1..<4) - test(.day, in: .quarter, for: date, expected: 1..<91) - test(.weekday, in: .quarter, for: date, expected: 1..<8) - test(.weekdayOrdinal, in: .quarter, for: date, expected: 1..<15) - test(.weekOfMonth, in: .quarter, for: date, expected: 0..<14) - test(.weekOfYear, in: .quarter, for: date, expected: 1..<15) - test(.day, in: .weekOfYear, for: date, expected: nil) - test(.month, in: .yearForWeekOfYear, for: date, expected: nil) - test(.quarter, in: .yearForWeekOfYear, for: date, expected: nil) - test(.weekOfYear, in: .yearForWeekOfYear, for: date, expected: 1..<54) - test(.weekOfMonth, in: .yearForWeekOfYear, for: date, expected: nil) - test(.weekdayOrdinal, in: .yearForWeekOfYear, for: date, expected: 1..<70) - test(.day, in: .yearForWeekOfYear, for: date, expected: 1..<428) - test(.day, in: .year, for: date, expected: 1..<366) - test(.weekday, in: .year, for: date, expected: 1..<8) - test(.weekdayOrdinal, in: .year, for: date, expected: 1..<60) - test(.quarter, in: .year, for: date, expected: 1..<5) - test(.weekOfYear, in: .year, for: date, expected: 1..<54) - test(.weekOfMonth, in: .year, for: date, expected: 0..<58) - test(.day, in: .month, for: date, expected: 1..<29) - test(.weekdayOrdinal, in: .month, for: date, expected: 1..<5) - test(.weekOfMonth, in: .month, for: date, expected: 0..<5) - test(.weekOfYear, in: .month, for: date, expected: 5..<10) - test(.day, in: .weekOfMonth, for: date, expected: 23..<29) - - date = Date(timeIntervalSince1970: 820483200.0) // 1996-01-01T00:00:00-0800 (1996-01-01T08:00:00Z) - test(.month, in: .quarter, for: date, expected: 1..<4) - test(.day, in: .quarter, for: date, expected: 1..<92) - test(.weekday, in: .quarter, for: date, expected: 1..<8) - test(.weekdayOrdinal, in: .quarter, for: date, expected: 1..<16) - test(.weekOfMonth, in: .quarter, for: date, expected: 0..<14) - test(.weekOfYear, in: .quarter, for: date, expected: 1..<15) - test(.day, in: .weekOfYear, for: date, expected: nil) - test(.month, in: .yearForWeekOfYear, for: date, expected: nil) - test(.quarter, in: .yearForWeekOfYear, for: date, expected: nil) - test(.weekOfYear, in: .yearForWeekOfYear, for: date, expected: 1..<53) - test(.weekOfMonth, in: .yearForWeekOfYear, for: date, expected: nil) - test(.weekdayOrdinal, in: .yearForWeekOfYear, for: date, expected: 1..<66) - test(.day, in: .yearForWeekOfYear, for: date, expected: 1..<398) - test(.day, in: .year, for: date, expected: 1..<367) - test(.weekday, in: .year, for: date, expected: 1..<8) - test(.weekdayOrdinal, in: .year, for: date, expected: 1..<61) - test(.quarter, in: .year, for: date, expected: 1..<5) - test(.weekOfYear, in: .year, for: date, expected: 1..<54) - test(.weekOfMonth, in: .year, for: date, expected: 0..<57) - test(.day, in: .month, for: date, expected: 1..<32) - test(.weekdayOrdinal, in: .month, for: date, expected: 1..<6) - test(.weekOfMonth, in: .month, for: date, expected: 1..<6) - test(.weekOfYear, in: .month, for: date, expected: 1..<6) - test(.day, in: .weekOfMonth, for: date, expected: 1..<7) - } - - // MARK: - Difference - - func testDateComponentsFromStartToEnd() { - var calendar = _CalendarGregorian(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: 1, minimumDaysInFirstWeek: 4, gregorianStartDate: nil) - var start: Date! - var end: Date! - func test(_ components: Calendar.ComponentSet, expected: DateComponents, file: StaticString = #filePath, line: UInt = #line) { - let actual = calendar.dateComponents(components, from: start, to: end) - XCTAssertEqual(actual, expected, file: file, line: line) - } - - // non leap to leap - start = Date(timeIntervalSince1970: 788918400.0) // 1995-01-01 - end = Date(timeIntervalSince1970: 825638400.0) // 1996-03-01 - test([.year, .day, .month], expected: .init(year: 1, month: 2, day: 0)) - test([.weekday, .year, .month, .weekOfMonth], expected: .init(year: 1, month: 2, weekday: 0, weekOfMonth: 0)) - test([.yearForWeekOfYear, .weekOfYear], expected: .init(weekOfYear: 8, yearForWeekOfYear: 1)) - test([.weekday, .year, .month, .weekdayOrdinal], expected: .init(year: 1, month: 2, weekday: 0, weekdayOrdinal: 0)) - - // leap to non leap - // positive year, negative month - start = Date(timeIntervalSince1970: 823132800.0) // 1996-02-01 - end = Date(timeIntervalSince1970: 852076800.0) // 1997-01-01 - test([.year, .day, .month], expected: .init(year: 0, month: 11, day: 0)) - test([.weekday, .year, .month, .weekOfMonth], expected: .init(year: 0, month: 11, weekday: 0, weekOfMonth: 0)) - test([.yearForWeekOfYear, .weekOfYear], expected: .init(weekOfYear: 47, yearForWeekOfYear: 0)) - test([.weekday, .year, .month, .weekdayOrdinal], expected: .init(year: 0, month: 11, weekday: 0, weekdayOrdinal: 0)) - - // within leap - // positive month, positive day - start = Date(timeIntervalSince1970: 822960000.0) // 1996-01-30 - end = Date(timeIntervalSince1970: 825552000.0) // 1996-02-29 - test([.year, .day, .month], expected: .init(year: 0, month: 1, day: 0)) - test([.weekday, .year, .month, .weekOfMonth], expected: .init(year: 0, month: 1, weekday: 0, weekOfMonth: 0)) - test([.yearForWeekOfYear, .weekOfYear], expected: .init(weekOfYear: 4, yearForWeekOfYear: 0)) - test([.weekday, .year, .month, .weekdayOrdinal], expected: .init(year: 0, month: 1, weekday: 0, weekdayOrdinal: 0)) - - // positive month, negative day - start = Date(timeIntervalSince1970: 823046400.0) // 1996-01-31 - end = Date(timeIntervalSince1970: 825638400.0) // 1996-03-01 - test([.year, .day, .month], expected: .init(year: 0, month: 1, day: 1)) - test([.weekday, .year, .month, .weekOfMonth], expected: .init(year: 0, month: 1, weekday: 1, weekOfMonth: 0)) - test([.yearForWeekOfYear, .weekOfYear], expected: .init(weekOfYear: 4, yearForWeekOfYear: 0)) - test([.weekday, .year, .month, .weekdayOrdinal], expected: .init(year: 0, month: 1, weekday: 1, weekdayOrdinal: 0)) - - // within non leap - // positive month, positive day - start = Date(timeIntervalSince1970: 788918400.0) // 1995-01-01 - end = Date(timeIntervalSince1970: 794361600.0) // 1995-03-05 - test([.year, .day, .month], expected: .init(year: 0, month: 2, day: 4)) - test([.weekday, .year, .month, .weekOfMonth], expected: .init(year: 0, month: 2, weekday: 4, weekOfMonth: 0)) - test([.yearForWeekOfYear, .weekOfYear], expected: .init(weekOfYear: 9, yearForWeekOfYear: 0)) - test([.weekday, .year, .month, .weekdayOrdinal], expected: .init(year: 0, month: 2, weekday: 4, weekdayOrdinal: 0)) - - // positive month, negative day - start = Date(timeIntervalSince1970: 791510400.0) // 1995-01-31 - end = Date(timeIntervalSince1970: 794361600.0) // 1995-03-05 - test([.year, .day, .month], expected: .init(year: 0, month: 1, day: 5)) - test([.weekday, .year, .month, .weekOfMonth], expected: .init(year: 0, month: 1, weekday: 5, weekOfMonth: 0)) - test([.yearForWeekOfYear, .weekOfYear], expected: .init(weekOfYear: 4, yearForWeekOfYear: 0)) - test([.weekday, .year, .month, .weekdayOrdinal], expected: .init(year: 0, month: 1, weekday: 5, weekdayOrdinal: 0)) - - // --------- - // Backwards - start = Date(timeIntervalSince1970: 852076800.0) // 1997-01-01 - end = Date(timeIntervalSince1970: 851817600.0) // 1996-12-29 - test([.year, .day, .month], expected: .init(year: 0, month: 0, day: -3)) - test([.weekday, .year, .month, .weekOfMonth], expected: .init(year: 0, month: 0, weekday: -3, weekOfMonth: 0)) - test([.yearForWeekOfYear, .weekOfYear], expected: .init(weekOfYear: 0, yearForWeekOfYear: 0)) - test([.weekday, .year, .month, .weekdayOrdinal], expected: .init(year: 0, month: 0, weekday: -3, weekdayOrdinal: 0)) - - // leap to non leap - // negative year, positive month - start = Date(timeIntervalSince1970: 825638400.0) // 1996-03-01 - end = Date(timeIntervalSince1970: 817776000.0) // 1995-12-01 - test([.year, .day, .month], expected: .init(year: 0, month: -3, day: 0)) - test([.weekday, .year, .month, .weekOfMonth], expected: .init(year: 0, month: -3, weekday: 0, weekOfMonth: 0)) - test([.yearForWeekOfYear, .weekOfYear], expected: .init(weekOfYear: -13, yearForWeekOfYear: 0)) - test([.weekday, .year, .month, .weekdayOrdinal], expected: .init(year: 0, month: -3, weekday: 0, weekdayOrdinal: 0)) - - // within leap - // negative month, negative day - start = Date(timeIntervalSince1970: 825984000.0) // 1996-03-05 - end = Date(timeIntervalSince1970: 820454400.0) // 1996-01-01 - test([.year, .day, .month], expected: .init(year: 0, month: -2, day: -4)) - test([.weekday, .year, .month, .weekOfMonth], expected: .init(year: 0, month: -2, weekday: -4, weekOfMonth: 0)) - test([.yearForWeekOfYear, .weekOfYear], expected: .init(weekOfYear: -9, yearForWeekOfYear: 0)) - test([.weekday, .year, .month, .weekdayOrdinal], expected: .init(year: 0, month: -2, weekday: -4, weekdayOrdinal: 0)) - - // negative month, positive day - start = Date(timeIntervalSince1970: 825552000.0) // 1996-02-29 - end = Date(timeIntervalSince1970: 823046400.0) // 1996-01-31 - test([.year, .day, .month], expected: .init(year: 0, month: 0, day: -29)) - test([.weekday, .year, .month, .weekOfMonth], expected: .init(year: 0, month: 0, weekday: -1, weekOfMonth: -4)) - test([.yearForWeekOfYear, .weekOfYear], expected: .init(weekOfYear: -4, yearForWeekOfYear: 0)) - test([.weekday, .year, .month, .weekdayOrdinal], expected: .init(year: 0, month: 0, weekday: -29, weekdayOrdinal: 0)) - - // within non leap - // negative month, negative day - start = Date(timeIntervalSince1970: 794361600.0) // 1995-03-05 - end = Date(timeIntervalSince1970: 788918400.0) // 1995-01-01 - test([.year, .day, .month], expected: .init(year: 0, month: -2, day: -4)) - test([.weekday, .year, .month, .weekOfMonth], expected: .init(year: 0, month: -2, weekday: -4, weekOfMonth: 0)) - test([.yearForWeekOfYear, .weekOfYear], expected: .init(weekOfYear: -9, yearForWeekOfYear: 0)) - test([.weekday, .year, .month, .weekdayOrdinal], expected: .init(year: 0, month: -2, weekday: -4, weekdayOrdinal: 0)) - - // negative month, positive day - start = Date(timeIntervalSince1970: 793929600.0) // 1995-02-28 - end = Date(timeIntervalSince1970: 791510400.0) // 1995-01-31 - test([.year, .day, .month], expected: .init(year: 0, month: 0, day: -28)) - test([.weekday, .year, .month, .weekOfMonth], expected: .init(year: 0, month: 0, weekday: 0, weekOfMonth: -4)) - test([.yearForWeekOfYear, .weekOfYear], expected: .init(weekOfYear: -4, yearForWeekOfYear: 0)) - test([.weekday, .year, .month, .weekdayOrdinal], expected: .init(year: 0, month: 0, weekday: -28, weekdayOrdinal: 0)) - - calendar = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(secondsFromGMT: -8*3600), locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - start = Date(timeIntervalSinceReferenceDate: 0) // 2000-12-31 16:00:00 PT - end = Date(timeIntervalSinceReferenceDate: 5458822.0) // 2001-03-04 20:20:22 PT - var expected = DateComponents(era: 0, year: 0, month: 2, day: 4, hour: 4, minute: 20, second: 22, nanosecond: 0, weekday: 0, weekdayOrdinal: 0, quarter: 0 , weekOfMonth: 0, weekOfYear: 0, yearForWeekOfYear: 0) - // FIXME 123202377: This is wrong, but it's the same as Calendar_ICU's current behavior - expected.dayOfYear = 0 - test([.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .dayOfYear, .calendar, .timeZone], expected: expected) - } - - func testDifference() { - var calendar = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(secondsFromGMT: -28800)!, locale: nil, firstWeekday: 1, minimumDaysInFirstWeek: 4, gregorianStartDate: nil) - var start: Date! - var end: Date! - func test(_ component: Calendar.Component, expected: Int, file: StaticString = #filePath, line: UInt = #line) { - let (actualDiff, _) = try! calendar.difference(inComponent: component, from: start, to: end) - XCTAssertEqual(actualDiff, expected, file: file, line: line) - } - - // non leap to leap - start = Date(timeIntervalSince1970: 788947200.0) // 1995-01-01 - end = Date(timeIntervalSince1970: 825667200.0) // 1996-03-01 - test(.era, expected: 0) - test(.year, expected: 1) - test(.month, expected: 14) - test(.day, expected: 425) - test(.hour, expected: 10200) - test(.weekday, expected: 425) - test(.weekdayOrdinal, expected: 60) - test(.weekOfMonth, expected: 60) - test(.weekOfYear, expected: 60) - test(.yearForWeekOfYear, expected: 1) - test(.dayOfYear, expected: 425) - - // leap to non leap - start = Date(timeIntervalSince1970: 820483200.0) // 1996-01-01 - end = Date(timeIntervalSince1970: 852105600.0) // 1997-01-01 - test(.era, expected: 0) - test(.year, expected: 1) - test(.month, expected: 12) - test(.day, expected: 366) - test(.hour, expected: 8784) - test(.weekday, expected: 366) - test(.weekdayOrdinal, expected: 52) - test(.weekOfMonth, expected: 52) - test(.weekOfYear, expected: 52) - test(.yearForWeekOfYear, expected: 1) - test(.dayOfYear, expected: 366) - - // within leap - start = Date(timeIntervalSince1970: 820483200.0) // 1996-01-01 - end = Date(timeIntervalSince1970: 825580800.0) // 1996-02-29 - test(.era, expected: 0) - test(.year, expected: 0) - test(.month, expected: 1) - test(.day, expected: 59) - test(.hour, expected: 1416) - test(.weekday, expected: 59) - test(.weekdayOrdinal, expected: 8) - test(.weekOfMonth, expected: 8) - test(.weekOfYear, expected: 8) - test(.yearForWeekOfYear, expected: 0) - test(.dayOfYear, expected: 59) - - start = Date(timeIntervalSince1970: 820483200.0) // 1996-01-01 - end = Date(timeIntervalSince1970: 825667200.0) // 1996-03-01 - test(.era, expected: 0) - test(.year, expected: 0) - test(.month, expected: 2) - test(.day, expected: 60) - test(.hour, expected: 1440) - test(.weekday, expected: 60) - test(.weekdayOrdinal, expected: 8) - test(.weekOfMonth, expected: 8) - test(.weekOfYear, expected: 8) - test(.yearForWeekOfYear, expected: 0) - test(.dayOfYear, expected: 60) - - // within non leap - start = Date(timeIntervalSince1970: 788947200.0) // 1995-01-01 - end = Date(timeIntervalSince1970: 794044800.0) // 1995-03-01 - test(.era, expected: 0) - test(.year, expected: 0) - test(.month, expected: 2) - test(.day, expected: 59) - test(.hour, expected: 1416) - test(.weekday, expected: 59) - test(.weekdayOrdinal, expected: 8) - test(.weekOfMonth, expected: 8) - test(.weekOfYear, expected: 8) - test(.yearForWeekOfYear, expected: 0) - test(.dayOfYear, expected: 59) - - // Backwards - // non leap to leap - start = Date(timeIntervalSince1970: 825667200.0) // 1996-03-01 - end = Date(timeIntervalSince1970: 788947200.0) // 1995-01-01 - test(.era, expected: 0) - test(.year, expected: -1) - test(.month, expected: -14) - test(.day, expected: -425) - test(.hour, expected: -10200) - test(.weekday, expected: -425) - test(.weekdayOrdinal, expected: -60) - test(.weekOfMonth, expected: -60) - test(.weekOfYear, expected: -60) - test(.yearForWeekOfYear, expected: -1) - test(.dayOfYear, expected: -425) - - // leap to non leap - start = Date(timeIntervalSince1970: 820483200.0) // 1996-01-01 - end = Date(timeIntervalSince1970: 788947200.0) // 1995-01-01 - test(.era, expected: 0) - test(.year, expected: -1) - test(.month, expected: -12) - test(.day, expected: -365) - test(.hour, expected: -8760) - test(.weekday, expected: -365) - test(.weekdayOrdinal, expected: -52) - test(.weekOfMonth, expected: -52) - test(.weekOfYear, expected: -52) - test(.yearForWeekOfYear, expected: -1) - test(.dayOfYear, expected: -365) - - // within leap - start = Date(timeIntervalSince1970: 825667200.0) // 1996-03-01 - end = Date(timeIntervalSince1970: 820483200.0) // 1996-01-01 - test(.era, expected: 0) - test(.year, expected: 0) - test(.month, expected: -2) - test(.day, expected: -60) - test(.hour, expected: -1440) - test(.weekday, expected: -60) - test(.weekdayOrdinal, expected: -8) - test(.weekOfMonth, expected: -8) - test(.weekOfYear, expected: -8) - test(.yearForWeekOfYear, expected: 0) - test(.dayOfYear, expected: -60) - - start = Date(timeIntervalSince1970: 825580800.0) // 1996-02-29 - end = Date(timeIntervalSince1970: 820483200.0) // 1996-01-01 - test(.era, expected: 0) - test(.year, expected: 0) - test(.month, expected: -1) - test(.day, expected: -59) - test(.hour, expected: -1416) - test(.weekday, expected: -59) - test(.weekdayOrdinal, expected: -8) - test(.weekOfMonth, expected: -8) - test(.weekOfYear, expected: -8) - test(.yearForWeekOfYear, expected: 0) - test(.dayOfYear, expected: -59) - - // within non leap - start = Date(timeIntervalSince1970: 794044800.0) // 1995-03-01 - end = Date(timeIntervalSince1970: 788947200.0) // 1995-01-01 - test(.era, expected: 0) - test(.year, expected: 0) - test(.month, expected: -2) - test(.day, expected: -59) - test(.hour, expected: -1416) - test(.weekday, expected: -59) - test(.weekdayOrdinal, expected: -8) - test(.weekOfMonth, expected: -8) - test(.weekOfYear, expected: -8) - test(.yearForWeekOfYear, expected: 0) - test(.dayOfYear, expected: -59) - - // Time - - start = Date(timeIntervalSince1970: 820479600.0) // 1995-12-31 23:00:00 - end = Date(timeIntervalSince1970: 825667200.0) // 1996-03-01 00:00:00 - test(.hour, expected: 1441) - test(.minute, expected: 86460) - test(.second, expected: 5187600) - test(.nanosecond, expected: Int(Int32.max)) - - start = Date(timeIntervalSince1970: 852105540.0) // 1996-12-31 23:59:00 - end = Date(timeIntervalSince1970: 857203205.0) // 1997-03-01 00:00:05 - test(.hour, expected: 1416) - test(.minute, expected: 84961) - test(.second, expected: 5097665) - test(.nanosecond, expected: Int(Int32.max)) - - start = Date(timeIntervalSince1970: 825580720.0) // 1996-02-28 23:58:40 - end = Date(timeIntervalSince1970: 825580805.0) // 1996-02-29 00:00:05 - test(.hour, expected: 0) - test(.minute, expected: 1) - test(.second, expected: 85) - test(.nanosecond, expected: Int(Int32.max)) - - start = Date(timeIntervalSince1970: 825580720.0) // 1996-02-28 23:58:40 - end = Date(timeIntervalSince1970: 825667205.0) // 1996-03-01 00:00:05 - test(.hour, expected: 24) - test(.minute, expected: 1441) - test(.second, expected: 86485) - test(.nanosecond, expected: Int(Int32.max)) - - start = Date(timeIntervalSince1970: 794044710.0) // 1995-02-28 23:58:30 - end = Date(timeIntervalSince1970: 794044805.0) // 1995-03-01 00:00:05 - test(.hour, expected: 0) - test(.minute, expected: 1) - test(.second, expected: 95) - test(.nanosecond, expected: Int(Int32.max)) - - start = Date(timeIntervalSince1970: 857203205.0) // 1997-03-01 00:00:05 - end = Date(timeIntervalSince1970: 852105520.0) // 1996-12-31 23:58:40 - test(.hour, expected: -1416) - test(.minute, expected: -84961) - test(.second, expected: -5097685) - test(.nanosecond, expected: Int(Int32.min)) - - start = Date(timeIntervalSince1970: 825667205.0) // 1996-03-01 00:00:05 - end = Date(timeIntervalSince1970: 820483120.0) // 1995-12-31 23:58:40 - test(.hour, expected: -1440) - test(.minute, expected: -86401) - test(.second, expected: -5184085) - test(.nanosecond, expected: Int(Int32.min)) - - start = Date(timeIntervalSince1970: 825667205.0) // 1996-03-01 00:00:05 - end = Date(timeIntervalSince1970: 825580720.0) // 1996-02-28 23:58:40 - test(.hour, expected: -24) - test(.minute, expected: -1441) - test(.second, expected: -86485) - test(.nanosecond, expected: Int(Int32.min)) - - start = Date(timeIntervalSince1970: 825580805.0) // 1996-02-29 00:00:05 - end = Date(timeIntervalSince1970: 825580720.0) // 1996-02-28 23:58:40 - test(.hour, expected: 0) - test(.minute, expected: -1) - test(.second, expected: -85) - test(.nanosecond, expected: Int(Int32.min)) - - start = Date(timeIntervalSince1970: 825580805.0) // 1996-02-29 00:00:05 - end = Date(timeIntervalSince1970: 820569520.0) // 1996-01-01 23:58:40 - test(.hour, expected: -1392) - test(.minute, expected: -83521) - test(.second, expected: -5011285) - test(.nanosecond, expected: Int(Int32.min)) - - start = Date(timeIntervalSince1970: 794044805.0) // 1995-03-01 00:00:05 - end = Date(timeIntervalSince1970: 794044710.0) // 1995-02-28 23:58:30 - test(.hour, expected: 0) - test(.minute, expected: -1) - test(.second, expected: -95) - test(.nanosecond, expected: Int(Int32.min)) - - calendar = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(secondsFromGMT: -8*3600), locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - start = Date(timeIntervalSinceReferenceDate: 0) // 2000-12-31 16:00:00 PT - end = Date(timeIntervalSinceReferenceDate: 5458822.0) // 2001-03-04 20:20:22 PT - test(.month, expected: 2) - test(.dayOfYear, expected: 63) - } - - func testDifference_DST() { - let calendar = _CalendarGregorian(identifier: .gregorian, timeZone: TimeZone(identifier: "America/Los_Angeles")!, locale: nil, firstWeekday: 1, minimumDaysInFirstWeek: 4, gregorianStartDate: nil) - - var start: Date! - var end: Date! - func test(_ component: Calendar.Component, expected: Int, file: StaticString = #filePath, line: UInt = #line) { - let (actualDiff, _) = try! calendar.difference(inComponent: component, from: start, to: end) - XCTAssertEqual(actualDiff, expected, file: file, line: line) - } - - start = Date(timeIntervalSince1970: 828867787.0) // 1996-04-07T01:03:07-0800 - end = Date(timeIntervalSince1970: 828871387.0) // 1996-04-07T03:03:07-0700 - test(.hour, expected: 1) - test(.minute, expected: 60) - test(.second, expected: 3600) - - start = Date(timeIntervalSince1970: 828867787.0) // 1996-04-07T01:03:07-0800 - end = Date(timeIntervalSince1970: 828874987.0) // 1996-04-07T04:03:07-0700 - test(.hour, expected: 2) - test(.minute, expected: 120) - test(.second, expected: 7200) - - start = Date(timeIntervalSince1970: 846403387.0) // 1996-10-27T01:03:07-0700 - end = Date(timeIntervalSince1970: 846406987.0) // 1996-10-27T01:03:07-0800 - test(.hour, expected: 1) - test(.minute, expected: 60) - test(.second, expected: 3600) - - start = Date(timeIntervalSince1970: 846403387.0) // 1996-10-27T01:03:07-0700 - end = Date(timeIntervalSince1970: 846410587.0) // 1996-10-27T02:03:07-0800 - test(.hour, expected: 2) - test(.minute, expected: 120) - test(.second, expected: 7200) - - // backwards - - start = Date(timeIntervalSince1970: 828871387.0) // 1996-04-07T03:03:07-0700 - end = Date(timeIntervalSince1970: 828867787.0) // 1996-04-07T01:03:07-0800 - test(.hour, expected: -1) - test(.minute, expected: -60) - test(.second, expected: -3600) - - start = Date(timeIntervalSince1970: 828874987.0) // 1996-04-07T04:03:07-0700 - end = Date(timeIntervalSince1970: 828867787.0) // 1996-04-07T01:03:07-0800 - test(.hour, expected: -2) - test(.minute, expected: -120) - test(.second, expected: -7200) - - start = Date(timeIntervalSince1970: 846406987.0) // 1996-10-27T01:03:07-0800 - end = Date(timeIntervalSince1970: 846403387.0) // 1996-10-27T01:03:07-0700 - test(.hour, expected: -1) - test(.minute, expected: -60) - test(.second, expected: -3600) - - start = Date(timeIntervalSince1970: 846410587.0) // 1996-10-27T02:03:07-0800 - end = Date(timeIntervalSince1970: 846403387.0) // 1996-10-27T01:03:07-0700 - test(.hour, expected: -2) - test(.minute, expected: -120) - test(.second, expected: -7200) - } - - // MARK: ISO8601 - - func test_iso8601Gregorian() { - var calendar1 = Calendar(identifier: .iso8601) - let calendar2 = Calendar(identifier: .iso8601) - XCTAssertEqual(calendar1, calendar2) - - XCTAssertEqual(calendar1.firstWeekday, 2) - XCTAssertEqual(calendar1.minimumDaysInFirstWeek, 4) - XCTAssertEqual(calendar1.locale, .unlocalized) - - // Verify that the properties are still mutable - let tz = TimeZone(secondsFromGMT: -3600)! - calendar1.timeZone = tz - XCTAssertNotEqual(calendar1, calendar2) - - XCTAssertEqual(calendar1.timeZone, tz) - } -} - diff --git a/Tests/FoundationEssentialsTests/IndexPathTests.swift b/Tests/FoundationEssentialsTests/IndexPathTests.swift deleted file mode 100644 index 86e9e825a..000000000 --- a/Tests/FoundationEssentialsTests/IndexPathTests.swift +++ /dev/null @@ -1,762 +0,0 @@ -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(FoundationEssentials) -@testable import FoundationEssentials -#endif - -class TestIndexPath: XCTestCase { - func testEmpty() { - let ip = IndexPath() - XCTAssertEqual(ip.count, 0) - -#if FOUNDATION_FRAMEWORK - // Darwin allows nil if length is 0 - let nsip = NSIndexPath(indexes: nil, length: 0) - XCTAssertEqual(nsip.length, 0) - let newIp = nsip.adding(1) - XCTAssertEqual(newIp.count, 1) -#endif - } - - func testSingleIndex() { - let ip = IndexPath(index: 1) - XCTAssertEqual(ip.count, 1) - XCTAssertEqual(ip[0], 1) - - let highValueIp = IndexPath(index: .max) - XCTAssertEqual(highValueIp.count, 1) - XCTAssertEqual(highValueIp[0], .max) - - let lowValueIp = IndexPath(index: .min) - XCTAssertEqual(lowValueIp.count, 1) - XCTAssertEqual(lowValueIp[0], .min) - } - - func testTwoIndexes() { - let ip = IndexPath(indexes: [0, 1]) - XCTAssertEqual(ip.count, 2) - XCTAssertEqual(ip[0], 0) - XCTAssertEqual(ip[1], 1) - } - - func testManyIndexes() { - let ip = IndexPath(indexes: [0, 1, 2, 3, 4]) - XCTAssertEqual(ip.count, 5) - XCTAssertEqual(ip[0], 0) - XCTAssertEqual(ip[1], 1) - XCTAssertEqual(ip[2], 2) - XCTAssertEqual(ip[3], 3) - XCTAssertEqual(ip[4], 4) - } - - func testCreateFromSequence() { - let seq = repeatElement(5, count: 3) - let ip = IndexPath(indexes: seq) - XCTAssertEqual(ip.count, 3) - XCTAssertEqual(ip[0], 5) - XCTAssertEqual(ip[1], 5) - XCTAssertEqual(ip[2], 5) - } - - func testCreateFromLiteral() { - let ip: IndexPath = [1, 2, 3, 4] - XCTAssertEqual(ip.count, 4) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) - XCTAssertEqual(ip[2], 3) - XCTAssertEqual(ip[3], 4) - } - - func testDropLast() { - let ip: IndexPath = [1, 2, 3, 4] - let ip2 = ip.dropLast() - XCTAssertEqual(ip2.count, 3) - XCTAssertEqual(ip2[0], 1) - XCTAssertEqual(ip2[1], 2) - XCTAssertEqual(ip2[2], 3) - } - - func testDropLastFromEmpty() { - let ip: IndexPath = [] - let ip2 = ip.dropLast() - XCTAssertEqual(ip2.count, 0) - } - - func testDropLastFromSingle() { - let ip: IndexPath = [1] - let ip2 = ip.dropLast() - XCTAssertEqual(ip2.count, 0) - } - - func testDropLastFromPair() { - let ip: IndexPath = [1, 2] - let ip2 = ip.dropLast() - XCTAssertEqual(ip2.count, 1) - XCTAssertEqual(ip2[0], 1) - } - - func testDropLastFromTriple() { - let ip: IndexPath = [1, 2, 3] - let ip2 = ip.dropLast() - XCTAssertEqual(ip2.count, 2) - XCTAssertEqual(ip2[0], 1) - XCTAssertEqual(ip2[1], 2) - } - - func testStartEndIndex() { - let ip: IndexPath = [1, 2, 3, 4] - XCTAssertEqual(ip.startIndex, 0) - XCTAssertEqual(ip.endIndex, ip.count) - } - - func testIterator() { - let ip: IndexPath = [1, 2, 3, 4] - var iter = ip.makeIterator() - var sum = 0 - while let index = iter.next() { - sum += index - } - XCTAssertEqual(sum, 1 + 2 + 3 + 4) - } - - func testIndexing() { - let ip: IndexPath = [1, 2, 3, 4] - XCTAssertEqual(ip.index(before: 1), 0) - XCTAssertEqual(ip.index(before: 0), -1) // beyond range! - XCTAssertEqual(ip.index(after: 1), 2) - XCTAssertEqual(ip.index(after: 4), 5) // beyond range! - } - - func testCompare() { - let ip1: IndexPath = [1, 2] - let ip2: IndexPath = [3, 4] - let ip3: IndexPath = [5, 1] - let ip4: IndexPath = [1, 1, 1] - let ip5: IndexPath = [1, 1, 9] - - XCTAssertEqual(ip1.compare(ip1), ComparisonResult.orderedSame) - XCTAssertEqual(ip1 < ip1, false) - XCTAssertEqual(ip1 <= ip1, true) - XCTAssertEqual(ip1 == ip1, true) - XCTAssertEqual(ip1 >= ip1, true) - XCTAssertEqual(ip1 > ip1, false) - - XCTAssertEqual(ip1.compare(ip2), ComparisonResult.orderedAscending) - XCTAssertEqual(ip1 < ip2, true) - XCTAssertEqual(ip1 <= ip2, true) - XCTAssertEqual(ip1 == ip2, false) - XCTAssertEqual(ip1 >= ip2, false) - XCTAssertEqual(ip1 > ip2, false) - - XCTAssertEqual(ip1.compare(ip3), ComparisonResult.orderedAscending) - XCTAssertEqual(ip1 < ip3, true) - XCTAssertEqual(ip1 <= ip3, true) - XCTAssertEqual(ip1 == ip3, false) - XCTAssertEqual(ip1 >= ip3, false) - XCTAssertEqual(ip1 > ip3, false) - - XCTAssertEqual(ip1.compare(ip4), ComparisonResult.orderedDescending) - XCTAssertEqual(ip1 < ip4, false) - XCTAssertEqual(ip1 <= ip4, false) - XCTAssertEqual(ip1 == ip4, false) - XCTAssertEqual(ip1 >= ip4, true) - XCTAssertEqual(ip1 > ip4, true) - - XCTAssertEqual(ip1.compare(ip5), ComparisonResult.orderedDescending) - XCTAssertEqual(ip1 < ip5, false) - XCTAssertEqual(ip1 <= ip5, false) - XCTAssertEqual(ip1 == ip5, false) - XCTAssertEqual(ip1 >= ip5, true) - XCTAssertEqual(ip1 > ip5, true) - - XCTAssertEqual(ip2.compare(ip1), ComparisonResult.orderedDescending) - XCTAssertEqual(ip2 < ip1, false) - XCTAssertEqual(ip2 <= ip1, false) - XCTAssertEqual(ip2 == ip1, false) - XCTAssertEqual(ip2 >= ip1, true) - XCTAssertEqual(ip2 > ip1, true) - - XCTAssertEqual(ip2.compare(ip2), ComparisonResult.orderedSame) - XCTAssertEqual(ip2 < ip2, false) - XCTAssertEqual(ip2 <= ip2, true) - XCTAssertEqual(ip2 == ip2, true) - XCTAssertEqual(ip2 >= ip2, true) - XCTAssertEqual(ip2 > ip2, false) - - XCTAssertEqual(ip2.compare(ip3), ComparisonResult.orderedAscending) - XCTAssertEqual(ip2 < ip3, true) - XCTAssertEqual(ip2 <= ip3, true) - XCTAssertEqual(ip2 == ip3, false) - XCTAssertEqual(ip2 >= ip3, false) - XCTAssertEqual(ip2 > ip3, false) - - XCTAssertEqual(ip2.compare(ip4), ComparisonResult.orderedDescending) - XCTAssertEqual(ip2.compare(ip5), ComparisonResult.orderedDescending) - XCTAssertEqual(ip3.compare(ip1), ComparisonResult.orderedDescending) - XCTAssertEqual(ip3.compare(ip2), ComparisonResult.orderedDescending) - XCTAssertEqual(ip3.compare(ip3), ComparisonResult.orderedSame) - XCTAssertEqual(ip3.compare(ip4), ComparisonResult.orderedDescending) - XCTAssertEqual(ip3.compare(ip5), ComparisonResult.orderedDescending) - XCTAssertEqual(ip4.compare(ip1), ComparisonResult.orderedAscending) - XCTAssertEqual(ip4.compare(ip2), ComparisonResult.orderedAscending) - XCTAssertEqual(ip4.compare(ip3), ComparisonResult.orderedAscending) - XCTAssertEqual(ip4.compare(ip4), ComparisonResult.orderedSame) - XCTAssertEqual(ip4.compare(ip5), ComparisonResult.orderedAscending) - XCTAssertEqual(ip5.compare(ip1), ComparisonResult.orderedAscending) - XCTAssertEqual(ip5.compare(ip2), ComparisonResult.orderedAscending) - XCTAssertEqual(ip5.compare(ip3), ComparisonResult.orderedAscending) - XCTAssertEqual(ip5.compare(ip4), ComparisonResult.orderedDescending) - XCTAssertEqual(ip5.compare(ip5), ComparisonResult.orderedSame) - - let ip6: IndexPath = [1, 1] - XCTAssertEqual(ip6.compare(ip5), ComparisonResult.orderedAscending) - XCTAssertEqual(ip5.compare(ip6), ComparisonResult.orderedDescending) - } - - func testHashing() { - let samples: [IndexPath] = [ - [], - [1], - [2], - [Int.max], - [1, 1], - [2, 1], - [1, 2], - [1, 1, 1], - [2, 1, 1], - [1, 2, 1], - [1, 1, 2], - [Int.max, Int.max, Int.max], - ] - checkHashable(samples, equalityOracle: { $0 == $1 }) - - // this should not cause an overflow crash - _ = IndexPath(indexes: [Int.max >> 8, 2, Int.max >> 36]).hashValue - } - - func testEquality() { - let ip1: IndexPath = [1, 1] - let ip2: IndexPath = [1, 1] - let ip3: IndexPath = [1, 1, 1] - let ip4: IndexPath = [] - let ip5: IndexPath = [1] - - XCTAssertTrue(ip1 == ip2) - XCTAssertFalse(ip1 == ip3) - XCTAssertFalse(ip1 == ip4) - XCTAssertFalse(ip4 == ip1) - XCTAssertFalse(ip5 == ip1) - XCTAssertFalse(ip5 == ip4) - XCTAssertTrue(ip4 == ip4) - XCTAssertTrue(ip5 == ip5) - } - - func testSubscripting() { - var ip1: IndexPath = [1] - var ip2: IndexPath = [1, 2] - var ip3: IndexPath = [1, 2, 3] - - XCTAssertEqual(ip1[0], 1) - - XCTAssertEqual(ip2[0], 1) - XCTAssertEqual(ip2[1], 2) - - XCTAssertEqual(ip3[0], 1) - XCTAssertEqual(ip3[1], 2) - XCTAssertEqual(ip3[2], 3) - - ip1[0] = 2 - XCTAssertEqual(ip1[0], 2) - - ip2[0] = 2 - ip2[1] = 3 - XCTAssertEqual(ip2[0], 2) - XCTAssertEqual(ip2[1], 3) - - ip3[0] = 2 - ip3[1] = 3 - ip3[2] = 4 - XCTAssertEqual(ip3[0], 2) - XCTAssertEqual(ip3[1], 3) - XCTAssertEqual(ip3[2], 4) - - let ip4 = ip3[0..<2] - XCTAssertEqual(ip4.count, 2) - XCTAssertEqual(ip4[0], 2) - XCTAssertEqual(ip4[1], 3) - - let ip5 = ip3[1...] - XCTAssertEqual(ip5.count, 2) - XCTAssertEqual(ip5[0], 3) - XCTAssertEqual(ip5[1], 4) - - let ip6 = ip3[2...] - XCTAssertEqual(ip6.count, 1) - XCTAssertEqual(ip6[0], 4) - } - - func testAppending() { - var ip : IndexPath = [1, 2, 3, 4] - let ip2 = IndexPath(indexes: [5, 6, 7]) - - ip.append(ip2) - - XCTAssertEqual(ip.count, 7) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[6], 7) - - let ip3 = ip.appending(IndexPath(indexes: [8, 9])) - XCTAssertEqual(ip3.count, 9) - XCTAssertEqual(ip3[7], 8) - XCTAssertEqual(ip3[8], 9) - - let ip4 = ip3.appending([10, 11]) - XCTAssertEqual(ip4.count, 11) - XCTAssertEqual(ip4[9], 10) - XCTAssertEqual(ip4[10], 11) - - let ip5 = ip.appending(8) - XCTAssertEqual(ip5.count, 8) - XCTAssertEqual(ip5[7], 8) - } - - func testAppendEmpty() { - var ip: IndexPath = [] - ip.append(1) - - XCTAssertEqual(ip.count, 1) - XCTAssertEqual(ip[0], 1) - - ip.append(2) - XCTAssertEqual(ip.count, 2) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) - - ip.append(3) - XCTAssertEqual(ip.count, 3) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) - XCTAssertEqual(ip[2], 3) - - ip.append(4) - XCTAssertEqual(ip.count, 4) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) - XCTAssertEqual(ip[2], 3) - XCTAssertEqual(ip[3], 4) - } - - func testAppendEmptyIndexPath() { - var ip: IndexPath = [] - ip.append(IndexPath(indexes: [])) - - XCTAssertEqual(ip.count, 0) - } - - func testAppendManyIndexPath() { - var ip: IndexPath = [] - ip.append(IndexPath(indexes: [1, 2, 3])) - - XCTAssertEqual(ip.count, 3) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) - XCTAssertEqual(ip[2], 3) - } - - func testAppendEmptyIndexPathToSingle() { - var ip: IndexPath = [1] - ip.append(IndexPath(indexes: [])) - - XCTAssertEqual(ip.count, 1) - XCTAssertEqual(ip[0], 1) - } - - func testAppendSingleIndexPath() { - var ip: IndexPath = [] - ip.append(IndexPath(indexes: [1])) - - XCTAssertEqual(ip.count, 1) - XCTAssertEqual(ip[0], 1) - } - - func testAppendSingleIndexPathToSingle() { - var ip: IndexPath = [1] - ip.append(IndexPath(indexes: [1])) - - XCTAssertEqual(ip.count, 2) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 1) - } - - func testAppendPairIndexPath() { - var ip: IndexPath = [] - ip.append(IndexPath(indexes: [1, 2])) - - XCTAssertEqual(ip.count, 2) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) - } - - func testAppendManyIndexPathToEmpty() { - var ip: IndexPath = [] - ip.append(IndexPath(indexes: [1, 2, 3])) - - XCTAssertEqual(ip.count, 3) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) - XCTAssertEqual(ip[2], 3) - } - - func testAppendByOperator() { - let ip1: IndexPath = [] - let ip2: IndexPath = [] - - let ip3 = ip1 + ip2 - XCTAssertEqual(ip3.count, 0) - - let ip4: IndexPath = [1] - let ip5: IndexPath = [2] - - let ip6 = ip4 + ip5 - XCTAssertEqual(ip6.count, 2) - XCTAssertEqual(ip6[0], 1) - XCTAssertEqual(ip6[1], 2) - - var ip7: IndexPath = [] - ip7 += ip6 - XCTAssertEqual(ip7.count, 2) - XCTAssertEqual(ip7[0], 1) - XCTAssertEqual(ip7[1], 2) - } - - func testAppendArray() { - var ip: IndexPath = [1, 2, 3, 4] - let indexes = [5, 6, 7] - - ip.append(indexes) - - XCTAssertEqual(ip.count, 7) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[6], 7) - } - - func testRanges() { - let ip1 = IndexPath(indexes: [1, 2, 3]) - let ip2 = IndexPath(indexes: [6, 7, 8]) - - // Replace the whole range - var mutateMe = ip1 - mutateMe[0..<3] = ip2 - XCTAssertEqual(mutateMe, ip2) - - // Insert at the beginning - mutateMe = ip1 - mutateMe[0..<0] = ip2 - XCTAssertEqual(mutateMe, IndexPath(indexes: [6, 7, 8, 1, 2, 3])) - - // Insert at the end - mutateMe = ip1 - mutateMe[3..<3] = ip2 - XCTAssertEqual(mutateMe, IndexPath(indexes: [1, 2, 3, 6, 7, 8])) - - // Insert in middle - mutateMe = ip1 - mutateMe[2..<2] = ip2 - XCTAssertEqual(mutateMe, IndexPath(indexes: [1, 2, 6, 7, 8, 3])) - } - - func testRangeFromEmpty() { - let ip1 = IndexPath() - let ip2 = ip1[0..<0] - XCTAssertEqual(ip2.count, 0) - } - - func testRangeFromSingle() { - let ip1 = IndexPath(indexes: [1]) - let ip2 = ip1[0..<0] - XCTAssertEqual(ip2.count, 0) - let ip3 = ip1[0..<1] - XCTAssertEqual(ip3.count, 1) - XCTAssertEqual(ip3[0], 1) - } - - func testRangeFromPair() { - let ip1 = IndexPath(indexes: [1, 2]) - let ip2 = ip1[0..<0] - XCTAssertEqual(ip2.count, 0) - let ip3 = ip1[0..<1] - XCTAssertEqual(ip3.count, 1) - XCTAssertEqual(ip3[0], 1) - let ip4 = ip1[1..<1] - XCTAssertEqual(ip4.count, 0) - let ip5 = ip1[0..<2] - XCTAssertEqual(ip5.count, 2) - XCTAssertEqual(ip5[0], 1) - XCTAssertEqual(ip5[1], 2) - let ip6 = ip1[1..<2] - XCTAssertEqual(ip6.count, 1) - XCTAssertEqual(ip6[0], 2) - let ip7 = ip1[2..<2] - XCTAssertEqual(ip7.count, 0) - } - - func testRangeFromMany() { - let ip1 = IndexPath(indexes: [1, 2, 3]) - let ip2 = ip1[0..<0] - XCTAssertEqual(ip2.count, 0) - let ip3 = ip1[0..<1] - XCTAssertEqual(ip3.count, 1) - let ip4 = ip1[0..<2] - XCTAssertEqual(ip4.count, 2) - let ip5 = ip1[0..<3] - XCTAssertEqual(ip5.count, 3) - } - - func testRangeReplacementSingle() { - var ip1 = IndexPath(indexes: [1]) - ip1[0..<1] = IndexPath(indexes: [2]) - XCTAssertEqual(ip1[0], 2) - - ip1[0..<1] = IndexPath(indexes: []) - XCTAssertEqual(ip1.count, 0) - } - - func testRangeReplacementPair() { - var ip1 = IndexPath(indexes: [1, 2]) - ip1[0..<1] = IndexPath(indexes: [2, 3]) - XCTAssertEqual(ip1.count, 3) - XCTAssertEqual(ip1[0], 2) - XCTAssertEqual(ip1[1], 3) - XCTAssertEqual(ip1[2], 2) - - ip1[0..<1] = IndexPath(indexes: []) - XCTAssertEqual(ip1.count, 2) - } - - func testMoreRanges() { - var ip = IndexPath(indexes: [1, 2, 3]) - let ip2 = IndexPath(indexes: [5, 6, 7, 8, 9, 10]) - - ip[1..<2] = ip2 - XCTAssertEqual(ip, IndexPath(indexes: [1, 5, 6, 7, 8, 9, 10, 3])) - } - - func testIteration() { - let ip = IndexPath(indexes: [1, 2, 3]) - - var count = 0 - for _ in ip { - count += 1 - } - - XCTAssertEqual(3, count) - } - - func testDescription() { - let ip1: IndexPath = [] - let ip2: IndexPath = [1] - let ip3: IndexPath = [1, 2] - let ip4: IndexPath = [1, 2, 3] - - XCTAssertEqual(ip1.description, "[]") - XCTAssertEqual(ip2.description, "[1]") - XCTAssertEqual(ip3.description, "[1, 2]") - XCTAssertEqual(ip4.description, "[1, 2, 3]") - - XCTAssertEqual(ip1.debugDescription, ip1.description) - XCTAssertEqual(ip2.debugDescription, ip2.description) - XCTAssertEqual(ip3.debugDescription, ip3.description) - XCTAssertEqual(ip4.debugDescription, ip4.description) - } - - func test_AnyHashableContainingIndexPath() { - let values: [IndexPath] = [ - IndexPath(indexes: [1, 2]), - IndexPath(indexes: [1, 2, 3]), - IndexPath(indexes: [1, 2, 3]), - ] - let anyHashables = values.map(AnyHashable.init) - expectEqual(IndexPath.self, type(of: anyHashables[0].base)) - expectEqual(IndexPath.self, type(of: anyHashables[1].base)) - expectEqual(IndexPath.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) - } - - func test_slice_1ary() { - let indexPath: IndexPath = [0] - let res = indexPath.dropFirst() - XCTAssertEqual(0, res.count) - - let slice = indexPath[1..<1] - XCTAssertEqual(0, slice.count) - } - - func test_dropFirst() { - var pth = IndexPath(indexes:[1,2,3,4]) - while !pth.isEmpty { - // this should not crash - pth = pth.dropFirst() - } - } -} - -#if FOUNDATION_FRAMEWORK - -class TestIndexPathBridging: XCTestCase { - func testBridgeToObjC() { - let ip1: IndexPath = [] - let ip2: IndexPath = [1] - let ip3: IndexPath = [1, 2] - let ip4: IndexPath = [1, 2, 3] - - let nsip1 = ip1 as NSIndexPath - let nsip2 = ip2 as NSIndexPath - let nsip3 = ip3 as NSIndexPath - let nsip4 = ip4 as NSIndexPath - - XCTAssertEqual(nsip1.length, 0) - XCTAssertEqual(nsip2.length, 1) - XCTAssertEqual(nsip3.length, 2) - XCTAssertEqual(nsip4.length, 3) - } - - func testForceBridgeFromObjC() { - let nsip1 = NSIndexPath() - let nsip2 = NSIndexPath(index: 1) - let nsip3 = [1, 2].withUnsafeBufferPointer { (buffer: UnsafeBufferPointer) -> NSIndexPath in - return NSIndexPath(indexes: buffer.baseAddress, length: buffer.count) - } - let nsip4 = [1, 2, 3].withUnsafeBufferPointer { (buffer: UnsafeBufferPointer) -> NSIndexPath in - return NSIndexPath(indexes: buffer.baseAddress, length: buffer.count) - } - - var ip1: IndexPath? = IndexPath() - IndexPath._forceBridgeFromObjectiveC(nsip1, result: &ip1) - XCTAssertNotNil(ip1) - XCTAssertEqual(ip1!.count, 0) - - var ip2: IndexPath? = IndexPath() - IndexPath._forceBridgeFromObjectiveC(nsip2, result: &ip2) - XCTAssertNotNil(ip2) - XCTAssertEqual(ip2!.count, 1) - XCTAssertEqual(ip2![0], 1) - - var ip3: IndexPath? = IndexPath() - IndexPath._forceBridgeFromObjectiveC(nsip3, result: &ip3) - XCTAssertNotNil(ip3) - XCTAssertEqual(ip3!.count, 2) - XCTAssertEqual(ip3![0], 1) - XCTAssertEqual(ip3![1], 2) - - var ip4: IndexPath? = IndexPath() - IndexPath._forceBridgeFromObjectiveC(nsip4, result: &ip4) - XCTAssertNotNil(ip4) - XCTAssertEqual(ip4!.count, 3) - XCTAssertEqual(ip4![0], 1) - XCTAssertEqual(ip4![1], 2) - XCTAssertEqual(ip4![2], 3) - } - - func testConditionalBridgeFromObjC() { - let nsip1 = NSIndexPath() - let nsip2 = NSIndexPath(index: 1) - let nsip3 = [1, 2].withUnsafeBufferPointer { (buffer: UnsafeBufferPointer) -> NSIndexPath in - return NSIndexPath(indexes: buffer.baseAddress, length: buffer.count) - } - let nsip4 = [1, 2, 3].withUnsafeBufferPointer { (buffer: UnsafeBufferPointer) -> NSIndexPath in - return NSIndexPath(indexes: buffer.baseAddress, length: buffer.count) - } - - var ip1: IndexPath? = IndexPath() - XCTAssertTrue(IndexPath._conditionallyBridgeFromObjectiveC(nsip1, result: &ip1)) - XCTAssertNotNil(ip1) - XCTAssertEqual(ip1!.count, 0) - - var ip2: IndexPath? = IndexPath() - XCTAssertTrue(IndexPath._conditionallyBridgeFromObjectiveC(nsip2, result: &ip2)) - XCTAssertNotNil(ip2) - XCTAssertEqual(ip2!.count, 1) - XCTAssertEqual(ip2![0], 1) - - var ip3: IndexPath? = IndexPath() - XCTAssertTrue(IndexPath._conditionallyBridgeFromObjectiveC(nsip3, result: &ip3)) - XCTAssertNotNil(ip3) - XCTAssertEqual(ip3!.count, 2) - XCTAssertEqual(ip3![0], 1) - XCTAssertEqual(ip3![1], 2) - - var ip4: IndexPath? = IndexPath() - XCTAssertTrue(IndexPath._conditionallyBridgeFromObjectiveC(nsip4, result: &ip4)) - XCTAssertNotNil(ip4) - XCTAssertEqual(ip4!.count, 3) - XCTAssertEqual(ip4![0], 1) - XCTAssertEqual(ip4![1], 2) - XCTAssertEqual(ip4![2], 3) - } - - func testUnconditionalBridgeFromObjC() { - let nsip1 = NSIndexPath() - let nsip2 = NSIndexPath(index: 1) - let nsip3 = [1, 2].withUnsafeBufferPointer { (buffer: UnsafeBufferPointer) -> NSIndexPath in - return NSIndexPath(indexes: buffer.baseAddress, length: buffer.count) - } - let nsip4 = [1, 2, 3].withUnsafeBufferPointer { (buffer: UnsafeBufferPointer) -> NSIndexPath in - return NSIndexPath(indexes: buffer.baseAddress, length: buffer.count) - } - - let ip1: IndexPath = IndexPath._unconditionallyBridgeFromObjectiveC(nsip1) - XCTAssertEqual(ip1.count, 0) - - let ip2: IndexPath = IndexPath._unconditionallyBridgeFromObjectiveC(nsip2) - XCTAssertEqual(ip2.count, 1) - XCTAssertEqual(ip2[0], 1) - - let ip3: IndexPath = IndexPath._unconditionallyBridgeFromObjectiveC(nsip3) - XCTAssertEqual(ip3.count, 2) - XCTAssertEqual(ip3[0], 1) - XCTAssertEqual(ip3[1], 2) - - let ip4: IndexPath = IndexPath._unconditionallyBridgeFromObjectiveC(nsip4) - XCTAssertEqual(ip4.count, 3) - XCTAssertEqual(ip4[0], 1) - XCTAssertEqual(ip4[1], 2) - XCTAssertEqual(ip4[2], 3) - } - - func testObjcBridgeType() { - XCTAssertTrue(IndexPath._getObjectiveCType() == NSIndexPath.self) - } - - func test_AnyHashableCreatedFromNSIndexPath() { - let values: [NSIndexPath] = [ - NSIndexPath(index: 1), - NSIndexPath(index: 2), - NSIndexPath(index: 2), - ] - let anyHashables = values.map(AnyHashable.init) - expectEqual(IndexPath.self, type(of: anyHashables[0].base)) - expectEqual(IndexPath.self, type(of: anyHashables[1].base)) - expectEqual(IndexPath.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) - } - - func test_unconditionallyBridgeFromObjectiveC() { - XCTAssertEqual(IndexPath(), IndexPath._unconditionallyBridgeFromObjectiveC(nil)) - } -} - -#endif // FOUNDATION_FRAMEWORK - diff --git a/Tests/FoundationEssentialsTests/JSONEncoderTests.swift b/Tests/FoundationEssentialsTests/JSONEncoderTests.swift deleted file mode 100644 index 6697df493..000000000 --- a/Tests/FoundationEssentialsTests/JSONEncoderTests.swift +++ /dev/null @@ -1,4529 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// RUN: %target-run-simple-swift -// REQUIRES: executable_test -// REQUIRES: objc_interop -// REQUIRES: rdar49634697 -// REQUIRES: rdar55727144 - -#if canImport(TestSupport) -import TestSupport -#endif // canImport(TestSupport) - -#if canImport(FoundationEssentials) -@_spi(SwiftCorelibsFoundation) -@testable import FoundationEssentials -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#endif - -// MARK: - Test Suite - -final class JSONEncoderTests : XCTestCase { - // MARK: - Encoding Top-Level Empty Types - func testEncodingTopLevelEmptyStruct() { - let empty = EmptyStruct() - _testRoundTrip(of: empty, expectedJSON: _jsonEmptyDictionary) - } - - func testEncodingTopLevelEmptyClass() { - let empty = EmptyClass() - _testRoundTrip(of: empty, expectedJSON: _jsonEmptyDictionary) - } - - // MARK: - Encoding Top-Level Single-Value Types - func testEncodingTopLevelSingleValueEnum() { - _testRoundTrip(of: Switch.off) - _testRoundTrip(of: Switch.on) - } - - func testEncodingTopLevelSingleValueStruct() { - _testRoundTrip(of: Timestamp(3141592653)) - } - - func testEncodingTopLevelSingleValueClass() { - _testRoundTrip(of: Counter()) - } - - // MARK: - Encoding Top-Level Structured Types - func testEncodingTopLevelStructuredStruct() { - // Address is a struct type with multiple fields. - let address = Address.testValue - _testRoundTrip(of: address) - } - - func testEncodingTopLevelStructuredSingleStruct() { - // Numbers is a struct which encodes as an array through a single value container. - let numbers = Numbers.testValue - _testRoundTrip(of: numbers) - } - - func testEncodingTopLevelStructuredSingleClass() { - // Mapping is a class which encodes as a dictionary through a single value container. - let mapping = Mapping.testValue - _testRoundTrip(of: mapping) - } - - func testEncodingTopLevelDeepStructuredType() { - // Company is a type with fields which are Codable themselves. - let company = Company.testValue - _testRoundTrip(of: company) - } - - func testEncodingClassWhichSharesEncoderWithSuper() { - // Employee is a type which shares its encoder & decoder with its superclass, Person. - let employee = Employee.testValue - _testRoundTrip(of: employee) - } - - func testEncodingTopLevelNullableType() { - // EnhancedBool is a type which encodes either as a Bool or as nil. - _testRoundTrip(of: EnhancedBool.true, expectedJSON: "true".data(using: String._Encoding.utf8)!) - _testRoundTrip(of: EnhancedBool.false, expectedJSON: "false".data(using: String._Encoding.utf8)!) - _testRoundTrip(of: EnhancedBool.fileNotFound, expectedJSON: "null".data(using: String._Encoding.utf8)!) - } - - func testEncodingTopLevelArrayOfInt() { - let a = [1,2,3] - let result1 = String(data: try! JSONEncoder().encode(a), encoding: String._Encoding.utf8) - XCTAssertEqual(result1, "[1,2,3]") - - let b : [Int] = [] - let result2 = String(data: try! JSONEncoder().encode(b), encoding: String._Encoding.utf8) - XCTAssertEqual(result2, "[]") - } - - func testEncodingTopLevelWithConfiguration() throws { - // CodableTypeWithConfiguration is a struct that conforms to CodableWithConfiguration - let value = CodableTypeWithConfiguration.testValue - let encoder = JSONEncoder() - let decoder = JSONDecoder() - - var decoded = try decoder.decode(CodableTypeWithConfiguration.self, from: try encoder.encode(value, configuration: .init(1)), configuration: .init(1)) - XCTAssertEqual(decoded, value) - decoded = try decoder.decode(CodableTypeWithConfiguration.self, from: try encoder.encode(value, configuration: CodableTypeWithConfiguration.ConfigProviding.self), configuration: CodableTypeWithConfiguration.ConfigProviding.self) - XCTAssertEqual(decoded, value) - } - -#if false // FIXME: XCTest doesn't support crash tests yet rdar://20195010&22387653 - func testEncodingConflictedTypeNestedContainersWithTheSameTopLevelKey() { - struct Model : Encodable, Equatable { - let first: String - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: TopLevelCodingKeys.self) - - var firstNestedContainer = container.nestedContainer(keyedBy: FirstNestedCodingKeys.self, forKey: .top) - try firstNestedContainer.encode(self.first, forKey: .first) - - // The following line would fail as it attempts to re-encode into already encoded container is invalid. This will always fail - var secondNestedContainer = container.nestedUnkeyedContainer(forKey: .top) - try secondNestedContainer.encode("second") - } - - init(first: String) { - self.first = first - } - - static var testValue: Model { - return Model(first: "Johnny Appleseed") - } - - enum TopLevelCodingKeys : String, CodingKey { - case top - } - enum FirstNestedCodingKeys : String, CodingKey { - case first - } - } - - let model = Model.testValue - // This following test would fail as it attempts to re-encode into already encoded container is invalid. This will always fail - expectCrashLater() - _testEncodeFailure(of: model) - } -#endif - - // MARK: - Date Strategy Tests - - func testEncodingDateSecondsSince1970() { - // Cannot encode an arbitrary number of seconds since we've lost precision since 1970. - let seconds = 1000.0 - let expectedJSON = "1000".data(using: String._Encoding.utf8)! - - _testRoundTrip(of: Date(timeIntervalSince1970: seconds), - expectedJSON: expectedJSON, - dateEncodingStrategy: .secondsSince1970, - dateDecodingStrategy: .secondsSince1970) - - // Optional dates should encode the same way. - _testRoundTrip(of: Optional(Date(timeIntervalSince1970: seconds)), - expectedJSON: expectedJSON, - dateEncodingStrategy: .secondsSince1970, - dateDecodingStrategy: .secondsSince1970) - } - - func testEncodingDateMillisecondsSince1970() { - // Cannot encode an arbitrary number of seconds since we've lost precision since 1970. - let seconds = 1000.0 - let expectedJSON = "1000000".data(using: String._Encoding.utf8)! - - _testRoundTrip(of: Date(timeIntervalSince1970: seconds), - expectedJSON: expectedJSON, - dateEncodingStrategy: .millisecondsSince1970, - dateDecodingStrategy: .millisecondsSince1970) - - // Optional dates should encode the same way. - _testRoundTrip(of: Optional(Date(timeIntervalSince1970: seconds)), - expectedJSON: expectedJSON, - dateEncodingStrategy: .millisecondsSince1970, - dateDecodingStrategy: .millisecondsSince1970) - } - - fileprivate struct TopLevelArrayWrapper : Codable, Equatable where T : Codable, T : Equatable { - let value: T - - init(_ value: T) { - self.value = value - } - - func encode(to encoder: Encoder) throws { - var container = encoder.unkeyedContainer() - try container.encode(value) - } - - init(from decoder: Decoder) throws { - var container = try decoder.unkeyedContainer() - value = try container.decode(T.self) - assert(container.isAtEnd) - } - - static func ==(_ lhs: TopLevelArrayWrapper, _ rhs: TopLevelArrayWrapper) -> Bool { - return lhs.value == rhs.value - } - } - - func test_encodingDateCustom() { - let timestamp = Date() - - // We'll encode a number instead of a date. - let encode = { @Sendable (_ data: Date, _ encoder: Encoder) throws -> Void in - var container = encoder.singleValueContainer() - try container.encode(42) - } - let decode = { @Sendable (_: Decoder) throws -> Date in return timestamp } - - let expectedJSON = "42".data(using: String._Encoding.utf8)! - _testRoundTrip(of: timestamp, - expectedJSON: expectedJSON, - dateEncodingStrategy: .custom(encode), - dateDecodingStrategy: .custom(decode)) - - // Optional dates should encode the same way. - _testRoundTrip(of: Optional(timestamp), - expectedJSON: expectedJSON, - dateEncodingStrategy: .custom(encode), - dateDecodingStrategy: .custom(decode)) - - // So should wrapped dates. - let expectedJSON_array = "[42]".data(using: String._Encoding.utf8)! - _testRoundTrip(of: TopLevelArrayWrapper(timestamp), - expectedJSON: expectedJSON_array, - dateEncodingStrategy: .custom(encode), - dateDecodingStrategy: .custom(decode)) - } - - func testEncodingDateCustomEmpty() { - let timestamp = Date() - - // Encoding nothing should encode an empty keyed container ({}). - let encode = { @Sendable (_: Date, _: Encoder) throws -> Void in } - let decode = { @Sendable (_: Decoder) throws -> Date in return timestamp } - - let expectedJSON = "{}".data(using: String._Encoding.utf8)! - _testRoundTrip(of: timestamp, - expectedJSON: expectedJSON, - dateEncodingStrategy: .custom(encode), - dateDecodingStrategy: .custom(decode)) - - // Optional dates should encode the same way. - _testRoundTrip(of: Optional(timestamp), - expectedJSON: expectedJSON, - dateEncodingStrategy: .custom(encode), - dateDecodingStrategy: .custom(decode)) - } - - // MARK: - Data Strategy Tests - func testEncodingData() { - let data = Data([0xDE, 0xAD, 0xBE, 0xEF]) - - let expectedJSON = "[222,173,190,239]".data(using: String._Encoding.utf8)! - _testRoundTrip(of: data, - expectedJSON: expectedJSON, - dataEncodingStrategy: .deferredToData, - dataDecodingStrategy: .deferredToData) - - // Optional data should encode the same way. - _testRoundTrip(of: Optional(data), - expectedJSON: expectedJSON, - dataEncodingStrategy: .deferredToData, - dataDecodingStrategy: .deferredToData) - } - - func testEncodingDataCustom() { - // We'll encode a number instead of data. - let encode = { @Sendable (_ data: Data, _ encoder: Encoder) throws -> Void in - var container = encoder.singleValueContainer() - try container.encode(42) - } - let decode = { @Sendable (_: Decoder) throws -> Data in return Data() } - - let expectedJSON = "42".data(using: String._Encoding.utf8)! - _testRoundTrip(of: Data(), - expectedJSON: expectedJSON, - dataEncodingStrategy: .custom(encode), - dataDecodingStrategy: .custom(decode)) - - // Optional data should encode the same way. - _testRoundTrip(of: Optional(Data()), - expectedJSON: expectedJSON, - dataEncodingStrategy: .custom(encode), - dataDecodingStrategy: .custom(decode)) - } - - func testEncodingDataCustomEmpty() { - // Encoding nothing should encode an empty keyed container ({}). - let encode = { @Sendable (_: Data, _: Encoder) throws -> Void in } - let decode = { @Sendable (_: Decoder) throws -> Data in return Data() } - - let expectedJSON = "{}".data(using: String._Encoding.utf8)! - _testRoundTrip(of: Data(), - expectedJSON: expectedJSON, - dataEncodingStrategy: .custom(encode), - dataDecodingStrategy: .custom(decode)) - - // Optional Data should encode the same way. - _testRoundTrip(of: Optional(Data()), - expectedJSON: expectedJSON, - dataEncodingStrategy: .custom(encode), - dataDecodingStrategy: .custom(decode)) - } - - // MARK: - Non-Conforming Floating Point Strategy Tests - func testEncodingNonConformingFloats() { - _testEncodeFailure(of: Float.infinity) - _testEncodeFailure(of: Float.infinity) - _testEncodeFailure(of: -Float.infinity) - _testEncodeFailure(of: Float.nan) - - _testEncodeFailure(of: Double.infinity) - _testEncodeFailure(of: -Double.infinity) - _testEncodeFailure(of: Double.nan) - - // Optional Floats/Doubles should encode the same way. - _testEncodeFailure(of: Float.infinity) - _testEncodeFailure(of: -Float.infinity) - _testEncodeFailure(of: Float.nan) - - _testEncodeFailure(of: Double.infinity) - _testEncodeFailure(of: -Double.infinity) - _testEncodeFailure(of: Double.nan) - } - - func testEncodingNonConformingFloatStrings() { - let encodingStrategy: JSONEncoder.NonConformingFloatEncodingStrategy = .convertToString(positiveInfinity: "INF", negativeInfinity: "-INF", nan: "NaN") - let decodingStrategy: JSONDecoder.NonConformingFloatDecodingStrategy = .convertFromString(positiveInfinity: "INF", negativeInfinity: "-INF", nan: "NaN") - - _testRoundTrip(of: Float.infinity, - expectedJSON: "\"INF\"".data(using: String._Encoding.utf8)!, - nonConformingFloatEncodingStrategy: encodingStrategy, - nonConformingFloatDecodingStrategy: decodingStrategy) - _testRoundTrip(of: -Float.infinity, - expectedJSON: "\"-INF\"".data(using: String._Encoding.utf8)!, - nonConformingFloatEncodingStrategy: encodingStrategy, - nonConformingFloatDecodingStrategy: decodingStrategy) - - // Since Float.nan != Float.nan, we have to use a placeholder that'll encode NaN but actually round-trip. - _testRoundTrip(of: FloatNaNPlaceholder(), - expectedJSON: "\"NaN\"".data(using: String._Encoding.utf8)!, - nonConformingFloatEncodingStrategy: encodingStrategy, - nonConformingFloatDecodingStrategy: decodingStrategy) - - _testRoundTrip(of: Double.infinity, - expectedJSON: "\"INF\"".data(using: String._Encoding.utf8)!, - nonConformingFloatEncodingStrategy: encodingStrategy, - nonConformingFloatDecodingStrategy: decodingStrategy) - _testRoundTrip(of: -Double.infinity, - expectedJSON: "\"-INF\"".data(using: String._Encoding.utf8)!, - nonConformingFloatEncodingStrategy: encodingStrategy, - nonConformingFloatDecodingStrategy: decodingStrategy) - - // Since Double.nan != Double.nan, we have to use a placeholder that'll encode NaN but actually round-trip. - _testRoundTrip(of: DoubleNaNPlaceholder(), - expectedJSON: "\"NaN\"".data(using: String._Encoding.utf8)!, - nonConformingFloatEncodingStrategy: encodingStrategy, - nonConformingFloatDecodingStrategy: decodingStrategy) - - // Optional Floats and Doubles should encode the same way. - _testRoundTrip(of: Optional(Float.infinity), - expectedJSON: "\"INF\"".data(using: String._Encoding.utf8)!, - nonConformingFloatEncodingStrategy: encodingStrategy, - nonConformingFloatDecodingStrategy: decodingStrategy) - _testRoundTrip(of: Optional(-Float.infinity), - expectedJSON: "\"-INF\"".data(using: String._Encoding.utf8)!, - nonConformingFloatEncodingStrategy: encodingStrategy, - nonConformingFloatDecodingStrategy: decodingStrategy) - _testRoundTrip(of: Optional(Double.infinity), - expectedJSON: "\"INF\"".data(using: String._Encoding.utf8)!, - nonConformingFloatEncodingStrategy: encodingStrategy, - nonConformingFloatDecodingStrategy: decodingStrategy) - _testRoundTrip(of: Optional(-Double.infinity), - expectedJSON: "\"-INF\"".data(using: String._Encoding.utf8)!, - nonConformingFloatEncodingStrategy: encodingStrategy, - nonConformingFloatDecodingStrategy: decodingStrategy) - } - - // MARK: - Directly Encoded Array Tests - - func testDirectlyEncodedArrays() { - let encodingStrategy: JSONEncoder.NonConformingFloatEncodingStrategy = .convertToString(positiveInfinity: "INF", negativeInfinity: "-INF", nan: "NaN") - let decodingStrategy: JSONDecoder.NonConformingFloatDecodingStrategy = .convertFromString(positiveInfinity: "INF", negativeInfinity: "-INF", nan: "NaN") - - struct Arrays: Codable, Equatable { - let integers: [Int] - let doubles: [Double] - let strings: [String] - } - - let value = Arrays( - integers: [.min, 0, 42, .max], - doubles: [42.0, 3.14, .infinity, -.infinity], - strings: ["Hello", "World", "true", "0\n1", "\u{0008}"] - ) - _testRoundTrip(of: value, - nonConformingFloatEncodingStrategy: encodingStrategy, - nonConformingFloatDecodingStrategy: decodingStrategy) - _testRoundTrip(of: value, - outputFormatting: .prettyPrinted, - nonConformingFloatEncodingStrategy: encodingStrategy, - nonConformingFloatDecodingStrategy: decodingStrategy) - } - - // MARK: - Key Strategy Tests - private struct EncodeMe : Encodable { - var keyName: String - func encode(to coder: Encoder) throws { - var c = coder.container(keyedBy: _TestKey.self) - try c.encode("test", forKey: _TestKey(stringValue: keyName)!) - } - } - - func testEncodingKeyStrategyCustom() { - let expected = "{\"QQQhello\":\"test\"}" - let encoded = EncodeMe(keyName: "hello") - - let encoder = JSONEncoder() - let customKeyConversion = { @Sendable (_ path : [CodingKey]) -> CodingKey in - let key = _TestKey(stringValue: "QQQ" + path.last!.stringValue)! - return key - } - encoder.keyEncodingStrategy = .custom(customKeyConversion) - let resultData = try! encoder.encode(encoded) - let resultString = String(bytes: resultData, encoding: String._Encoding.utf8) - - XCTAssertEqual(expected, resultString) - } - - private struct EncodeFailure : Encodable { - var someValue: Double - } - - private struct EncodeFailureNested : Encodable { - var nestedValue: EncodeFailure - } - - private struct EncodeNested : Encodable { - let nestedValue: EncodeMe - } - - private struct EncodeNestedNested : Encodable { - let outerValue: EncodeNested - } - - func testEncodingKeyStrategyPath() { - // Make sure a more complex path shows up the way we want - // Make sure the path reflects keys in the Swift, not the resulting ones in the JSON - let expected = "{\"QQQouterValue\":{\"QQQnestedValue\":{\"QQQhelloWorld\":\"test\"}}}" - let encoded = EncodeNestedNested(outerValue: EncodeNested(nestedValue: EncodeMe(keyName: "helloWorld"))) - - let encoder = JSONEncoder() - // We only will mutate this from one thread as we call the encoder synchronously - nonisolated(unsafe) var callCount = 0 - - let customKeyConversion = { @Sendable (_ path : [CodingKey]) -> CodingKey in - // This should be called three times: - // 1. to convert 'outerValue' to something - // 2. to convert 'nestedValue' to something - // 3. to convert 'helloWorld' to something - callCount = callCount + 1 - - if path.count == 0 { - XCTFail("The path should always have at least one entry") - } else if path.count == 1 { - XCTAssertEqual(["outerValue"], path.map { $0.stringValue }) - } else if path.count == 2 { - XCTAssertEqual(["outerValue", "nestedValue"], path.map { $0.stringValue }) - } else if path.count == 3 { - XCTAssertEqual(["outerValue", "nestedValue", "helloWorld"], path.map { $0.stringValue }) - } else { - XCTFail("The path mysteriously had more entries") - } - - let key = _TestKey(stringValue: "QQQ" + path.last!.stringValue)! - return key - } - encoder.keyEncodingStrategy = .custom(customKeyConversion) - let resultData = try! encoder.encode(encoded) - let resultString = String(bytes: resultData, encoding: String._Encoding.utf8) - - XCTAssertEqual(expected, resultString) - XCTAssertEqual(3, callCount) - } - - private struct DecodeMe : Decodable { - let found: Bool - init(from coder: Decoder) throws { - let c = try coder.container(keyedBy: _TestKey.self) - // Get the key that we expect to be passed in (camel case) - let camelCaseKey = try c.decode(String.self, forKey: _TestKey(stringValue: "camelCaseKey")!) - - // Use the camel case key to decode from the JSON. The decoder should convert it to snake case to find it. - found = try c.decode(Bool.self, forKey: _TestKey(stringValue: camelCaseKey)!) - } - } - - private struct DecodeMe2 : Decodable { var hello: String } - - func testDecodingKeyStrategyCustom() { - let input = "{\"----hello\":\"test\"}".data(using: String._Encoding.utf8)! - let decoder = JSONDecoder() - let customKeyConversion = { @Sendable (_ path: [CodingKey]) -> CodingKey in - // This converter removes the first 4 characters from the start of all string keys, if it has more than 4 characters - let string = path.last!.stringValue - guard string.count > 4 else { return path.last! } - let newString = String(string.dropFirst(4)) - return _TestKey(stringValue: newString)! - } - decoder.keyDecodingStrategy = .custom(customKeyConversion) - let result = try! decoder.decode(DecodeMe2.self, from: input) - - XCTAssertEqual("test", result.hello) - } - - func testDecodingDictionaryStringKeyConversionUntouched() { - let input = "{\"leave_me_alone\":\"test\"}".data(using: String._Encoding.utf8)! - let decoder = JSONDecoder() - decoder.keyDecodingStrategy = .convertFromSnakeCase - let result = try! decoder.decode([String: String].self, from: input) - - XCTAssertEqual(["leave_me_alone": "test"], result) - } - - func testDecodingDictionaryFailureKeyPath() { - let input = "{\"leave_me_alone\":\"test\"}".data(using: String._Encoding.utf8)! - let decoder = JSONDecoder() - decoder.keyDecodingStrategy = .convertFromSnakeCase - do { - _ = try decoder.decode([String: Int].self, from: input) - } catch DecodingError.typeMismatch(_, let context) { - XCTAssertEqual(1, context.codingPath.count) - XCTAssertEqual("leave_me_alone", context.codingPath[0].stringValue) - } catch { - XCTFail("Unexpected error: \(String(describing: error))") - } - } - - private struct DecodeFailure : Decodable { - var intValue: Int - } - - private struct DecodeFailureNested : Decodable { - var nestedValue: DecodeFailure - } - - private struct DecodeMe3 : Codable { - var thisIsCamelCase : String - } - - func testKeyStrategyDuplicateKeys() { - // This test is mostly to make sure we don't assert on duplicate keys - struct DecodeMe5 : Codable { - var oneTwo : String - var numberOfKeys : Int - - enum CodingKeys : String, CodingKey { - case oneTwo - case oneTwoThree - } - - init() { - oneTwo = "test" - numberOfKeys = 0 - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - oneTwo = try container.decode(String.self, forKey: .oneTwo) - numberOfKeys = container.allKeys.count - } - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(oneTwo, forKey: .oneTwo) - try container.encode("test2", forKey: .oneTwoThree) - } - } - - let customKeyConversion = { @Sendable (_ path: [CodingKey]) -> CodingKey in - // All keys are the same! - return _TestKey(stringValue: "oneTwo")! - } - - // Decoding - // This input has a dictionary with two keys, but only one will end up in the container - let input = "{\"unused key 1\":\"test1\",\"unused key 2\":\"test2\"}".data(using: String._Encoding.utf8)! - let decoder = JSONDecoder() - decoder.keyDecodingStrategy = .custom(customKeyConversion) - - let decodingResult = try! decoder.decode(DecodeMe5.self, from: input) - // There will be only one result for oneTwo. - XCTAssertEqual(1, decodingResult.numberOfKeys) - // While the order in which these values should be taken is NOT defined by the JSON spec in any way, the historical behavior has been to select the *first* value for a given key. - XCTAssertEqual(decodingResult.oneTwo, "test1") - - // Encoding - let encoded = DecodeMe5() - let encoder = JSONEncoder() - encoder.keyEncodingStrategy = .custom(customKeyConversion) - let decodingResultData = try! encoder.encode(encoded) - let decodingResultString = String(bytes: decodingResultData, encoding: String._Encoding.utf8) - - // There will be only one value in the result (the second one encoded) - XCTAssertEqual("{\"oneTwo\":\"test2\"}", decodingResultString) - } - - // MARK: - Encoder Features - func testNestedContainerCodingPaths() { - let encoder = JSONEncoder() - do { - let _ = try encoder.encode(NestedContainersTestType()) - } catch let error as NSError { - XCTFail("Caught error during encoding nested container types: \(error)") - } - } - - func testSuperEncoderCodingPaths() { - let encoder = JSONEncoder() - do { - let _ = try encoder.encode(NestedContainersTestType(testSuperEncoder: true)) - } catch let error as NSError { - XCTFail("Caught error during encoding nested container types: \(error)") - } - } - - // MARK: - Type coercion - func testTypeCoercion() { - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Int].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Int8].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Int16].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Int32].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Int64].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Int128].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [UInt].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [UInt8].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [UInt16].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [UInt32].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [UInt64].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [UInt128].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Float].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Double].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [Int], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [Int8], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [Int16], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [Int32], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [Int64], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [Int128], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [UInt], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [UInt8], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [UInt16], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [UInt32], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [UInt64], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [UInt128], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0.0, 1.0] as [Float], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0.0, 1.0] as [Double], as: [Bool].self) - } - - func testDecodingConcreteTypeParameter() { - let encoder = JSONEncoder() - guard let json = try? encoder.encode(Employee.testValue) else { - XCTFail("Unable to encode Employee.") - return - } - - let decoder = JSONDecoder() - guard let decoded = try? decoder.decode(Employee.self as Person.Type, from: json) else { - XCTFail("Failed to decode Employee as Person from JSON.") - return - } - - expectEqual(type(of: decoded), Employee.self, "Expected decoded value to be of type Employee; got \(type(of: decoded)) instead.") - } - - // MARK: - Encoder State - // SR-6078 - func testEncoderStateThrowOnEncode() { - struct ReferencingEncoderWrapper : Encodable { - let value: T - init(_ value: T) { self.value = value } - - func encode(to encoder: Encoder) throws { - // This approximates a subclass calling into its superclass, where the superclass encodes a value that might throw. - // The key here is that getting the superEncoder creates a referencing encoder. - var container = encoder.unkeyedContainer() - let superEncoder = container.superEncoder() - - // Pushing a nested container on leaves the referencing encoder with multiple containers. - var nestedContainer = superEncoder.unkeyedContainer() - try nestedContainer.encode(value) - } - } - - // The structure that would be encoded here looks like - // - // [[[Float.infinity]]] - // - // The wrapper asks for an unkeyed container ([^]), gets a super encoder, and creates a nested container into that ([[^]]). - // We then encode an array into that ([[[^]]]), which happens to be a value that causes us to throw an error. - // - // The issue at hand reproduces when you have a referencing encoder (superEncoder() creates one) that has a container on the stack (unkeyedContainer() adds one) that encodes a value going through box_() (Array does that) that encodes something which throws (Float.infinity does that). - // When reproducing, this will cause a test failure via fatalError(). - _ = try? JSONEncoder().encode(ReferencingEncoderWrapper([Float.infinity])) - } - - func testEncoderStateThrowOnEncodeCustomDate() { - // This test is identical to testEncoderStateThrowOnEncode, except throwing via a custom Date closure. - struct ReferencingEncoderWrapper : Encodable { - let value: T - init(_ value: T) { self.value = value } - func encode(to encoder: Encoder) throws { - var container = encoder.unkeyedContainer() - let superEncoder = container.superEncoder() - var nestedContainer = superEncoder.unkeyedContainer() - try nestedContainer.encode(value) - } - } - - // The closure needs to push a container before throwing an error to trigger. - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .custom({ _, encoder in - let _ = encoder.unkeyedContainer() - enum CustomError : Error { case foo } - throw CustomError.foo - }) - - _ = try? encoder.encode(ReferencingEncoderWrapper(Date())) - } - - func testEncoderStateThrowOnEncodeCustomData() { - // This test is identical to testEncoderStateThrowOnEncode, except throwing via a custom Data closure. - struct ReferencingEncoderWrapper : Encodable { - let value: T - init(_ value: T) { self.value = value } - func encode(to encoder: Encoder) throws { - var container = encoder.unkeyedContainer() - let superEncoder = container.superEncoder() - var nestedContainer = superEncoder.unkeyedContainer() - try nestedContainer.encode(value) - } - } - - // The closure needs to push a container before throwing an error to trigger. - let encoder = JSONEncoder() - encoder.dataEncodingStrategy = .custom({ _, encoder in - let _ = encoder.unkeyedContainer() - enum CustomError : Error { case foo } - throw CustomError.foo - }) - - _ = try? encoder.encode(ReferencingEncoderWrapper(Data())) - } - - func test_106506794() throws { - struct Level1: Codable, Equatable { - let level2: Level2 - - enum CodingKeys: String, CodingKey { - case level2 - } - - func encode(to encoder: Encoder) throws { - var keyed = encoder.container(keyedBy: Self.CodingKeys.self) - var nested = keyed.nestedUnkeyedContainer(forKey: .level2) - try nested.encode(level2) - } - - init(from decoder: Decoder) throws { - let keyed = try decoder.container(keyedBy: Self.CodingKeys.self) - var nested = try keyed.nestedUnkeyedContainer(forKey: .level2) - self.level2 = try nested.decode(Level2.self) - } - - struct Level2: Codable, Equatable { - let name : String - } - - init(level2: Level2) { - self.level2 = level2 - } - } - - let value = Level1.init(level2: .init(name: "level2")) - let data = try JSONEncoder().encode(value) - - do { - let decodedValue = try JSONDecoder().decode(Level1.self, from: data) - XCTAssertEqual(value, decodedValue) - } catch { - XCTFail("Decode should not have failed with error: \(error))") - } - } - - // MARK: - Decoder State - // SR-6048 - func testDecoderStateThrowOnDecode() { - // The container stack here starts as [[1,2,3]]. Attempting to decode as [String] matches the outer layer (Array), and begins decoding the array. - // Once Array decoding begins, 1 is pushed onto the container stack ([[1,2,3], 1]), and 1 is attempted to be decoded as String. This throws a .typeMismatch, but the container is not popped off the stack. - // When attempting to decode [Int], the container stack is still ([[1,2,3], 1]), and 1 fails to decode as [Int]. - let json = "[1,2,3]".data(using: String._Encoding.utf8)! - let _ = try! JSONDecoder().decode(EitherDecodable<[String], [Int]>.self, from: json) - } - - func testDecoderStateThrowOnDecodeCustomDate() { - // This test is identical to testDecoderStateThrowOnDecode, except we're going to fail because our closure throws an error, not because we hit a type mismatch. - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .custom({ decoder in - enum CustomError : Error { case foo } - throw CustomError.foo - }) - - let json = "1".data(using: String._Encoding.utf8)! - let _ = try! decoder.decode(EitherDecodable.self, from: json) - } - - func testDecoderStateThrowOnDecodeCustomData() { - // This test is identical to testDecoderStateThrowOnDecode, except we're going to fail because our closure throws an error, not because we hit a type mismatch. - let decoder = JSONDecoder() - decoder.dataDecodingStrategy = .custom({ decoder in - enum CustomError : Error { case foo } - throw CustomError.foo - }) - - let json = "1".data(using: String._Encoding.utf8)! - let _ = try! decoder.decode(EitherDecodable.self, from: json) - } - - - func testDecodingFailure() { - struct DecodeFailure : Decodable { - var invalid: String - } - let toDecode = "{\"invalid\": json}"; - _testDecodeFailure(of: DecodeFailure.self, data: toDecode.data(using: String._Encoding.utf8)!) - } - - func testDecodingFailureThrowInInitKeyedContainer() { - struct DecodeFailure : Decodable { - private enum CodingKeys: String, CodingKey { - case checkedString - } - - private enum Error: Swift.Error { - case expectedError - } - - var checkedString: String - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let string = try container.decode(String.self, forKey: .checkedString) - guard string == "foo" else { - throw Error.expectedError - } - self.checkedString = string // shouldn't happen - } - } - - let toDecode = "{ \"checkedString\" : \"baz\" }" - _testDecodeFailure(of: DecodeFailure.self, data: toDecode.data(using: String._Encoding.utf8)!) - } - - func testDecodingFailureThrowInInitSingleContainer() { - struct DecodeFailure : Decodable { - private enum Error: Swift.Error { - case expectedError - } - - var checkedString: String - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - let string = try container.decode(String.self) - guard string == "foo" else { - throw Error.expectedError - } - self.checkedString = string // shouldn't happen - } - } - - let toDecode = "{ \"checkedString\" : \"baz\" }" - _testDecodeFailure(of: DecodeFailure.self, data: toDecode.data(using: String._Encoding.utf8)!) - } - - func testInvalidFragment() { - struct DecodeFailure: Decodable { - var foo: String - } - let toDecode = "\"foo" - _testDecodeFailure(of: DecodeFailure.self, data: toDecode.data(using: String._Encoding.utf8)!) - } - - func testRepeatedFailedNilChecks() { - struct RepeatNilCheckDecodable : Decodable { - enum Failure : Error { - case badNil - case badValue(expected: Int, actual: Int) - } - - init(from decoder: Decoder) throws { - var unkeyedContainer = try decoder.unkeyedContainer() - - guard try unkeyedContainer.decodeNil() == false else { - throw Failure.badNil - } - guard try unkeyedContainer.decodeNil() == false else { - throw Failure.badNil - } - let value = try unkeyedContainer.decode(Int.self) - guard value == 1 else { - throw Failure.badValue(expected: 1, actual: value) - } - - guard try unkeyedContainer.decodeNil() == false else { - throw Failure.badNil - } - guard try unkeyedContainer.decodeNil() == false else { - throw Failure.badNil - } - let value2 = try unkeyedContainer.decode(Int.self) - guard value2 == 2 else { - throw Failure.badValue(expected: 2, actual: value2) - } - - guard try unkeyedContainer.decodeNil() == false else { - throw Failure.badNil - } - guard try unkeyedContainer.decodeNil() == false else { - throw Failure.badNil - } - let value3 = try unkeyedContainer.decode(Int.self) - guard value3 == 3 else { - throw Failure.badValue(expected: 3, actual: value3) - } - } - } - let json = "[1, 2, 3]".data(using: String._Encoding.utf8)! - XCTAssertNoThrow(try JSONDecoder().decode(RepeatNilCheckDecodable.self, from: json)) - } - - func testDelayedDecoding() throws { - - // One variation is deferring the use of a container. - struct DelayedDecodable_ContainerVersion : Codable { - var _i : Int? = nil - init(_ i: Int) { - self._i = i - } - - func encode(to encoder: Encoder) throws { - var c = encoder.unkeyedContainer() - try c.encode(_i!) - } - - var cont : UnkeyedDecodingContainer? = nil - init(from decoder: Decoder) throws { - cont = try decoder.unkeyedContainer() - } - - var i : Int { - get throws { - if let i = _i { - return i - } - var contCopy = cont! - return try contCopy.decode(Int.self) - } - } - } - - let before = DelayedDecodable_ContainerVersion(42) - let data = try JSONEncoder().encode(before) - - let decoded = try JSONDecoder().decode(DelayedDecodable_ContainerVersion.self, from: data) - XCTAssertNoThrow(try decoded.i) - - // The other variant is deferring the use of the *top-level* decoder. This does NOT work for non-top level decoders. - struct DelayedDecodable_DecoderVersion : Codable { - var _i : Int? = nil - init(_ i: Int) { - self._i = i - } - - func encode(to encoder: Encoder) throws { - var c = encoder.unkeyedContainer() - try c.encode(_i!) - } - - var decoder : Decoder? = nil - init(from decoder: Decoder) throws { - self.decoder = decoder - } - - var i : Int { - get throws { - if let i = _i { - return i - } - var unkeyed = try decoder!.unkeyedContainer() - return try unkeyed.decode(Int.self) - } - } - } - // Reuse the same data. - let decoded2 = try JSONDecoder().decode(DelayedDecodable_DecoderVersion.self, from: data) - XCTAssertNoThrow(try decoded2.i) - } - - // MARK: - Helper Functions - private var _jsonEmptyDictionary: Data { - return "{}".data(using: String._Encoding.utf8)! - } - - private func _testEncodeFailure(of value: T) { - do { - let _ = try JSONEncoder().encode(value) - XCTFail("Encode of top-level \(T.self) was expected to fail.") - } catch { - XCTAssertNotNil(error); - } - } - - private func _testDecodeFailure(of value: T.Type, data: Data) { - do { - let _ = try JSONDecoder().decode(value, from: data) - XCTFail("Decode of top-level \(value) was expected to fail.") - } catch { - XCTAssertNotNil(error); - } - } - - private func _testRoundTrip(of value: T, - expectedJSON json: Data? = nil, - outputFormatting: JSONEncoder.OutputFormatting = [], - dateEncodingStrategy: JSONEncoder.DateEncodingStrategy = .deferredToDate, - dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .deferredToDate, - dataEncodingStrategy: JSONEncoder.DataEncodingStrategy = .base64, - dataDecodingStrategy: JSONDecoder.DataDecodingStrategy = .base64, - keyEncodingStrategy: JSONEncoder.KeyEncodingStrategy = .useDefaultKeys, - keyDecodingStrategy: JSONDecoder.KeyDecodingStrategy = .useDefaultKeys, - nonConformingFloatEncodingStrategy: JSONEncoder.NonConformingFloatEncodingStrategy = .throw, - nonConformingFloatDecodingStrategy: JSONDecoder.NonConformingFloatDecodingStrategy = .throw) where T : Codable, T : Equatable { - var payload: Data! = nil - do { - let encoder = JSONEncoder() - encoder.outputFormatting = outputFormatting - encoder.dateEncodingStrategy = dateEncodingStrategy - encoder.dataEncodingStrategy = dataEncodingStrategy - encoder.nonConformingFloatEncodingStrategy = nonConformingFloatEncodingStrategy - encoder.keyEncodingStrategy = keyEncodingStrategy - payload = try encoder.encode(value) - } catch { - XCTFail("Failed to encode \(T.self) to JSON: \(error)") - } - - if let expectedJSON = json { - let expected = String(data: expectedJSON, encoding: .utf8)! - let actual = String(data: payload, encoding: .utf8)! - XCTAssertEqual(expected, actual, "Produced JSON not identical to expected JSON.") - } - - do { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = dateDecodingStrategy - decoder.dataDecodingStrategy = dataDecodingStrategy - decoder.nonConformingFloatDecodingStrategy = nonConformingFloatDecodingStrategy - decoder.keyDecodingStrategy = keyDecodingStrategy - let decoded = try decoder.decode(T.self, from: payload) - XCTAssertEqual(decoded, value, "\(T.self) did not round-trip to an equal value.") - } catch { - XCTFail("Failed to decode \(T.self) from JSON: \(error)") - } - } - - private func _testRoundTripTypeCoercionFailure(of value: T, as type: U.Type) where T : Codable, U : Codable { - do { - let data = try JSONEncoder().encode(value) - let _ = try JSONDecoder().decode(U.self, from: data) - XCTFail("Coercion from \(T.self) to \(U.self) was expected to fail.") - } catch {} - } - - private func _test(JSONString: String, to object: T) { -#if FOUNDATION_FRAMEWORK - let encs : [String._Encoding] = [.utf8, .utf16BigEndian, .utf16LittleEndian, .utf32BigEndian, .utf32LittleEndian] -#else - // TODO: Reenable other encoding once string.data(using:) is fully implemented. - let encs : [String._Encoding] = [.utf8, .utf16BigEndian, .utf16LittleEndian] -#endif - let decoder = JSONDecoder() - for enc in encs { - let data = JSONString.data(using: enc)! - let parsed : T - do { - parsed = try decoder.decode(T.self, from: data) - } catch { - XCTFail("Failed to decode \(JSONString) with encoding \(enc): Error: \(error)") - continue - } - XCTAssertEqual(object, parsed) - } - } - - func test_JSONEscapedSlashes() { - _test(JSONString: "\"\\/test\\/path\"", to: "/test/path") - _test(JSONString: "\"\\\\/test\\\\/path\"", to: "\\/test\\/path") - } - - func test_JSONEscapedForwardSlashes() { - _testRoundTrip(of: ["/":1], expectedJSON: -""" -{"\\/":1} -""".data(using: String._Encoding.utf8)!) - } - - func test_JSONUnicodeCharacters() { - // UTF8: - // E9 96 86 E5 B4 AC EB B0 BA EB 80 AB E9 A2 92 - // 閆崬밺뀫颒 - _test(JSONString: "[\"閆崬밺뀫颒\"]", to: ["閆崬밺뀫颒"]) - _test(JSONString: "[\"本日\"]", to: ["本日"]) - } - - func test_JSONUnicodeEscapes() throws { - let testCases = [ - // e-acute and greater-than-or-equal-to - "\"\\u00e9\\u2265\"" : "é≥", - - // e-acute and greater-than-or-equal-to, surrounded by 42 - "\"42\\u00e942\\u226542\"" : "42é42≥42", - - // e-acute with upper-case hex - "\"\\u00E9\"" : "é", - - // G-clef (UTF16 surrogate pair) 0x1D11E - "\"\\uD834\\uDD1E\"" : "ð„ž", - ] - for (input, expectedOutput) in testCases { - _test(JSONString: input, to: expectedOutput) - } - } - - func test_encodingJSONHexUnicodeEscapes() throws { - let testCases = [ - "\u{0001}\u{0002}\u{0003}": "\"\\u0001\\u0002\\u0003\"", - "\u{0010}\u{0018}\u{001f}": "\"\\u0010\\u0018\\u001f\"", - ] - for (string, json) in testCases { - _testRoundTrip(of: string, expectedJSON: Data(json.utf8)) - } - } - - func test_JSONBadUnicodeEscapes() { - let badCases = ["\\uD834", "\\uD834hello", "hello\\uD834", "\\uD834\\u1221", "\\uD8", "\\uD834x\\uDD1E"] - for str in badCases { - let data = str.data(using: String._Encoding.utf8)! - XCTAssertThrowsError(try JSONDecoder().decode(String.self, from: data)) - } - } - - func test_nullByte() throws { - let string = "abc\u{0000}def" - let encoder = JSONEncoder() - let decoder = JSONDecoder() - - let data = try encoder.encode([string]) - let decoded = try decoder.decode([String].self, from: data) - XCTAssertEqual([string], decoded) - - let data2 = try encoder.encode([string:string]) - let decoded2 = try decoder.decode([String:String].self, from: data2) - XCTAssertEqual([string:string], decoded2) - - struct Container: Codable { - let s: String - } - let data3 = try encoder.encode(Container(s: string)) - let decoded3 = try decoder.decode(Container.self, from: data3) - XCTAssertEqual(decoded3.s, string) - } - - func test_superfluouslyEscapedCharacters() { - let json = "[\"\\h\\e\\l\\l\\o\"]" - XCTAssertThrowsError(try JSONDecoder().decode([String].self, from: json.data(using: String._Encoding.utf8)!)) - } - - func test_equivalentUTF8Sequences() { - let json = -""" -{ - "caf\\u00e9" : true, - "cafe\\u0301" : false -} -""".data(using: String._Encoding.utf8)! - - do { - let dict = try JSONDecoder().decode([String:Bool].self, from: json) - XCTAssertEqual(dict.count, 1) - } catch { - XCTFail("Unexpected error: \(error)") - } - } - - func test_JSONControlCharacters() { - let array = [ - "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", - "\\u0005", "\\u0006", "\\u0007", "\\b", "\\t", - "\\n", "\\u000b", "\\f", "\\r", "\\u000e", - "\\u000f", "\\u0010", "\\u0011", "\\u0012", "\\u0013", - "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", - "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d", - "\\u001e", "\\u001f", " " - ] - for (ascii, json) in zip(0...0x20, array) { - let quotedJSON = "\"\(json)\"" - let expectedResult = String(Character(UnicodeScalar(ascii)!)) - _test(JSONString: quotedJSON, to: expectedResult) - } - } - - func test_JSONNumberFragments() { - let array = ["0 ", "1.0 ", "0.1 ", "1e3 ", "-2.01e-3 ", "0", "1.0", "1e3", "-2.01e-3", "0e-10"] - let expected = [0, 1.0, 0.1, 1000, -0.00201, 0, 1.0, 1000, -0.00201, 0] - for (json, expected) in zip(array, expected) { - _test(JSONString: json, to: expected) - } - } - - func test_invalidJSONNumbersFailAsExpected() { - let array = ["0.", "1e ", "-2.01e- ", "+", "2.01e-1234", "+2.0q", "2s", "NaN", "nan", "Infinity", "inf", "-", "0x42", "1.e2"] - for json in array { - let data = json.data(using: String._Encoding.utf8)! - XCTAssertThrowsError(try JSONDecoder().decode(Float.self, from: data), "Expected error for input \"\(json)\"") - } - } - - func _checkExpectedThrownDataCorruptionUnderlyingError(contains substring: String, closure: () throws -> Void) { - do { - try closure() - XCTFail("Expected failure containing string: \"\(substring)\"") - } catch let error as DecodingError { - guard case let .dataCorrupted(context) = error else { - XCTFail("Unexpected DecodingError type: \(error)") - return - } -#if FOUNDATION_FRAMEWORK - let nsError = context.underlyingError! as NSError - XCTAssertTrue(nsError.debugDescription.contains(substring), "Description \"\(nsError.debugDescription)\" doesn't contain substring \"\(substring)\"") -#endif - } catch { - XCTFail("Unexpected error type: \(error)") - } - } - - func test_topLevelFragmentsWithGarbage() { - _checkExpectedThrownDataCorruptionUnderlyingError(contains: "Unexpected character") { - let _ = try JSONDecoder().decode(Bool.self, from: "tru_".data(using: String._Encoding.utf8)!) - let _ = try json5Decoder.decode(Bool.self, from: "tru_".data(using: String._Encoding.utf8)!) - } - _checkExpectedThrownDataCorruptionUnderlyingError(contains: "Unexpected character") { - let _ = try JSONDecoder().decode(Bool.self, from: "fals_".data(using: String._Encoding.utf8)!) - let _ = try json5Decoder.decode(Bool.self, from: "fals_".data(using: String._Encoding.utf8)!) - } - _checkExpectedThrownDataCorruptionUnderlyingError(contains: "Unexpected character") { - let _ = try JSONDecoder().decode(Bool?.self, from: "nul_".data(using: String._Encoding.utf8)!) - let _ = try json5Decoder.decode(Bool?.self, from: "nul_".data(using: String._Encoding.utf8)!) - } - } - - func test_topLevelNumberFragmentsWithJunkDigitCharacters() { - let fullData = "3.141596".data(using: String._Encoding.utf8)! - let partialData = fullData[0..<4] - - XCTAssertEqual(3.14, try JSONDecoder().decode(Double.self, from: partialData)) - } - - func test_depthTraversal() { - struct SuperNestedArray : Decodable { - init(from decoder: Decoder) throws { - var container = try decoder.unkeyedContainer() - while container.count! > 0 { - container = try container.nestedUnkeyedContainer() - } - } - } - - let MAX_DEPTH = 512 - let jsonGood = String(repeating: "[", count: MAX_DEPTH / 2) + String(repeating: "]", count: MAX_DEPTH / 2) - let jsonBad = String(repeating: "[", count: MAX_DEPTH + 1) + String(repeating: "]", count: MAX_DEPTH + 1) - - XCTAssertNoThrow(try JSONDecoder().decode(SuperNestedArray.self, from: jsonGood.data(using: String._Encoding.utf8)!)) - XCTAssertThrowsError(try JSONDecoder().decode(SuperNestedArray.self, from: jsonBad.data(using: String._Encoding.utf8)!)) - - } - - func test_JSONPermitsTrailingCommas() { - // Trailing commas aren't valid JSON and should never be emitted, but are syntactically unambiguous and are allowed by - // most parsers for ease of use. - let json = "{\"key\" : [ true, ],}" - let data = json.data(using: String._Encoding.utf8)! - - let result = try! JSONDecoder().decode([String:[Bool]].self, from: data) - let expected = ["key" : [true]] - XCTAssertEqual(result, expected) - } - - func test_whitespaceOnlyData() { - let data = " ".data(using: String._Encoding.utf8)! - XCTAssertThrowsError(try JSONDecoder().decode(Int.self, from: data)) - } - - func test_smallFloatNumber() { - _testRoundTrip(of: [["magic_number" : 7.45673334164903e-115]]) - } - - func test_largeIntegerNumber() { - let num : UInt64 = 6032314514195021674 - let json = "{\"a\":\(num)}" - let data = json.data(using: String._Encoding.utf8)! - - let result = try! JSONDecoder().decode([String:UInt64].self, from: data) - let number = result["a"]! - XCTAssertEqual(number, num) - } - - func test_largeIntegerNumberIsNotRoundedToNearestDoubleWhenDecodingAsAnInteger() { - XCTAssertEqual(Double(sign: .plus, exponent: 63, significand: 1).ulp, 2048) - XCTAssertEqual(Double(sign: .plus, exponent: 64, significand: 1).ulp, 4096) - - let int64s: [(String, Int64?)] = [ - ("-9223372036854776833", nil), // -2^63 - 1025 (Double: -2^63 - 2048) - ("-9223372036854776832", nil), // -2^63 - 1024 (Double: -2^63) - ("-9223372036854775809", nil), // -2^63 - 1 (Double: -2^63) - ("-9223372036854775808", Int64.min), // -2^63 (Double: -2^63) - - ( "9223372036854775807", Int64.max), // 2^63 - 1 (Double: 2^63) - ( "9223372036854775808", nil), // 2^63 (Double: 2^63) - ( "9223372036854776832", nil), // 2^63 + 1024 (Double: 2^63) - ( "9223372036854776833", nil), // 2^63 + 1025 (Double: 2^63 + 2048) - ] - - let uint64s: [(String, UInt64?)] = [ - ( "9223372036854775807", 1 << 63 - 0001), // 2^63 - 1 (Double: 2^63) - ( "9223372036854775808", 1 << 63 + 0000), // 2^63 (Double: 2^63) - ( "9223372036854776832", 1 << 63 + 1024), // 2^63 + 1024 (Double: 2^63) - ( "9223372036854776833", 1 << 63 + 1025), // 2^63 + 1025 (Double: 2^63 + 2048) - - ("18446744073709551615", UInt64.max), // 2^64 - 1 (Double: 2^64) - ("18446744073709551616", nil), // 2^64 (Double: 2^64) - ("18446744073709553664", nil), // 2^64 + 2048 (Double: 2^64) - ("18446744073709553665", nil), // 2^64 + 2049 (Double: 2^64 + 4096) - ] - - for json5 in [true, false] { - let decoder = JSONDecoder() - decoder.allowsJSON5 = json5 - - for (json, value) in int64s { - let result = try? decoder.decode(Int64.self, from: json.data(using: String._Encoding.utf8)!) - XCTAssertEqual(result, value, "Unexpected \(decoder) result for input \"\(json)\"") - } - - for (json, value) in uint64s { - let result = try? decoder.decode(UInt64.self, from: json.data(using: String._Encoding.utf8)!) - XCTAssertEqual(result, value, "Unexpected \(decoder) result for input \"\(json)\"") - } - } - } - - func test_roundTrippingExtremeValues() { - struct Numbers : Codable, Equatable { - let floats : [Float] - let doubles : [Double] - } - let testValue = Numbers(floats: [.greatestFiniteMagnitude, .leastNormalMagnitude], doubles: [.greatestFiniteMagnitude, .leastNormalMagnitude]) - _testRoundTrip(of: testValue) - } - - func test_roundTrippingInt128() { - let values = [ - Int128.min, - Int128.min + 1, - -0x1_0000_0000_0000_0000, - 0x0_8000_0000_0000_0000, - -1, - 0, - 0x7fff_ffff_ffff_ffff, - 0x8000_0000_0000_0000, - 0xffff_ffff_ffff_ffff, - 0x1_0000_0000_0000_0000, - .max - ] - for i128 in values { - _testRoundTrip(of: i128) - } - } - - func test_Int128SlowPath() { - let decoder = JSONDecoder() - let work: [Int128] = [18446744073709551615, -18446744073709551615] - for value in work { - // force the slow-path by appending ".0" - let json = "\(value).0".data(using: String._Encoding.utf8)! - XCTAssertEqual(value, try? decoder.decode(Int128.self, from: json)) - } - // These should work, but making them do so probably requires - // rewriting the slow path to use a dedicated parser. For now, - // we ensure that they throw instead of returning some bogus - // result. - let shouldWorkButDontYet: [Int128] = [ - .min, -18446744073709551616, 18446744073709551616, .max - ] - for value in shouldWorkButDontYet { - // force the slow-path by appending ".0" - let json = "\(value).0".data(using: String._Encoding.utf8)! - XCTAssertThrowsError(try decoder.decode(Int128.self, from: json)) - } - } - - func test_roundTrippingUInt128() { - let values = [ - UInt128.zero, - 1, - 0x0000_0000_0000_0000_7fff_ffff_ffff_ffff, - 0x0000_0000_0000_0000_8000_0000_0000_0000, - 0x0000_0000_0000_0000_ffff_ffff_ffff_ffff, - 0x0000_0000_0000_0001_0000_0000_0000_0000, - 0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ffff, - 0x8000_0000_0000_0000_0000_0000_0000_0000, - .max - ] - for u128 in values { - _testRoundTrip(of: u128) - } - } - - func test_UInt128SlowPath() { - let decoder = JSONDecoder() - let work: [UInt128] = [18446744073709551615] - for value in work { - // force the slow-path by appending ".0" - let json = "\(value).0".data(using: String._Encoding.utf8)! - XCTAssertEqual(value, try? decoder.decode(UInt128.self, from: json)) - } - // These should work, but making them do so probably requires - // rewriting the slow path to use a dedicated parser. For now, - // we ensure that they throw instead of returning some bogus - // result. - let shouldWorkButDontYet: [UInt128] = [ - 18446744073709551616, .max - ] - for value in shouldWorkButDontYet { - // force the slow-path by appending ".0" - let json = "\(value).0".data(using: String._Encoding.utf8)! - XCTAssertThrowsError(try decoder.decode(UInt128.self, from: json)) - } - } - - func test_roundTrippingDoubleValues() { - struct Numbers : Codable, Equatable { - let doubles : [String:Double] - let decimals : [String:Decimal] - } - let testValue = Numbers( - doubles: [ - "-55.66" : -55.66, - "-9.81" : -9.81, - "-0.284" : -0.284, - "-3.4028234663852886e+38" : Double(-Float.greatestFiniteMagnitude), - "-1.1754943508222875e-38" : Double(-Float.leastNormalMagnitude), - "-1.7976931348623157e+308" : -.greatestFiniteMagnitude, - "-2.2250738585072014e-308" : -.leastNormalMagnitude, - "0.000001" : 0.000001, - ], - decimals: [ - "1.234567891011121314" : Decimal(string: "1.234567891011121314")!, - "-1.234567891011121314" : Decimal(string: "-1.234567891011121314")!, - "0.1234567891011121314" : Decimal(string: "0.1234567891011121314")!, - "-0.1234567891011121314" : Decimal(string: "-0.1234567891011121314")!, - "123.4567891011121314e-100" : Decimal(string: "123.4567891011121314e-100")!, - "-123.4567891011121314e-100" : Decimal(string: "-123.4567891011121314e-100")!, - "11234567891011121314e-100" : Decimal(string: "1234567891011121314e-100")!, - "-1234567891011121314e-100" : Decimal(string: "-1234567891011121314e-100")!, - "0.1234567891011121314e-100" : Decimal(string: "0.1234567891011121314e-100")!, - "-0.1234567891011121314e-100" : Decimal(string: "-0.1234567891011121314e-100")!, - "3.14159265358979323846264338327950288419" : Decimal(string: "3.14159265358979323846264338327950288419")!, - "2.71828182845904523536028747135266249775" : Decimal(string: "2.71828182845904523536028747135266249775")!, - "440474310512876335.18692524723746578303827301433673643795" : Decimal(string: "440474310512876335.18692524723746578303827301433673643795")! - ] - ) - _testRoundTrip(of: testValue) - } - - func test_decodeLargeDoubleAsInteger() { - let data = try! JSONEncoder().encode(Double.greatestFiniteMagnitude) - XCTAssertThrowsError(try JSONDecoder().decode(UInt64.self, from: data)) - } - - func test_localeDecimalPolicyIndependence() { - var currentLocale: UnsafeMutablePointer? = nil - if let localePtr = setlocale(LC_ALL, nil) { - currentLocale = strdup(localePtr) - } - - defer { - if let currentLocale { - setlocale(LC_ALL, currentLocale) - free(currentLocale) - } - } - - let orig = ["decimalValue" : 1.1] - - do { - setlocale(LC_ALL, "fr_FR") - let data = try JSONEncoder().encode(orig) - -#if os(Windows) - setlocale(LC_ALL, "en_US") -#else - setlocale(LC_ALL, "en_US_POSIX") -#endif - let decoded = try JSONDecoder().decode(type(of: orig).self, from: data) - - XCTAssertEqual(orig, decoded) - } catch { - XCTFail("Error: \(error)") - } - } - - func test_whitespace() { - let tests : [(json: String, expected: [String:Bool])] = [ - ("{\"v\"\n : true}", ["v":true]), - ("{\"v\"\r\n : true}", ["v":true]), - ("{\"v\"\r : true}", ["v":true]) - ] - for test in tests { - let data = test.json.data(using: String._Encoding.utf8)! - let decoded = try! JSONDecoder().decode([String:Bool].self, from: data) - XCTAssertEqual(test.expected, decoded) - } - } - - func test_assumesTopLevelDictionary() { - let decoder = JSONDecoder() - decoder.assumesTopLevelDictionary = true - - let json = "\"x\" : 42" - do { - let result = try decoder.decode([String:Int].self, from: json.data(using: String._Encoding.utf8)!) - XCTAssertEqual(result, ["x" : 42]) - } catch { - XCTFail("Error thrown while decoding assumed top-level dictionary: \(error)") - } - - let jsonWithBraces = "{\"x\" : 42}" - do { - let result = try decoder.decode([String:Int].self, from: jsonWithBraces.data(using: String._Encoding.utf8)!) - XCTAssertEqual(result, ["x" : 42]) - } catch { - XCTFail("Error thrown while decoding assumed top-level dictionary: \(error)") - } - - do { - let result = try decoder.decode([String:Int].self, from: Data()) - XCTAssertEqual(result, [:]) - } catch { - XCTFail("Error thrown while decoding empty assumed top-level dictionary: \(error)") - } - - let jsonWithEndBraceOnly = "\"x\" : 42}" - XCTAssertThrowsError(try decoder.decode([String:Int].self, from: jsonWithEndBraceOnly.data(using: String._Encoding.utf8)!)) - - let jsonWithStartBraceOnly = "{\"x\" : 42" - XCTAssertThrowsError(try decoder.decode([String:Int].self, from: jsonWithStartBraceOnly.data(using: String._Encoding.utf8)!)) - - } - - func test_BOMPrefixes() { - let json = "\"ðŸ‘ðŸ»\"" - let decoder = JSONDecoder() - - // UTF-8 BOM - let utf8_BOM = Data([0xEF, 0xBB, 0xBF]) - XCTAssertEqual("ðŸ‘ðŸ»", try decoder.decode(String.self, from: utf8_BOM + json.data(using: String._Encoding.utf8)!)) - - // UTF-16 BE - let utf16_BE_BOM = Data([0xFE, 0xFF]) - XCTAssertEqual("ðŸ‘ðŸ»", try decoder.decode(String.self, from: utf16_BE_BOM + json.data(using: String._Encoding.utf16BigEndian)!)) - - // UTF-16 LE - let utf16_LE_BOM = Data([0xFF, 0xFE]) - XCTAssertEqual("ðŸ‘ðŸ»", try decoder.decode(String.self, from: utf16_LE_BOM + json.data(using: String._Encoding.utf16LittleEndian)!)) - - // UTF-32 BE - let utf32_BE_BOM = Data([0x0, 0x0, 0xFE, 0xFF]) - XCTAssertEqual("ðŸ‘ðŸ»", try decoder.decode(String.self, from: utf32_BE_BOM + json.data(using: String._Encoding.utf32BigEndian)!)) - - // UTF-32 LE - let utf32_LE_BOM = Data([0xFE, 0xFF, 0, 0]) - XCTAssertEqual("ðŸ‘ðŸ»", try decoder.decode(String.self, from: utf32_LE_BOM + json.data(using: String._Encoding.utf32LittleEndian)!)) - - // Try some mismatched BOMs - XCTAssertThrowsError(try decoder.decode(String.self, from: utf32_LE_BOM + json.data(using: String._Encoding.utf32BigEndian)!)) - - XCTAssertThrowsError(try decoder.decode(String.self, from: utf16_BE_BOM + json.data(using: String._Encoding.utf32LittleEndian)!)) - - XCTAssertThrowsError(try decoder.decode(String.self, from: utf8_BOM + json.data(using: String._Encoding.utf16BigEndian)!)) - } - - func test_invalidKeyUTF8() { - // {"key[255]":"value"} - // The invalid UTF-8 byte sequence in the key should trigger a thrown error, not a crash. - let data = Data([123, 34, 107, 101, 121, 255, 34, 58, 34, 118, 97, 108, 117, 101, 34, 125]) - struct Example: Decodable { - let key: String - } - XCTAssertThrowsError(try JSONDecoder().decode(Example.self, from: data)) - } - - func test_valueNotFoundError() { - struct ValueNotFound : Decodable { - let a: Bool - let nope: String? - - enum CodingKeys: String, CodingKey { - case a, nope - } - - init(from decoder: Decoder) throws { - let keyed = try decoder.container(keyedBy: CodingKeys.self) - self.a = try keyed.decode(Bool.self, forKey: .a) - - do { - let sup = try keyed.superDecoder(forKey: .nope) - self.nope = try sup.singleValueContainer().decode(String.self) - } catch DecodingError.valueNotFound { - // This is fine. - self.nope = nil - } - } - } - let json = "{\"a\":true}".data(using: String._Encoding.utf8)! - - // The expected valueNotFound error is swalled by the init(from:) implementation. - XCTAssertNoThrow(try JSONDecoder().decode(ValueNotFound.self, from: json)) - } - - func test_infiniteDate() { - let date = Date(timeIntervalSince1970: .infinity) - - let encoder = JSONEncoder() - - encoder.dateEncodingStrategy = .deferredToDate - XCTAssertThrowsError(try encoder.encode([date])) - - encoder.dateEncodingStrategy = .secondsSince1970 - XCTAssertThrowsError(try encoder.encode([date])) - - encoder.dateEncodingStrategy = .millisecondsSince1970 - XCTAssertThrowsError(try encoder.encode([date])) - } - - func test_typeEncodesNothing() { - struct EncodesNothing : Encodable { - func encode(to encoder: Encoder) throws { - // Intentionally nothing. - } - } - let enc = JSONEncoder() - - XCTAssertThrowsError(try enc.encode(EncodesNothing())) - - // Unknown if the following behavior is strictly correct, but it's what the prior implementation does, so this test exists to make sure we maintain compatibility. - - let arrayData = try! enc.encode([EncodesNothing()]) - XCTAssertEqual("[{}]", String(data: arrayData, encoding: .utf8)) - - let objectData = try! enc.encode(["test" : EncodesNothing()]) - XCTAssertEqual("{\"test\":{}}", String(data: objectData, encoding: .utf8)) - } - - func test_superEncoders() { - struct SuperEncoding : Encodable { - enum CodingKeys: String, CodingKey { - case firstSuper - case secondSuper - case unkeyed - case direct - } - func encode(to encoder: Encoder) throws { - var keyed = encoder.container(keyedBy: CodingKeys.self) - - let keyedSuper1 = keyed.superEncoder(forKey: .firstSuper) - let keyedSuper2 = keyed.superEncoder(forKey: .secondSuper) - var keyedSVC1 = keyedSuper1.singleValueContainer() - var keyedSVC2 = keyedSuper2.singleValueContainer() - try keyedSVC1.encode("First") - try keyedSVC2.encode("Second") - - var unkeyed = keyed.nestedUnkeyedContainer(forKey: .unkeyed) - try unkeyed.encode(0) - let unkeyedSuper1 = unkeyed.superEncoder() - let unkeyedSuper2 = unkeyed.superEncoder() - try unkeyed.encode(42) - var unkeyedSVC1 = unkeyedSuper1.singleValueContainer() - var unkeyedSVC2 = unkeyedSuper2.singleValueContainer() - try unkeyedSVC1.encode("First") - try unkeyedSVC2.encode("Second") - - let directSuper = keyed.superEncoder(forKey: .direct) - try ["direct":"super"].encode(to: directSuper) - - // NOTE!!! At present, the order in which the values in the unkeyed container's superEncoders above get inserted into the resulting array depends on the order in which the superEncoders are deinit'd!! This can result in some very unexpected results, and this pattern is not recommended. This test exists just to verify compatibility. - } - } - let data = try! JSONEncoder().encode(SuperEncoding()) - let string = String(data: data, encoding: .utf8)! - - XCTAssertTrue(string.contains("\"firstSuper\":\"First\"")) - XCTAssertTrue(string.contains("\"secondSuper\":\"Second\"")) - XCTAssertTrue(string.contains("[0,\"First\",\"Second\",42]")) - XCTAssertTrue(string.contains("{\"direct\":\"super\"}")) - } - - func testRedundantKeys() { - // Last encoded key wins. - - struct RedundantEncoding : Encodable { - enum ReplacedType { - case value - case keyedContainer - case unkeyedContainer - } - let replacedType: ReplacedType - let useSuperEncoder: Bool - - enum CodingKeys: String, CodingKey { - case key - } - func encode(to encoder: Encoder) throws { - var keyed = encoder.container(keyedBy: CodingKeys.self) - switch replacedType { - case .value: - try keyed.encode(0, forKey: .key) - case .keyedContainer: - let _ = keyed.nestedContainer(keyedBy: CodingKeys.self, forKey: .key) - case .unkeyedContainer: - let _ = keyed.nestedUnkeyedContainer(forKey: .key) - } - if useSuperEncoder { - var svc = keyed.superEncoder(forKey: .key).singleValueContainer() - try svc.encode(42) - } else { - try keyed.encode(42, forKey: .key) - } - } - } - var data = try! JSONEncoder().encode(RedundantEncoding(replacedType: .value, useSuperEncoder: false)) - XCTAssertEqual(String(data: data, encoding: .utf8), ("{\"key\":42}")) - - data = try! JSONEncoder().encode(RedundantEncoding(replacedType: .value, useSuperEncoder: true)) - XCTAssertEqual(String(data: data, encoding: .utf8), ("{\"key\":42}")) - - data = try! JSONEncoder().encode(RedundantEncoding(replacedType: .keyedContainer, useSuperEncoder: false)) - XCTAssertEqual(String(data: data, encoding: .utf8), ("{\"key\":42}")) - - data = try! JSONEncoder().encode(RedundantEncoding(replacedType: .keyedContainer, useSuperEncoder: true)) - XCTAssertEqual(String(data: data, encoding: .utf8), ("{\"key\":42}")) - - data = try! JSONEncoder().encode(RedundantEncoding(replacedType: .unkeyedContainer, useSuperEncoder: false)) - XCTAssertEqual(String(data: data, encoding: .utf8), ("{\"key\":42}")) - - data = try! JSONEncoder().encode(RedundantEncoding(replacedType: .unkeyedContainer, useSuperEncoder: true)) - XCTAssertEqual(String(data: data, encoding: .utf8), ("{\"key\":42}")) - } - - func test_SR17581_codingEmptyDictionaryWithNonstringKeyDoesRoundtrip() throws { - struct Something: Codable { - struct Key: Codable, Hashable { - var x: String - } - - var dict: [Key: String] - - enum CodingKeys: String, CodingKey { - case dict - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - self.dict = try container.decode([Key: String].self, forKey: .dict) - } - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(dict, forKey: .dict) - } - - init(dict: [Key: String]) { - self.dict = dict - } - } - - let toEncode = Something(dict: [:]) - let data = try JSONEncoder().encode(toEncode) - let result = try JSONDecoder().decode(Something.self, from: data) - XCTAssertEqual(result.dict.count, 0) - } - - // None of these tests can be run in our automatic test suites right now, because they are expected to hit a preconditionFailure. They can only be verified manually. - func disabled_testPreconditionFailuresForContainerReplacement() { - struct RedundantEncoding : Encodable { - enum Subcase { - case replaceValueWithKeyedContainer - case replaceValueWithUnkeyedContainer - case replaceKeyedContainerWithUnkeyed - case replaceUnkeyedContainerWithKeyed - } - let subcase : Subcase - - enum CodingKeys: String, CodingKey { - case key - } - func encode(to encoder: Encoder) throws { - switch subcase { - case .replaceValueWithKeyedContainer: - var keyed = encoder.container(keyedBy: CodingKeys.self) - try keyed.encode(42, forKey: .key) - let _ = keyed.nestedContainer(keyedBy: CodingKeys.self, forKey: .key) - case .replaceValueWithUnkeyedContainer: - var keyed = encoder.container(keyedBy: CodingKeys.self) - try keyed.encode(42, forKey: .key) - let _ = keyed.nestedUnkeyedContainer(forKey: .key) - case .replaceKeyedContainerWithUnkeyed: - var keyed = encoder.container(keyedBy: CodingKeys.self) - let _ = keyed.nestedContainer(keyedBy: CodingKeys.self, forKey: .key) - let _ = keyed.nestedUnkeyedContainer(forKey: .key) - case .replaceUnkeyedContainerWithKeyed: - var keyed = encoder.container(keyedBy: CodingKeys.self) - let _ = keyed.nestedUnkeyedContainer(forKey: .key) - let _ = keyed.nestedContainer(keyedBy: CodingKeys.self, forKey: .key) - } - } - } - let _ = try! JSONEncoder().encode(RedundantEncoding(subcase: .replaceValueWithKeyedContainer)) -// let _ = try! JSONEncoder().encode(RedundantEncoding(subcase: .replaceValueWithUnkeyedContainer)) -// let _ = try! JSONEncoder().encode(RedundantEncoding(subcase: .replaceKeyedContainerWithUnkeyed)) -// let _ = try! JSONEncoder().encode(RedundantEncoding(subcase: .replaceUnkeyedContainerWithKeyed)) - } - - func test_decodeIfPresent() throws { - let emptyDictJSON = try JSONEncoder().encode(DecodeIfPresentAllTypes.allNils) - let testEmptyDict = try JSONDecoder().decode(DecodeIfPresentAllTypes.self, from: emptyDictJSON) - XCTAssertEqual(testEmptyDict, .allNils) - - let allNullDictJSON = try JSONEncoder().encode(DecodeIfPresentAllTypes.allNils) - let testAllNullDict = try JSONDecoder().decode(DecodeIfPresentAllTypes.self, from: allNullDictJSON) - XCTAssertEqual(testAllNullDict, .allNils) - - let allOnesDictJSON = try JSONEncoder().encode(DecodeIfPresentAllTypes.allOnes) - let testAllOnesDict = try JSONDecoder().decode(DecodeIfPresentAllTypes.self, from: allOnesDictJSON) - XCTAssertEqual(testAllOnesDict, .allOnes) - - let emptyArrayJSON = try JSONEncoder().encode(DecodeIfPresentAllTypes.allNils) - let testEmptyArray = try JSONDecoder().decode(DecodeIfPresentAllTypes.self, from: emptyArrayJSON) - XCTAssertEqual(testEmptyArray, .allNils) - - let allNullArrayJSON = try JSONEncoder().encode(DecodeIfPresentAllTypes.allNils) - let testAllNullArray = try JSONDecoder().decode(DecodeIfPresentAllTypes.self, from: allNullArrayJSON) - XCTAssertEqual(testAllNullArray, .allNils) - - let allOnesArrayJSON = try JSONEncoder().encode(DecodeIfPresentAllTypes.allOnes) - let testAllOnesArray = try JSONDecoder().decode(DecodeIfPresentAllTypes.self, from: allOnesArrayJSON) - XCTAssertEqual(testAllOnesArray, .allOnes) - } -} - -// MARK: - SnakeCase Tests -extension JSONEncoderTests { - var json5Decoder: JSONDecoder { - let decoder = JSONDecoder() - decoder.allowsJSON5 = true - return decoder - } - - func test_json5Numbers() { - let decoder = json5Decoder - - let successfulIntegers: [(String,Int)] = [ - ("1", 1), - ("11", 11), - ("99887766", 99887766), - ("-1", -1), - ("-10", -10), - ("0", 0), - ("+0", +0), - ("-0", -0), - ("+1", +1), - ("+10", +10), - ("0x1F", 0x1F), - ("0x0000000E", 0xE), - ("-0X1f", -0x1f), - ("+0X1f", +0x1f), - ("1.", 1), - ("1.e2", 100), - ("1e2", 100), - ("1E2", 100), - ("1e+2", 100), - ("1E+2", 100), - ("1e+02", 100), - ("1E+02", 100), - ] - for (json, expected) in successfulIntegers { - do { - let val = try decoder.decode(Int.self, from: json.data(using: String._Encoding.utf8)!) - XCTAssertEqual(val, expected, "Wrong value parsed from input \"\(json)\"") - } catch { - XCTFail("Error when parsing input \"\(json)\": \(error)") - } - } - - let successfulDoubles: [(String,Double)] = [ - ("1", 1), - ("11", 11), - ("99887766", 99887766), - ("-1", -1), - ("-10", -10), - ("0", 0), - ("+0", +0), - ("-0", -0), - ("+1", +1), - ("+10", +10), - ("Infinity", Double.infinity), - ("-Infinity", -Double.infinity), - ("+Infinity", Double.infinity), - ("-NaN", -Double.nan), - ("+NaN", Double.nan), - ("NaN", Double.nan), - (".1", 0.1), - ("1.", 1.0), - ("-.1", -0.1), - ("+.1", +0.1), - ("1e-2", 1e-2), - ("1E-2", 1E-2), - ("1e-02", 1e-02), - ("1E-02", 1E-02), - ("1e2", 1e2), - ("1E2", 1E2), - ("1e+2", 1e+2), - ("1E+2", 1E+2), - ("1e+02", 1e+02), - ("1E+02", 1E+02), - ("0x1F", Double(0x1F)), - ("-0X1f", Double(-0x1f)), - ("+0X1f", Double(+0x1f)), - ] - for (json, expected) in successfulDoubles { - do { - let val = try decoder.decode(Double.self, from: json.data(using: String._Encoding.utf8)!) - if expected.isNaN { - XCTAssertTrue(val.isNaN, "Wrong value \(val) parsed from input \"\(json)\"") - } else { - XCTAssertEqual(val, expected, "Wrong value parsed from input \"\(json)\"") - } - } catch { - XCTFail("Error when parsing input \"\(json)\": \(error)") - } - } - - let unsuccessfulIntegers = [ - "-", // single - - "+", // single + - "-a", // - followed by non-digit - "+a", // + followed by non-digit - "-0x", - "+0x", - "-0x ", - "+0x ", - "-0xAFFFFFAFFFFFAFFFFFAFFFFFAFFFFFAFFFFFAFFFFFAFFFFF", - "0xABC.DEF", - "0xABCpD", - "1e", - "1E", - "1e ", - "1E ", - "+1e ", - "+1e", - "-1e ", - "-1E ", - ] - for json in unsuccessfulIntegers { - do { - let _ = try decoder.decode(Int.self, from: json.data(using: String._Encoding.utf8)!) - XCTFail("Expected failure for input \"\(json)\"") - } catch { } - } - - let unsuccessfulDoubles = [ - "-Inf", - "-Inf ", - "+Inf", - "+Inf ", - "+Na", - "+Na ", - "-Na", - "-Na ", - "-infinity", - "-infinity ", - "+infinity", - "+infinity ", - "+NAN", - "+NA ", - "-NA", - "-NA ", - "-NAN", - "-NAN ", - "0x2.", - "0x2.2", - ".e1", - "0xFFFFFFFFFFFFFFFFFFFFFF", - ]; - for json in unsuccessfulDoubles { - do { - let _ = try decoder.decode(Double.self, from: json.data(using: String._Encoding.utf8)!) - XCTFail("Expected failure for input \"\(json)\"") - } catch { } - } - } - - func test_json5Null() { - let validJSON = "null" - let invalidJSON = [ - "Null", - "nul", - "nu", - "n", - "n ", - "nu " - ] - - XCTAssertNoThrow(try json5Decoder.decode(NullReader.self, from: validJSON.data(using: String._Encoding.utf8)!)) - - for json in invalidJSON { - XCTAssertThrowsError(try json5Decoder.decode(NullReader.self, from: json.data(using: String._Encoding.utf8)!), "Expected failure while decoding input \"\(json)\"") - } - } - - func test_json5EsotericErrors() { - // All of the following should fail - let arrayStrings = [ - "[", - "[ ", - "[\n\n", - "['hi',", - "['hi', ", - "['hi',\n" - ] - let objectStrings = [ - "{", - "{ ", - "{k ", - "{k :", - "{k : ", - "{k : true", - "{k : true ", - "{k : true\n\n", - "{k : true ", - "{k : true ", - ] - let objectCharacterArrays: [[UInt8]] = [ - [.init(ascii: "{"), 0x80], // Invalid UTF-8: Unexpected continuation byte - [.init(ascii: "{"), 0xc0], // Invalid UTF-8: Initial byte of 2-byte sequence without continuation - [.init(ascii: "{"), 0xe0, 0x80], // Invalid UTF-8: Initial byte of 3-byte sequence with only one continuation - [.init(ascii: "{"), 0xf0, 0x80, 0x80], // Invalid UTF-8: Initial byte of 3-byte sequence with only one continuation - ] - for json in arrayStrings { - XCTAssertThrowsError(try json5Decoder.decode([String].self, from: json.data(using: String._Encoding.utf8)!), "Expected error for input \"\(json)\"") - } - for json in objectStrings { - XCTAssertThrowsError(try json5Decoder.decode([String:Bool].self, from: json.data(using: String._Encoding.utf8)!), "Expected error for input \(json)") - } - for json in objectCharacterArrays { - XCTAssertThrowsError(try json5Decoder.decode([String:Bool].self, from: Data(json)), "Expected error for input \(json)") - } - } - - func test_json5Strings() { - let stringsToTrues = [ - "{v\n : true}", - "{v \n : true}", - "{ v \n : true,\nv\n:true,}", - "{v\r : true}", - "{v \r : true}", - "{ v \r : true,\rv\r:true,}", - "{v\r\n : true}", - "{v \r\n : true}", - "{ v \r\n : true,\r\nv\r\n:true,}", - "{v// comment \n : true}", - "{v // comment \n : true}", - "{v/* comment*/ \n : true}", - "{v/* comment */\n: true}", - "{v/* comment */:/*comment*/\ntrue}", - "{v// comment \r : true}", - "{v // comment \r : true}", - "{v/* comment*/ \r : true}", - "{v/* comment */\r: true}", - "{v/* comment */:/*comment*/\rtrue}", - "{v// comment \r\n : true}", - "{v // comment \r\n : true}", - "{v/* comment*/ \r\n : true}", - "{v/* comment */\r\n: true}", - "{v/* comment */:/*comment*/\r\ntrue}", - "// start with a comment\r\n{v:true}", - ] - - let stringsToStrings = [ - "{v : \"hi\\x20there\"}" : "hi there", - "{v : \"hi\\xthere\"}" : nil, - "{v : \"hi\\x2there\"}" : nil, - "{v : \"hi\\0there\"}" : nil, - "{v : \"hi\\x00there\"}" : nil, - "{v : \"hi\\u0000there\"}" : nil, // disallowed in JSON5 mode only - "{v:\"hello\\uA\"}" : nil, - "{v:\"hello\\uA \"}" : nil - ] - - for json in stringsToTrues { - XCTAssertNoThrow(try json5Decoder.decode([String:Bool].self, from: json.data(using: String._Encoding.utf8)!), "Failed to parse \"\(json)\"") - } - for (json, expected) in stringsToStrings { - do { - let decoded = try json5Decoder.decode([String:String].self, from: json.data(using: String._Encoding.utf8)!) - XCTAssertEqual(expected, decoded["v"]) - } catch { - if let expected { - XCTFail("Expected \(expected) for input \"\(json)\", but failed with \(error)") - } - } - } - } - - func test_json5AssumedDictionary() { - let decoder = json5Decoder - decoder.assumesTopLevelDictionary = true - - let stringsToString = [ - "hello: \"world\"" : [ "hello" : "world" ], - "{hello: \"world\"}" : [ "hello" : "world" ], // Still has markers - "hello: \"world\", goodbye: \"42\"" : [ "hello" : "world", "goodbye" : "42" ], // more than one value - "hello: \"world\"," : [ "hello" : "world" ], // Trailing comma - "hello: \"world\" " : [ "hello" : "world" ], // Trailing whitespace - "hello: \"world\", " : [ "hello" : "world" ], // Trailing whitespace and comma - "hello: \"world\" , " : [ "hello" : "world" ], // Trailing whitespace and comma - " hello : \"world\" " : [ "hello" : "world" ], // Before and after whitespace - "{hello: \"world\"" : nil, // Partial dictionary 1 - "hello: \"world\"}" : nil, // Partial dictionary 2 - "hello: \"world\" x " : nil, // Junk at end - "hello: \"world\" x" : nil, // Junk at end - "hello: \"world\"x" : nil, // Junk at end - "" : [:], // empty but valid - " " : [:], // empty but valid - "{ }" : [:], // empty but valid - "{}" : [:], // empty but valid - "," : nil, // Invalid - " , " : nil, // Invalid - ", " : nil, // Invalid - " ," : nil, // Invalid - ] - for (json, expected) in stringsToString { - do { - let decoded = try decoder.decode([String:String].self, from: json.data(using: String._Encoding.utf8)!) - XCTAssertEqual(expected, decoded) - } catch { - if let expected { - XCTFail("Expected \(expected) for input \"\(json)\", but failed with \(error)") - } - } - } - - struct HelloGoodbye : Decodable, Equatable { - let hello: String - let goodbye: [String:String] - } - let helloGoodbyeExpectedValue = HelloGoodbye( - hello: "world", - goodbye: ["hi" : "there"]) - let stringsToNestedDictionary = [ - "hello: \"world\", goodbye: {\"hi\":\"there\"}", // more than one value, nested dictionary - "hello: \"world\", goodbye: {\"hi\":\"there\"},", // more than one value, nested dictionary, trailing comma 1 - "hello: \"world\", goodbye: {\"hi\":\"there\",},", // more than one value, nested dictionary, trailing comma 2 - ] - for json in stringsToNestedDictionary { - do { - let decoded = try decoder.decode(HelloGoodbye.self, from: json.data(using: String._Encoding.utf8)!) - XCTAssertEqual(helloGoodbyeExpectedValue, decoded) - } catch { - XCTFail("Expected \(helloGoodbyeExpectedValue) for input \"\(json)\", but failed with \(error)") - } - } - - let arrayJSON = "[1,2,3]".data(using: String._Encoding.utf8)! // Assumed dictionary can't be an array - XCTAssertThrowsError(try decoder.decode([Int].self, from: arrayJSON)) - - let strFragmentJSON = "fragment".data(using: String._Encoding.utf8)! // Assumed dictionary can't be a fragment - XCTAssertThrowsError(try decoder.decode(String.self, from: strFragmentJSON)) - - let numFragmentJSON = "42".data(using: String._Encoding.utf8)! // Assumed dictionary can't be a fragment - XCTAssertThrowsError(try decoder.decode(Int.self, from: numFragmentJSON)) - } - - enum JSON5SpecTestType { - case json5 - case json5_foundationPermissiveJSON - case json - case js - case malformed - - var fileExtension : String { - switch self { - case .json5: return "json5" - case .json5_foundationPermissiveJSON: return "json5" - case .json: return "json" - case .js: return "js" - case .malformed: return "txt" - } - } - } -} - -// MARK: - SnakeCase Tests -extension JSONEncoderTests { - func testDecodingKeyStrategyCamel() { - let fromSnakeCaseTests = [ - ("", ""), // don't die on empty string - ("a", "a"), // single character - ("ALLCAPS", "ALLCAPS"), // If no underscores, we leave the word as-is - ("ALL_CAPS", "allCaps"), // Conversion from screaming snake case - ("single", "single"), // do not capitalize anything with no underscore - ("snake_case", "snakeCase"), // capitalize a character - ("one_two_three", "oneTwoThree"), // more than one word - ("one_2_three", "one2Three"), // numerics - ("one2_three", "one2Three"), // numerics, part 2 - ("snake_Ćase", "snakeĆase"), // do not further modify a capitalized diacritic - ("snake_ćase", "snakeĆase"), // capitalize a diacritic - ("alreadyCamelCase", "alreadyCamelCase"), // do not modify already camel case - ("__this_and_that", "__thisAndThat"), - ("_this_and_that", "_thisAndThat"), - ("this__and__that", "thisAndThat"), - ("this_and_that__", "thisAndThat__"), - ("this_aNd_that", "thisAndThat"), - ("_one_two_three", "_oneTwoThree"), - ("one_two_three_", "oneTwoThree_"), - ("__one_two_three", "__oneTwoThree"), - ("one_two_three__", "oneTwoThree__"), - ("_one_two_three_", "_oneTwoThree_"), - ("__one_two_three", "__oneTwoThree"), - ("__one_two_three__", "__oneTwoThree__"), - ("_test", "_test"), - ("_test_", "_test_"), - ("__test", "__test"), - ("test__", "test__"), - ("_", "_"), - ("__", "__"), - ("___", "___"), - ("m͉̟̹y̦̳GÍ͚͎̳r̤͉̤͕ͅea̲͕t͇̥̼͖U͇ÌÌ R͙̻̥͓̣L̥̖͎͓̪̫ͅR̩͖̩eq͈͓uÌže̱sÌ™t̤̺ͅ", "m͉̟̹y̦̳GÍ͚͎̳r̤͉̤͕ͅea̲͕t͇̥̼͖U͇ÌÌ R͙̻̥͓̣L̥̖͎͓̪̫ͅR̩͖̩eq͈͓uÌže̱sÌ™t̤̺ͅ"), // because Itai wanted to test this - ("ðŸ§_ðŸŸ", "ðŸ§ðŸŸ") // fishy emoji example? - ] - - for test in fromSnakeCaseTests { - // This JSON contains the camel case key that the test object should decode with, then it uses the snake case key (test.0) as the actual key for the boolean value. - let input = "{\"camelCaseKey\":\"\(test.1)\",\"\(test.0)\":true}".data(using: String._Encoding.utf8)! - - let decoder = JSONDecoder() - decoder.keyDecodingStrategy = .convertFromSnakeCase - - let result = try! decoder.decode(DecodeMe.self, from: input) - - XCTAssertTrue(result.found) - } - } - - func testEncodingDictionaryStringKeyConversionUntouched() { - let expected = "{\"leaveMeAlone\":\"test\"}" - let toEncode: [String: String] = ["leaveMeAlone": "test"] - - let encoder = JSONEncoder() - encoder.keyEncodingStrategy = .convertToSnakeCase - let resultData = try! encoder.encode(toEncode) - let resultString = String(bytes: resultData, encoding: String._Encoding.utf8) - - XCTAssertEqual(expected, resultString) - } - - func testKeyStrategySnakeGeneratedAndCustom() { - // Test that this works with a struct that has automatically generated keys - struct DecodeMe4 : Codable { - var thisIsCamelCase : String - var thisIsCamelCaseToo : String - private enum CodingKeys : String, CodingKey { - case thisIsCamelCase = "fooBar" - case thisIsCamelCaseToo - } - } - - // Decoding - let input = "{\"foo_bar\":\"test\",\"this_is_camel_case_too\":\"test2\"}".data(using: String._Encoding.utf8)! - let decoder = JSONDecoder() - decoder.keyDecodingStrategy = .convertFromSnakeCase - let decodingResult = try! decoder.decode(DecodeMe4.self, from: input) - - XCTAssertEqual("test", decodingResult.thisIsCamelCase) - XCTAssertEqual("test2", decodingResult.thisIsCamelCaseToo) - - // Encoding - let encoded = DecodeMe4(thisIsCamelCase: "test", thisIsCamelCaseToo: "test2") - let encoder = JSONEncoder() - encoder.keyEncodingStrategy = .convertToSnakeCase - let encodingResultData = try! encoder.encode(encoded) - let encodingResultString = String(bytes: encodingResultData, encoding: String._Encoding.utf8) - XCTAssertTrue(encodingResultString!.contains("foo_bar")) - XCTAssertTrue(encodingResultString!.contains("this_is_camel_case_too")) - } - - func testDecodingDictionaryFailureKeyPathNested() { - let input = "{\"top_level\": {\"sub_level\": {\"nested_value\": {\"int_value\": \"not_an_int\"}}}}".data(using: String._Encoding.utf8)! - let decoder = JSONDecoder() - decoder.keyDecodingStrategy = .convertFromSnakeCase - do { - _ = try decoder.decode([String: [String : DecodeFailureNested]].self, from: input) - } catch DecodingError.typeMismatch(_, let context) { - XCTAssertEqual(4, context.codingPath.count) - XCTAssertEqual("top_level", context.codingPath[0].stringValue) - XCTAssertEqual("sub_level", context.codingPath[1].stringValue) - XCTAssertEqual("nestedValue", context.codingPath[2].stringValue) - XCTAssertEqual("intValue", context.codingPath[3].stringValue) - } catch { - XCTFail("Unexpected error: \(String(describing: error))") - } - } - - func testDecodingKeyStrategyCamelGenerated() { - let encoded = DecodeMe3(thisIsCamelCase: "test") - let encoder = JSONEncoder() - encoder.keyEncodingStrategy = .convertToSnakeCase - let resultData = try! encoder.encode(encoded) - let resultString = String(bytes: resultData, encoding: String._Encoding.utf8) - XCTAssertEqual("{\"this_is_camel_case\":\"test\"}", resultString) - } - - func testDecodingStringExpectedType() { - let input = #"{"thisIsCamelCase": null}"#.data(using: String._Encoding.utf8)! - do { - _ = try JSONDecoder().decode(DecodeMe3.self, from: input) - } catch DecodingError.valueNotFound(let expected, _) { - XCTAssertTrue(expected == String.self) - } catch { - XCTFail("Unexpected error: \(String(describing: error))") - } - } - - func testEncodingKeyStrategySnakeGenerated() { - // Test that this works with a struct that has automatically generated keys - let input = "{\"this_is_camel_case\":\"test\"}".data(using: String._Encoding.utf8)! - let decoder = JSONDecoder() - decoder.keyDecodingStrategy = .convertFromSnakeCase - let result = try! decoder.decode(DecodeMe3.self, from: input) - - XCTAssertEqual("test", result.thisIsCamelCase) - } - - func testEncodingDictionaryFailureKeyPath() { - let toEncode: [String: EncodeFailure] = ["key": EncodeFailure(someValue: Double.nan)] - - let encoder = JSONEncoder() - encoder.keyEncodingStrategy = .convertToSnakeCase - do { - _ = try encoder.encode(toEncode) - } catch EncodingError.invalidValue(_, let context) { - XCTAssertEqual(2, context.codingPath.count) - XCTAssertEqual("key", context.codingPath[0].stringValue) - XCTAssertEqual("someValue", context.codingPath[1].stringValue) - } catch { - XCTFail("Unexpected error: \(String(describing: error))") - } - } - - func testEncodingDictionaryFailureKeyPathNested() { - let toEncode: [String: [String: EncodeFailureNested]] = ["key": ["sub_key": EncodeFailureNested(nestedValue: EncodeFailure(someValue: Double.nan))]] - - let encoder = JSONEncoder() - encoder.keyEncodingStrategy = .convertToSnakeCase - do { - _ = try encoder.encode(toEncode) - } catch EncodingError.invalidValue(_, let context) { - XCTAssertEqual(4, context.codingPath.count) - XCTAssertEqual("key", context.codingPath[0].stringValue) - XCTAssertEqual("sub_key", context.codingPath[1].stringValue) - XCTAssertEqual("nestedValue", context.codingPath[2].stringValue) - XCTAssertEqual("someValue", context.codingPath[3].stringValue) - } catch { - XCTFail("Unexpected error: \(String(describing: error))") - } - } - - func testEncodingKeyStrategySnake() { - let toSnakeCaseTests = [ - ("simpleOneTwo", "simple_one_two"), - ("myURL", "my_url"), - ("singleCharacterAtEndX", "single_character_at_end_x"), - ("thisIsAnXMLProperty", "this_is_an_xml_property"), - ("single", "single"), // no underscore - ("", ""), // don't die on empty string - ("a", "a"), // single character - ("aA", "a_a"), // two characters - ("version4Thing", "version4_thing"), // numerics - ("partCAPS", "part_caps"), // only insert underscore before first all caps - ("partCAPSLowerAGAIN", "part_caps_lower_again"), // switch back and forth caps. - ("manyWordsInThisThing", "many_words_in_this_thing"), // simple lowercase + underscore + more - ("asdfĆqer", "asdf_ćqer"), - ("already_snake_case", "already_snake_case"), - ("dataPoint22", "data_point22"), - ("dataPoint22Word", "data_point22_word"), - ("_oneTwoThree", "_one_two_three"), - ("oneTwoThree_", "one_two_three_"), - ("__oneTwoThree", "__one_two_three"), - ("oneTwoThree__", "one_two_three__"), - ("_oneTwoThree_", "_one_two_three_"), - ("__oneTwoThree", "__one_two_three"), - ("__oneTwoThree__", "__one_two_three__"), - ("_test", "_test"), - ("_test_", "_test_"), - ("__test", "__test"), - ("test__", "test__"), - ("m͉̟̹y̦̳GÍ͚͎̳r̤͉̤͕ͅea̲͕t͇̥̼͖U͇ÌÌ R͙̻̥͓̣L̥̖͎͓̪̫ͅR̩͖̩eq͈͓uÌže̱sÌ™t̤̺ͅ", "m͉̟̹y̦̳_gÍ͚͎̳r̤͉̤͕ͅea̲͕t͇̥̼͖_u͇ÌÌ r͙̻̥͓̣l̥̖͎͓̪̫ͅ_r̩͖̩eq͈͓uÌže̱sÌ™t̤̺ͅ"), // because Itai wanted to test this - ("ðŸ§ðŸŸ", "ðŸ§ðŸŸ") // fishy emoji example? - ] - - for test in toSnakeCaseTests { - let expected = "{\"\(test.1)\":\"test\"}" - let encoded = EncodeMe(keyName: test.0) - - let encoder = JSONEncoder() - encoder.keyEncodingStrategy = .convertToSnakeCase - let resultData = try! encoder.encode(encoded) - let resultString = String(bytes: resultData, encoding: String._Encoding.utf8) - - XCTAssertEqual(expected, resultString) - } - } - - func test_twoByteUTF16Inputs() { - let json = "7" - let decoder = JSONDecoder() - - XCTAssertEqual(7, try decoder.decode(Int.self, from: json.data(using: .utf16BigEndian)!)) - XCTAssertEqual(7, try decoder.decode(Int.self, from: json.data(using: .utf16LittleEndian)!)) - } - - private func _run_passTest(name: String, json5: Bool = false, type: T.Type) { - let jsonData = testData(forResource: name, withExtension: json5 ? "json5" : "json" , subdirectory: json5 ? "JSON5/pass" : "JSON/pass")! - - let plistData = testData(forResource: name, withExtension: "plist", subdirectory: "JSON/pass") - let decoder = json5Decoder - - let decoded: T - do { - decoded = try decoder.decode(T.self, from: jsonData) - } catch { - XCTFail("Pass test \"\(name)\" failed with error: \(error)") - return - } - - let prettyPrintEncoder = JSONEncoder() - prettyPrintEncoder.outputFormatting = .prettyPrinted - - for encoder in [JSONEncoder(), prettyPrintEncoder] { - let reencodedData = try! encoder.encode(decoded) - let redecodedObjects = try! decoder.decode(T.self, from: reencodedData) - XCTAssertEqual(decoded, redecodedObjects) - - if let plistData { - let decodedPlistObjects = try! PropertyListDecoder().decode(T.self, from: plistData) - XCTAssertEqual(decoded, decodedPlistObjects) - } - } - } - - func test_JSONPassTests() { - _run_passTest(name: "pass1-utf8", type: JSONPass.Test1.self) - _run_passTest(name: "pass1-utf16be", type: JSONPass.Test1.self) - _run_passTest(name: "pass1-utf16le", type: JSONPass.Test1.self) - _run_passTest(name: "pass1-utf32be", type: JSONPass.Test1.self) - _run_passTest(name: "pass1-utf32le", type: JSONPass.Test1.self) - _run_passTest(name: "pass2", type: JSONPass.Test2.self) - _run_passTest(name: "pass3", type: JSONPass.Test3.self) - _run_passTest(name: "pass4", type: JSONPass.Test4.self) - _run_passTest(name: "pass5", type: JSONPass.Test5.self) - _run_passTest(name: "pass6", type: JSONPass.Test6.self) - _run_passTest(name: "pass7", type: JSONPass.Test7.self) - _run_passTest(name: "pass8", type: JSONPass.Test8.self) - _run_passTest(name: "pass9", type: JSONPass.Test9.self) - _run_passTest(name: "pass10", type: JSONPass.Test10.self) - _run_passTest(name: "pass11", type: JSONPass.Test11.self) - _run_passTest(name: "pass12", type: JSONPass.Test12.self) - _run_passTest(name: "pass13", type: JSONPass.Test13.self) - _run_passTest(name: "pass14", type: JSONPass.Test14.self) - _run_passTest(name: "pass15", type: JSONPass.Test15.self) - } - - func test_json5PassJSONFiles() { - _run_passTest(name: "example", json5: true, type: JSON5Pass.Example.self) - _run_passTest(name: "hex", json5: true, type: JSON5Pass.Hex.self) - _run_passTest(name: "numbers", json5: true, type: JSON5Pass.Numbers.self) - _run_passTest(name: "strings", json5: true, type: JSON5Pass.Strings.self) - _run_passTest(name: "whitespace", json5: true, type: JSON5Pass.Whitespace.self) - } - - private func _run_failTest(name: String, type: T.Type) { - let jsonData = testData(forResource: name, withExtension: "json", subdirectory: "JSON/fail")! - - let decoder = JSONDecoder() - decoder.assumesTopLevelDictionary = true - do { - let _ = try decoder.decode(T.self, from: jsonData) - XCTFail("Decoding should have failed for invalid JSON data (test name: \(name))") - } catch { - print(error as NSError) - } - } - - func test_JSONFailTests() { - _run_failTest(name: "fail1", type: JSONFail.Test1.self) - _run_failTest(name: "fail2", type: JSONFail.Test2.self) - _run_failTest(name: "fail3", type: JSONFail.Test3.self) - _run_failTest(name: "fail4", type: JSONFail.Test4.self) - _run_failTest(name: "fail5", type: JSONFail.Test5.self) - _run_failTest(name: "fail6", type: JSONFail.Test6.self) - _run_failTest(name: "fail7", type: JSONFail.Test7.self) - _run_failTest(name: "fail8", type: JSONFail.Test8.self) - _run_failTest(name: "fail9", type: JSONFail.Test9.self) - _run_failTest(name: "fail10", type: JSONFail.Test10.self) - _run_failTest(name: "fail11", type: JSONFail.Test11.self) - _run_failTest(name: "fail12", type: JSONFail.Test12.self) - _run_failTest(name: "fail13", type: JSONFail.Test13.self) - _run_failTest(name: "fail14", type: JSONFail.Test14.self) - _run_failTest(name: "fail15", type: JSONFail.Test15.self) - _run_failTest(name: "fail16", type: JSONFail.Test16.self) - _run_failTest(name: "fail17", type: JSONFail.Test17.self) - _run_failTest(name: "fail18", type: JSONFail.Test18.self) - _run_failTest(name: "fail19", type: JSONFail.Test19.self) - _run_failTest(name: "fail21", type: JSONFail.Test21.self) - _run_failTest(name: "fail22", type: JSONFail.Test22.self) - _run_failTest(name: "fail23", type: JSONFail.Test23.self) - _run_failTest(name: "fail24", type: JSONFail.Test24.self) - _run_failTest(name: "fail25", type: JSONFail.Test25.self) - _run_failTest(name: "fail26", type: JSONFail.Test26.self) - _run_failTest(name: "fail27", type: JSONFail.Test27.self) - _run_failTest(name: "fail28", type: JSONFail.Test28.self) - _run_failTest(name: "fail29", type: JSONFail.Test29.self) - _run_failTest(name: "fail30", type: JSONFail.Test30.self) - _run_failTest(name: "fail31", type: JSONFail.Test31.self) - _run_failTest(name: "fail32", type: JSONFail.Test32.self) - _run_failTest(name: "fail33", type: JSONFail.Test33.self) - _run_failTest(name: "fail34", type: JSONFail.Test34.self) - _run_failTest(name: "fail35", type: JSONFail.Test35.self) - _run_failTest(name: "fail36", type: JSONFail.Test36.self) - _run_failTest(name: "fail37", type: JSONFail.Test37.self) - _run_failTest(name: "fail38", type: JSONFail.Test38.self) - _run_failTest(name: "fail39", type: JSONFail.Test39.self) - _run_failTest(name: "fail40", type: JSONFail.Test40.self) - _run_failTest(name: "fail41", type: JSONFail.Test41.self) - - } - - func _run_json5SpecTest(_ category: String, _ name: String, testType: JSON5SpecTestType, type: T.Type) { - let subdirectory = "/JSON5/spec/\(category)" - let ext = testType.fileExtension - let jsonData = testData(forResource: name, withExtension: ext, subdirectory: subdirectory)! - - let json5 = json5Decoder - let json = JSONDecoder() - - switch testType { - case .json, .json5_foundationPermissiveJSON: - // Valid JSON should remain valid JSON5 - XCTAssertNoThrow(try json5.decode(type, from: jsonData)) - - // Repeat with non-JSON5-compliant decoder. - XCTAssertNoThrow(try json.decode(type, from: jsonData)) - case .json5: - XCTAssertNoThrow(try json5.decode(type, from: jsonData)) - - // Regular JSON decoder should throw. - do { - let val = try json.decode(type, from: jsonData) - XCTFail("Expected decode failure (original JSON)for test \(name).\(ext), but got: \(val)") - } catch { } - case .js: - // Valid ES5 that's explicitly disallowed by JSON5 is also invalid JSON. - do { - let val = try json5.decode(type, from: jsonData) - XCTFail("Expected decode failure (JSON5) for test \(name).\(ext), but got: \(val)") - } catch { } - - // Regular JSON decoder should also throw. - do { - let val = try json.decode(type, from: jsonData) - XCTFail("Expected decode failure (original JSON) for test \(name).\(ext), but got: \(val)") - } catch { } - case .malformed: - // Invalid ES5 should remain invalid JSON5 - do { - let val = try json5.decode(type, from: jsonData) - XCTFail("Expected decode failure (JSON5) for test \(name).\(ext), but got: \(val)") - } catch { } - - // Regular JSON decoder should also throw. - do { - let val = try json.decode(type, from: jsonData) - XCTFail("Expected decode failure (original JSON) for test \(name).\(ext), but got: \(val)") - } catch { } - } - } - - // Also tests non-JSON5 decoder against the non-JSON5 tests in this test suite. - func test_json5Spec() { - // Expected successes: - _run_json5SpecTest("arrays", "empty-array", testType: .json, type: [Bool].self) - _run_json5SpecTest("arrays", "regular-array", testType: .json, type: [Bool?].self) - _run_json5SpecTest("arrays", "trailing-comma-array", testType: .json5_foundationPermissiveJSON, type: [NullReader].self) - - _run_json5SpecTest("comments", "block-comment-following-array-element", testType: .json5, type: [Bool].self) - _run_json5SpecTest("comments", "block-comment-following-top-level-value", testType: .json5, type: NullReader.self) - _run_json5SpecTest("comments", "block-comment-in-string", testType: .json, type: String.self) - _run_json5SpecTest("comments", "block-comment-preceding-top-level-value", testType: .json5, type: NullReader.self) - _run_json5SpecTest("comments", "block-comment-with-asterisks", testType: .json5, type: Bool.self) - _run_json5SpecTest("comments", "inline-comment-following-array-element", testType: .json5, type: [Bool].self) - _run_json5SpecTest("comments", "inline-comment-following-top-level-value", testType: .json5, type: NullReader.self) - _run_json5SpecTest("comments", "inline-comment-in-string", testType: .json, type: String.self) - _run_json5SpecTest("comments", "inline-comment-preceding-top-level-value", testType: .json5, type: NullReader.self) - - _run_json5SpecTest("misc", "npm-package", testType: .json, type: JSON5Spec.NPMPackage.self) - _run_json5SpecTest("misc", "npm-package", testType: .json5, type: JSON5Spec.NPMPackage.self) - _run_json5SpecTest("misc", "readme-example", testType: .json5, type: JSON5Spec.ReadmeExample.self) - _run_json5SpecTest("misc", "valid-whitespace", testType: .json5, type: [String:Bool].self) - - _run_json5SpecTest("new-lines", "comment-cr", testType: .json5, type: [String:String].self) - _run_json5SpecTest("new-lines", "comment-crlf", testType: .json5, type: [String:String].self) - _run_json5SpecTest("new-lines", "comment-lf", testType: .json5, type: [String:String].self) - _run_json5SpecTest("new-lines", "escaped-cr", testType: .json5, type: [String:String].self) - _run_json5SpecTest("new-lines", "escaped-crlf", testType: .json5, type: [String:String].self) - _run_json5SpecTest("new-lines", "escaped-lf", testType: .json5, type: [String:String].self) - - _run_json5SpecTest("numbers", "float-leading-decimal-point", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "float-leading-zero", testType: .json, type: Double.self) - _run_json5SpecTest("numbers", "float-trailing-decimal-point-with-integer-exponent", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "float-trailing-decimal-point", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "float-with-integer-exponent", testType: .json, type: Double.self) - _run_json5SpecTest("numbers", "float", testType: .json, type: Double.self) - _run_json5SpecTest("numbers", "hexadecimal-lowercase-letter", testType: .json5, type: UInt.self) - _run_json5SpecTest("numbers", "hexadecimal-uppercase-x", testType: .json5, type: UInt.self) - _run_json5SpecTest("numbers", "hexadecimal-with-integer-exponent", testType: .json5, type: UInt.self) - _run_json5SpecTest("numbers", "hexadecimal", testType: .json5, type: UInt.self) - _run_json5SpecTest("numbers", "infinity", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "integer-with-integer-exponent", testType: .json, type: Double.self) - _run_json5SpecTest("numbers", "integer-with-negative-integer-exponent", testType: .json, type: Double.self) - _run_json5SpecTest("numbers", "integer-with-negative-zero-integer-exponent", testType: .json, type: Int.self) - _run_json5SpecTest("numbers", "integer-with-positive-integer-exponent", testType: .json, type: Int.self) - _run_json5SpecTest("numbers", "integer-with-positive-zero-integer-exponent", testType: .json, type: Int.self) - _run_json5SpecTest("numbers", "integer-with-zero-integer-exponent", testType: .json, type: Int.self) - _run_json5SpecTest("numbers", "integer", testType: .json, type: Int.self) - _run_json5SpecTest("numbers", "nan", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "negative-float-leading-decimal-point", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "negative-float-leading-zero", testType: .json, type: Double.self) - _run_json5SpecTest("numbers", "negative-float-trailing-decimal-point", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "negative-float", testType: .json, type: Double.self) - _run_json5SpecTest("numbers", "negative-hexadecimal", testType: .json5, type: Int.self) - _run_json5SpecTest("numbers", "negative-infinity", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "negative-integer", testType: .json, type: Int.self) - _run_json5SpecTest("numbers", "negative-zero-float-leading-decimal-point", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "negative-zero-float-trailing-decimal-point", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "negative-zero-hexadecimal", testType: .json5, type: Int.self) - _run_json5SpecTest("numbers", "negative-zero-integer", testType: .json, type: Int.self) - _run_json5SpecTest("numbers", "positive-integer", testType: .json5, type: Int.self) - _run_json5SpecTest("numbers", "positive-zero-float-leading-decimal-point", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "positive-zero-float-trailing-decimal-point", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "positive-zero-float", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "positive-zero-hexadecimal", testType: .json5, type: Int.self) - _run_json5SpecTest("numbers", "positive-zero-integer", testType: .json5, type: Int.self) - _run_json5SpecTest("numbers", "zero-float-leading-decimal-point", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "zero-float-trailing-decimal-point", testType: .json5, type: Double.self) - _run_json5SpecTest("numbers", "zero-float", testType: .json, type: Double.self) - _run_json5SpecTest("numbers", "zero-hexadecimal", testType: .json5, type: Int.self) - _run_json5SpecTest("numbers", "zero-integer-with-integer-exponent", testType: .json, type: Int.self) - _run_json5SpecTest("numbers", "zero-integer", testType: .json, type: Int.self) - - _run_json5SpecTest("objects", "duplicate-keys", testType: .json, type: [String:Bool].self) - _run_json5SpecTest("objects", "empty-object", testType: .json, type: [String:Bool].self) - _run_json5SpecTest("objects", "reserved-unquoted-key", testType: .json5, type: [String:Bool].self) - _run_json5SpecTest("objects", "single-quoted-key", testType: .json5, type: [String:String].self) - _run_json5SpecTest("objects", "trailing-comma-object", testType: .json5_foundationPermissiveJSON, type: [String:String].self) - _run_json5SpecTest("objects", "unquoted-keys", testType: .json5, type: [String:String].self) - - _run_json5SpecTest("strings", "escaped-single-quoted-string", testType: .json5, type: String.self) - _run_json5SpecTest("strings", "multi-line-string", testType: .json5, type: String.self) - _run_json5SpecTest("strings", "single-quoted-string", testType: .json5, type: String.self) - - _run_json5SpecTest("todo", "unicode-escaped-unquoted-key", testType: .json5, type: [String:String].self) - _run_json5SpecTest("todo", "unicode-unquoted-key", testType: .json5, type: [String:String].self) - - // Expected failures: - _run_json5SpecTest("arrays", "leading-comma-array", testType: .js, type: [Bool].self) - _run_json5SpecTest("arrays", "lone-trailing-comma-array", testType: .js, type: [Bool].self) - _run_json5SpecTest("arrays", "no-comma-array", testType: .malformed, type: [Bool].self) - - _run_json5SpecTest("comments", "top-level-block-comment", testType: .malformed, type: Bool.self) - _run_json5SpecTest("comments", "top-level-inline-comment", testType: .malformed, type: Bool.self) - _run_json5SpecTest("comments", "unterminated-block-comment", testType: .malformed, type: Bool.self) - - _run_json5SpecTest("misc", "empty", testType: .malformed, type: Bool.self) - - _run_json5SpecTest("numbers", "hexadecimal-empty", testType: .malformed, type: UInt.self) - _run_json5SpecTest("numbers", "integer-with-float-exponent", testType: .malformed, type: Double.self) - _run_json5SpecTest("numbers", "integer-with-hexadecimal-exponent", testType: .malformed, type: Double.self) - _run_json5SpecTest("numbers", "integer-with-negative-float-exponent", testType: .malformed, type: Double.self) - _run_json5SpecTest("numbers", "integer-with-negative-hexadecimal-exponent", testType: .malformed, type: Double.self) - _run_json5SpecTest("numbers", "integer-with-positive-float-exponent", testType: .malformed, type: Double.self) - _run_json5SpecTest("numbers", "integer-with-positive-hexadecimal-exponent", testType: .malformed, type: Double.self) - _run_json5SpecTest("numbers", "lone-decimal-point", testType: .malformed, type: Double.self) - _run_json5SpecTest("numbers", "negative-noctal", testType: .js, type: Int.self) - _run_json5SpecTest("numbers", "negative-octal", testType: .malformed, type: Int.self) - _run_json5SpecTest("numbers", "noctal-with-leading-octal-digit", testType: .js, type: Int.self) - _run_json5SpecTest("numbers", "noctal", testType: .js, type: Int.self) - _run_json5SpecTest("numbers", "octal", testType: .malformed, type: Int.self) - _run_json5SpecTest("numbers", "positive-noctal", testType: .js, type: Int.self) - _run_json5SpecTest("numbers", "positive-octal", testType: .malformed, type: Int.self) - _run_json5SpecTest("numbers", "positive-zero-octal", testType: .malformed, type: Int.self) - _run_json5SpecTest("numbers", "zero-octal", testType: .malformed, type: Int.self) - - _run_json5SpecTest("objects", "illegal-unquoted-key-number", testType: .malformed, type: [String:String].self) - - // The spec test disallows this case, but historically NSJSONSerialization has allowed it. Our new implementation is more up-to-spec. - _run_json5SpecTest("objects", "illegal-unquoted-key-symbol", testType: .malformed, type: [String:String].self) - - _run_json5SpecTest("objects", "leading-comma-object", testType: .malformed, type: [String:String].self) - _run_json5SpecTest("objects", "lone-trailing-comma-object", testType: .malformed, type: [String:String].self) - _run_json5SpecTest("objects", "no-comma-object", testType: .malformed, type: [String:String].self) - - _run_json5SpecTest("strings", "unescaped-multi-line-string", testType: .malformed, type: String.self) - - } - - func testEncodingDateISO8601() { - let timestamp = Date(timeIntervalSince1970: 1000) - let expectedJSON = "\"\(timestamp.formatted(.iso8601))\"".data(using: String._Encoding.utf8)! - - _testRoundTrip(of: timestamp, - expectedJSON: expectedJSON, - dateEncodingStrategy: .iso8601, - dateDecodingStrategy: .iso8601) - - - // Optional dates should encode the same way. - _testRoundTrip(of: Optional(timestamp), - expectedJSON: expectedJSON, - dateEncodingStrategy: .iso8601, - dateDecodingStrategy: .iso8601) - } - - func testEncodingDataBase64() { - let data = Data([0xDE, 0xAD, 0xBE, 0xEF]) - - let expectedJSON = "\"3q2+7w==\"".data(using: String._Encoding.utf8)! - _testRoundTrip(of: data, expectedJSON: expectedJSON) - - // Optional data should encode the same way. - _testRoundTrip(of: Optional(data), expectedJSON: expectedJSON) - } -} - -// MARK: - Decimal Tests -extension JSONEncoderTests { - func testInterceptDecimal() { - let expectedJSON = "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".data(using: String._Encoding.utf8)! - - // Want to make sure we write out a JSON number, not the keyed encoding here. - // 1e127 is too big to fit natively in a Double, too, so want to make sure it's encoded as a Decimal. - let decimal = Decimal(sign: .plus, exponent: 127, significand: Decimal(1)) - _testRoundTrip(of: decimal, expectedJSON: expectedJSON) - - // Optional Decimals should encode the same way. - _testRoundTrip(of: Optional(decimal), expectedJSON: expectedJSON) - } - - func test_hugeNumbers() { - let json = "23456789012000000000000000000000000000000000000000000000000000000000000000000 " - let data = json.data(using: String._Encoding.utf8)! - - let decimal = try! JSONDecoder().decode(Decimal.self, from: data) - let expected = Decimal(string: json) - XCTAssertEqual(decimal, expected) - } - - func testInterceptLargeDecimal() { - struct TestBigDecimal: Codable, Equatable { - var uint64Max: Decimal = Decimal(UInt64.max) - var unit64MaxPlus1: Decimal = Decimal( - _exponent: 0, - _length: 5, - _isNegative: 0, - _isCompact: 1, - _reserved: 0, - _mantissa: (0, 0, 0, 0, 1, 0, 0, 0) - ) - var int64Min: Decimal = Decimal(Int64.min) - var int64MinMinus1: Decimal = Decimal( - _exponent: 0, - _length: 4, - _isNegative: 1, - _isCompact: 1, - _reserved: 0, - _mantissa: (1, 0, 0, 32768, 0, 0, 0, 0) - ) - } - - let testBigDecimal = TestBigDecimal() - _testRoundTrip(of: testBigDecimal) - } - - func testOverlargeDecimal() { - // Check value too large fails to decode. - XCTAssertThrowsError(try JSONDecoder().decode(Decimal.self, from: "100e200".data(using: .utf8)!)) - } -} - -// MARK: - Framework-only tests - -#if FOUNDATION_FRAMEWORK -extension JSONEncoderTests { - // This will remain a framework-only test due to dependence on `DateFormatter`. - func testEncodingDateFormatted() { - let formatter = DateFormatter() - formatter.dateStyle = .full - formatter.timeStyle = .full - - let timestamp = Date(timeIntervalSince1970: 1000) - let expectedJSON = "\"\(formatter.string(from: timestamp))\"".data(using: String._Encoding.utf8)! - - _testRoundTrip(of: timestamp, - expectedJSON: expectedJSON, - dateEncodingStrategy: .formatted(formatter), - dateDecodingStrategy: .formatted(formatter)) - - // Optional dates should encode the same way. - _testRoundTrip(of: Optional(timestamp), - expectedJSON: expectedJSON, - dateEncodingStrategy: .formatted(formatter), - dateDecodingStrategy: .formatted(formatter)) - - // So should wrapped dates. - let expectedJSON_array = "[\"\(formatter.string(from: timestamp))\"]".data(using: String._Encoding.utf8)! - _testRoundTrip(of: TopLevelArrayWrapper(timestamp), - expectedJSON: expectedJSON_array, - dateEncodingStrategy: .formatted(formatter), - dateDecodingStrategy: .formatted(formatter)) - } -} -#endif - -// MARK: - .sortedKeys Tests -extension JSONEncoderTests { - func testEncodingTopLevelStructuredClass() { - // Person is a class with multiple fields. - let expectedJSON = "{\"email\":\"appleseed@apple.com\",\"name\":\"Johnny Appleseed\"}".data(using: String._Encoding.utf8)! - let person = Person.testValue - _testRoundTrip(of: person, expectedJSON: expectedJSON, outputFormatting: [.sortedKeys]) - } - - func testEncodingOutputFormattingSortedKeys() { - let expectedJSON = "{\"email\":\"appleseed@apple.com\",\"name\":\"Johnny Appleseed\"}".data(using: String._Encoding.utf8)! - let person = Person.testValue - _testRoundTrip(of: person, expectedJSON: expectedJSON, outputFormatting: [.sortedKeys]) - } - - func testEncodingOutputFormattingPrettyPrintedSortedKeys() { - let expectedJSON = "{\n \"email\" : \"appleseed@apple.com\",\n \"name\" : \"Johnny Appleseed\"\n}".data(using: String._Encoding.utf8)! - let person = Person.testValue - _testRoundTrip(of: person, expectedJSON: expectedJSON, outputFormatting: [.prettyPrinted, .sortedKeys]) - } - - func testEncodingSortedKeys() { - // When requesting sorted keys, dictionary keys are sorted prior to being written out. - // This sort should be stable, numeric, and follow human-readable sorting rules as defined by the system locale. - let dict = [ - // These three keys should appear in a stable, deterministic ordering relative to one another, regardless of their order in the dictionary. - // For example, if the sort were naively case-insensitive, these three would be `NSOrderedSame`, and would not swap with one another in the sort, maintaining their relative ordering based on their position in the dictionary. The inclusion of other keys in the dictionary can alter their relative ordering (because of hashing), producing non-stable output. - "Foo" : 1, - "FOO" : 2, - "foo" : 3, - - // These keys should output in numeric order (1, 2, 3, 11, 12) rather than literal string order (1, 11, 12, 2, 3). - "foo1" : 4, - "Foo2" : 5, - "foo3" : 6, - "foo12" : 7, - "Foo11" : 8, - - // This key should be sorted in a human-readable way (e.g. among the other "foo" keys, not after them just because the binary value of 'ø' > 'o'). - "føo" : 9, - "bar" : 10 - ] - - _testRoundTrip(of: dict, expectedJSON: #"{"FOO":2,"Foo":1,"Foo11":8,"Foo2":5,"bar":10,"foo":3,"foo1":4,"foo12":7,"foo3":6,"føo":9}"#.data(using: String._Encoding.utf8)!, outputFormatting: [.sortedKeys]) - } - - func testEncodingSortedKeysStableOrdering() { - // We want to make sure that keys of different length (but with identical prefixes) always sort in a stable way, regardless of their hash ordering. - var dict = ["AAA" : 1, "AAAAAAB" : 2] - var expectedJSONString = "{\"AAA\":1,\"AAAAAAB\":2}" - _testRoundTrip(of: dict, expectedJSON: expectedJSONString.data(using: String._Encoding.utf8)!, outputFormatting: [.sortedKeys]) - - // We don't want this test to rely on the hashing of Strings or how Dictionary uses that hash. - // We'll insert a large number of keys into this dictionary and guarantee that the ordering of the above keys has indeed not changed. - // To ensure that we don't accidentally test the same (passing) case every time these keys will be shuffled. - let testSize = 256 - var Ns = Array(0 ..< testSize) - - // Simple Fisher-Yates shuffle. - for i in Ns.indices.reversed() { - let index = Int(Double.random(in: 0.0 ..< Double(i+1))) - let N = Ns[i] - Ns[i] = Ns[index] - - // Normally we'd set Ns[index] = N, but since all we need this value for is for inserting into the dictionary later, we can do it right here and not even write back to the source array. - // No need to do an O(n) loop over Ns again. - dict["key\(N)"] = N - } - - let numberKeys = (0 ..< testSize).map { "\($0)" }.sorted() - for key in numberKeys { - let insertedKeyJSON = ",\"key\(key)\":\(key)" - expectedJSONString.insert(contentsOf: insertedKeyJSON, at: expectedJSONString.index(before: expectedJSONString.endIndex)) - } - - _testRoundTrip(of: dict, expectedJSON: expectedJSONString.data(using: String._Encoding.utf8)!, outputFormatting: [.sortedKeys]) - } - - func testEncodingMultipleNestedContainersWithTheSameTopLevelKey() { - struct Model : Codable, Equatable { - let first: String - let second: String - - init(from coder: Decoder) throws { - let container = try coder.container(keyedBy: TopLevelCodingKeys.self) - - let firstNestedContainer = try container.nestedContainer(keyedBy: FirstNestedCodingKeys.self, forKey: .top) - self.first = try firstNestedContainer.decode(String.self, forKey: .first) - - let secondNestedContainer = try container.nestedContainer(keyedBy: SecondNestedCodingKeys.self, forKey: .top) - self.second = try secondNestedContainer.decode(String.self, forKey: .second) - } - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: TopLevelCodingKeys.self) - - var firstNestedContainer = container.nestedContainer(keyedBy: FirstNestedCodingKeys.self, forKey: .top) - try firstNestedContainer.encode(self.first, forKey: .first) - - var secondNestedContainer = container.nestedContainer(keyedBy: SecondNestedCodingKeys.self, forKey: .top) - try secondNestedContainer.encode(self.second, forKey: .second) - } - - init(first: String, second: String) { - self.first = first - self.second = second - } - - static var testValue: Model { - return Model(first: "Johnny Appleseed", - second: "appleseed@apple.com") - } - - enum TopLevelCodingKeys : String, CodingKey { - case top - } - - enum FirstNestedCodingKeys : String, CodingKey { - case first - } - enum SecondNestedCodingKeys : String, CodingKey { - case second - } - } - - let model = Model.testValue - let expectedJSON = "{\"top\":{\"first\":\"Johnny Appleseed\",\"second\":\"appleseed@apple.com\"}}".data(using: String._Encoding.utf8)! - _testRoundTrip(of: model, expectedJSON: expectedJSON, outputFormatting: [.sortedKeys]) - } - - func test_redundantKeyedContainer() { - struct EncodesTwice: Encodable { - enum CodingKeys: String, CodingKey { - case container - case somethingElse - } - - struct Nested: Encodable { - let foo = "Test" - } - - func encode(to encoder: Encoder) throws { - var topLevel = encoder.container(keyedBy: CodingKeys.self) - try topLevel.encode("Foo", forKey: .somethingElse) - - // Encode an object-like JSON value for the key "container" - try topLevel.encode(Nested(), forKey: .container) - - // A nested container for the same "container" key should reuse the previous container, appending to it, instead of asserting. 106648746. - var secondAgain = topLevel.nestedContainer(keyedBy: CodingKeys.self, forKey: .container) - try secondAgain.encode("SecondAgain", forKey: .somethingElse) - } - } - - let encoder = JSONEncoder() - encoder.outputFormatting = .sortedKeys - let data = try! encoder.encode(EncodesTwice()) - let string = String(data: data, encoding: .utf8)! - - XCTAssertEqual(string, "{\"container\":{\"foo\":\"Test\",\"somethingElse\":\"SecondAgain\"},\"somethingElse\":\"Foo\"}") - } - - func test_singleValueDictionaryAmendedByContainer() { - struct Test: Encodable { - enum CodingKeys: String, CodingKey { - case a - } - - func encode(to encoder: Encoder) throws { - var svc = encoder.singleValueContainer() - try svc.encode(["a" : "b", "other" : "foo"]) - - var keyed = encoder.container(keyedBy: CodingKeys.self) - try keyed.encode("c", forKey: .a) - } - } - let encoder = JSONEncoder() - encoder.outputFormatting = .sortedKeys - let data = try! encoder.encode(Test()) - let string = String(data: data, encoding: .utf8)! - - XCTAssertEqual(string, "{\"a\":\"c\",\"other\":\"foo\"}") - } -} - -// MARK: - URL Tests -extension JSONEncoderTests { - func testInterceptURL() { - // Want to make sure JSONEncoder writes out single-value URLs, not the keyed encoding. - let expectedJSON = "\"http:\\/\\/swift.org\"".data(using: String._Encoding.utf8)! - let url = URL(string: "http://swift.org")! - _testRoundTrip(of: url, expectedJSON: expectedJSON) - - // Optional URLs should encode the same way. - _testRoundTrip(of: Optional(url), expectedJSON: expectedJSON) - } - - func testInterceptURLWithoutEscapingOption() { - // Want to make sure JSONEncoder writes out single-value URLs, not the keyed encoding. - let expectedJSON = "\"http://swift.org\"".data(using: String._Encoding.utf8)! - let url = URL(string: "http://swift.org")! - _testRoundTrip(of: url, expectedJSON: expectedJSON, outputFormatting: [.withoutEscapingSlashes]) - - // Optional URLs should encode the same way. - _testRoundTrip(of: Optional(url), expectedJSON: expectedJSON, outputFormatting: [.withoutEscapingSlashes]) - } -} - -// MARK: - Helper Global Functions -func expectEqualPaths(_ lhs: [CodingKey], _ rhs: [CodingKey], _ prefix: String) { - if lhs.count != rhs.count { - XCTFail("\(prefix) [CodingKey].count mismatch: \(lhs.count) != \(rhs.count)") - return - } - - for (key1, key2) in zip(lhs, rhs) { - switch (key1.intValue, key2.intValue) { - case (.none, .none): break - case (.some(let i1), .none): - XCTFail("\(prefix) CodingKey.intValue mismatch: \(type(of: key1))(\(i1)) != nil") - return - case (.none, .some(let i2)): - XCTFail("\(prefix) CodingKey.intValue mismatch: nil != \(type(of: key2))(\(i2))") - return - case (.some(let i1), .some(let i2)): - guard i1 == i2 else { - XCTFail("\(prefix) CodingKey.intValue mismatch: \(type(of: key1))(\(i1)) != \(type(of: key2))(\(i2))") - return - } - } - - XCTAssertEqual(key1.stringValue, key2.stringValue, "\(prefix) CodingKey.stringValue mismatch: \(type(of: key1))('\(key1.stringValue)') != \(type(of: key2))('\(key2.stringValue)')") - } -} - -// MARK: - Test Types -/* FIXME: Import from %S/Inputs/Coding/SharedTypes.swift somehow. */ - -// MARK: - Empty Types -fileprivate struct EmptyStruct : Codable, Equatable { - static func ==(_ lhs: EmptyStruct, _ rhs: EmptyStruct) -> Bool { - return true - } -} - -fileprivate class EmptyClass : Codable, Equatable { - static func ==(_ lhs: EmptyClass, _ rhs: EmptyClass) -> Bool { - return true - } -} - -// MARK: - Single-Value Types -/// A simple on-off switch type that encodes as a single Bool value. -fileprivate enum Switch : Codable { - case off - case on - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - switch try container.decode(Bool.self) { - case false: self = .off - case true: self = .on - } - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - switch self { - case .off: try container.encode(false) - case .on: try container.encode(true) - } - } -} - -/// A simple timestamp type that encodes as a single Double value. -fileprivate struct Timestamp : Codable, Equatable { - let value: Double - - init(_ value: Double) { - self.value = value - } - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - value = try container.decode(Double.self) - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(self.value) - } - - static func ==(_ lhs: Timestamp, _ rhs: Timestamp) -> Bool { - return lhs.value == rhs.value - } -} - -/// A simple referential counter type that encodes as a single Int value. -fileprivate final class Counter : Codable, Equatable { - var count: Int = 0 - - init() {} - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - count = try container.decode(Int.self) - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(self.count) - } - - static func ==(_ lhs: Counter, _ rhs: Counter) -> Bool { - return lhs === rhs || lhs.count == rhs.count - } -} - -// MARK: - Structured Types -/// A simple address type that encodes as a dictionary of values. -fileprivate struct Address : Codable, Equatable { - let street: String - let city: String - let state: String - let zipCode: Int - let country: String - - init(street: String, city: String, state: String, zipCode: Int, country: String) { - self.street = street - self.city = city - self.state = state - self.zipCode = zipCode - self.country = country - } - - static func ==(_ lhs: Address, _ rhs: Address) -> Bool { - return lhs.street == rhs.street && - lhs.city == rhs.city && - lhs.state == rhs.state && - lhs.zipCode == rhs.zipCode && - lhs.country == rhs.country - } - - static var testValue: Address { - return Address(street: "1 Infinite Loop", - city: "Cupertino", - state: "CA", - zipCode: 95014, - country: "United States") - } -} - -/// A simple person class that encodes as a dictionary of values. -fileprivate class Person : Codable, Equatable { - let name: String - let email: String - let website: URL? - - - init(name: String, email: String, website: URL? = nil) { - self.name = name - self.email = email - self.website = website - } - - func isEqual(_ other: Person) -> Bool { - return self.name == other.name && - self.email == other.email && - self.website == other.website - } - - static func ==(_ lhs: Person, _ rhs: Person) -> Bool { - return lhs.isEqual(rhs) - } - - class var testValue: Person { - return Person(name: "Johnny Appleseed", email: "appleseed@apple.com") - } -} - -/// A class which shares its encoder and decoder with its superclass. -fileprivate class Employee : Person { - let id: Int - - init(name: String, email: String, website: URL? = nil, id: Int) { - self.id = id - super.init(name: name, email: email, website: website) - } - - enum CodingKeys : String, CodingKey { - case id - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - id = try container.decode(Int.self, forKey: .id) - try super.init(from: decoder) - } - - override func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(id, forKey: .id) - try super.encode(to: encoder) - } - - override func isEqual(_ other: Person) -> Bool { - if let employee = other as? Employee { - guard self.id == employee.id else { return false } - } - - return super.isEqual(other) - } - - override class var testValue: Employee { - return Employee(name: "Johnny Appleseed", email: "appleseed@apple.com", id: 42) - } -} - -/// A simple company struct which encodes as a dictionary of nested values. -fileprivate struct Company : Codable, Equatable { - let address: Address - var employees: [Employee] - - init(address: Address, employees: [Employee]) { - self.address = address - self.employees = employees - } - - static func ==(_ lhs: Company, _ rhs: Company) -> Bool { - return lhs.address == rhs.address && lhs.employees == rhs.employees - } - - static var testValue: Company { - return Company(address: Address.testValue, employees: [Employee.testValue]) - } -} - -/// An enum type which decodes from Bool?. -fileprivate enum EnhancedBool : Codable { - case `true` - case `false` - case fileNotFound - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - if container.decodeNil() { - self = .fileNotFound - } else { - let value = try container.decode(Bool.self) - self = value ? .true : .false - } - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - switch self { - case .true: try container.encode(true) - case .false: try container.encode(false) - case .fileNotFound: try container.encodeNil() - } - } -} - -/// A type which encodes as an array directly through a single value container. -private struct Numbers : Codable, Equatable { - let values = [4, 8, 15, 16, 23, 42] - - init() {} - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - let decodedValues = try container.decode([Int].self) - guard decodedValues == values else { - throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "The Numbers are wrong!")) - } - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(values) - } - - static func ==(_ lhs: Numbers, _ rhs: Numbers) -> Bool { - return lhs.values == rhs.values - } - - static var testValue: Numbers { - return Numbers() - } -} - -/// A type which encodes as a dictionary directly through a single value container. -fileprivate final class Mapping : Codable, Equatable { - let values: [String : Int] - - init(values: [String : Int]) { - self.values = values - } - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - values = try container.decode([String : Int].self) - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(values) - } - - static func ==(_ lhs: Mapping, _ rhs: Mapping) -> Bool { - return lhs === rhs || lhs.values == rhs.values - } - - static var testValue: Mapping { - return Mapping(values: ["Apple": 42, - "localhost": 127]) - } -} - -private struct NestedContainersTestType : Encodable { - let testSuperEncoder: Bool - - init(testSuperEncoder: Bool = false) { - self.testSuperEncoder = testSuperEncoder - } - - enum TopLevelCodingKeys : Int, CodingKey { - case a - case b - case c - } - - enum IntermediateCodingKeys : Int, CodingKey { - case one - case two - } - - func encode(to encoder: Encoder) throws { - if self.testSuperEncoder { - var topLevelContainer = encoder.container(keyedBy: TopLevelCodingKeys.self) - expectEqualPaths(encoder.codingPath, [], "Top-level Encoder's codingPath changed.") - expectEqualPaths(topLevelContainer.codingPath, [], "New first-level keyed container has non-empty codingPath.") - - let superEncoder = topLevelContainer.superEncoder(forKey: .a) - expectEqualPaths(encoder.codingPath, [], "Top-level Encoder's codingPath changed.") - expectEqualPaths(topLevelContainer.codingPath, [], "First-level keyed container's codingPath changed.") - expectEqualPaths(superEncoder.codingPath, [TopLevelCodingKeys.a], "New superEncoder had unexpected codingPath.") - _testNestedContainers(in: superEncoder, baseCodingPath: [TopLevelCodingKeys.a]) - } else { - _testNestedContainers(in: encoder, baseCodingPath: []) - } - } - - func _testNestedContainers(in encoder: Encoder, baseCodingPath: [CodingKey]) { - expectEqualPaths(encoder.codingPath, baseCodingPath, "New encoder has non-empty codingPath.") - - // codingPath should not change upon fetching a non-nested container. - var firstLevelContainer = encoder.container(keyedBy: TopLevelCodingKeys.self) - expectEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.") - expectEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "New first-level keyed container has non-empty codingPath.") - - // Nested Keyed Container - do { - // Nested container for key should have a new key pushed on. - var secondLevelContainer = firstLevelContainer.nestedContainer(keyedBy: IntermediateCodingKeys.self, forKey: .a) - expectEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.") - expectEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "First-level keyed container's codingPath changed.") - expectEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.a], "New second-level keyed container had unexpected codingPath.") - - // Inserting a keyed container should not change existing coding paths. - let thirdLevelContainerKeyed = secondLevelContainer.nestedContainer(keyedBy: IntermediateCodingKeys.self, forKey: .one) - expectEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.") - expectEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "First-level keyed container's codingPath changed.") - expectEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.a], "Second-level keyed container's codingPath changed.") - expectEqualPaths(thirdLevelContainerKeyed.codingPath, baseCodingPath + [TopLevelCodingKeys.a, IntermediateCodingKeys.one], "New third-level keyed container had unexpected codingPath.") - - // Inserting an unkeyed container should not change existing coding paths. - let thirdLevelContainerUnkeyed = secondLevelContainer.nestedUnkeyedContainer(forKey: .two) - expectEqualPaths(encoder.codingPath, baseCodingPath + [], "Top-level Encoder's codingPath changed.") - expectEqualPaths(firstLevelContainer.codingPath, baseCodingPath + [], "First-level keyed container's codingPath changed.") - expectEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.a], "Second-level keyed container's codingPath changed.") - expectEqualPaths(thirdLevelContainerUnkeyed.codingPath, baseCodingPath + [TopLevelCodingKeys.a, IntermediateCodingKeys.two], "New third-level unkeyed container had unexpected codingPath.") - } - - // Nested Unkeyed Container - do { - // Nested container for key should have a new key pushed on. - var secondLevelContainer = firstLevelContainer.nestedUnkeyedContainer(forKey: .b) - expectEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.") - expectEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "First-level keyed container's codingPath changed.") - expectEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.b], "New second-level keyed container had unexpected codingPath.") - - // Appending a keyed container should not change existing coding paths. - let thirdLevelContainerKeyed = secondLevelContainer.nestedContainer(keyedBy: IntermediateCodingKeys.self) - expectEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.") - expectEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "First-level keyed container's codingPath changed.") - expectEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.b], "Second-level unkeyed container's codingPath changed.") - expectEqualPaths(thirdLevelContainerKeyed.codingPath, baseCodingPath + [TopLevelCodingKeys.b, _TestKey(index: 0)], "New third-level keyed container had unexpected codingPath.") - - // Appending an unkeyed container should not change existing coding paths. - let thirdLevelContainerUnkeyed = secondLevelContainer.nestedUnkeyedContainer() - expectEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.") - expectEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "First-level keyed container's codingPath changed.") - expectEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.b], "Second-level unkeyed container's codingPath changed.") - expectEqualPaths(thirdLevelContainerUnkeyed.codingPath, baseCodingPath + [TopLevelCodingKeys.b, _TestKey(index: 1)], "New third-level unkeyed container had unexpected codingPath.") - } - } -} - -private struct CodableTypeWithConfiguration : CodableWithConfiguration, Equatable { - struct Config { - let num: Int - - init(_ num: Int) { - self.num = num - } - } - - struct ConfigProviding : EncodingConfigurationProviding, DecodingConfigurationProviding { - static var encodingConfiguration: Config { Config(2) } - static var decodingConfiguration: Config { Config(2) } - } - - typealias EncodingConfiguration = Config - typealias DecodingConfiguration = Config - - static let testValue = Self(3) - - let num: Int - - init(_ num: Int) { - self.num = num - } - - func encode(to encoder: Encoder, configuration: Config) throws { - var container = encoder.singleValueContainer() - try container.encode(num + configuration.num) - } - - init(from decoder: Decoder, configuration: Config) throws { - let container = try decoder.singleValueContainer() - num = try container.decode(Int.self) - configuration.num - } -} - -// MARK: - Helper Types - -/// A key type which can take on any string or integer value. -/// This needs to mirror _CodingKey. -fileprivate struct _TestKey : CodingKey { - var stringValue: String - var intValue: Int? - - init?(stringValue: String) { - self.stringValue = stringValue - self.intValue = nil - } - - init?(intValue: Int) { - self.stringValue = "\(intValue)" - self.intValue = intValue - } - - init(index: Int) { - self.stringValue = "Index \(index)" - self.intValue = index - } -} - -fileprivate struct FloatNaNPlaceholder : Codable, Equatable { - init() {} - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(Float.nan) - } - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - let float = try container.decode(Float.self) - if !float.isNaN { - throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Couldn't decode NaN.")) - } - } - - static func ==(_ lhs: FloatNaNPlaceholder, _ rhs: FloatNaNPlaceholder) -> Bool { - return true - } -} - -fileprivate struct DoubleNaNPlaceholder : Codable, Equatable { - init() {} - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(Double.nan) - } - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - let double = try container.decode(Double.self) - if !double.isNaN { - throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Couldn't decode NaN.")) - } - } - - static func ==(_ lhs: DoubleNaNPlaceholder, _ rhs: DoubleNaNPlaceholder) -> Bool { - return true - } -} - -internal protocol DecodeIfPresentAllTypesConfig { - static var useKeyed: Bool { get } - static var encodeNulls: Bool { get } -} -internal struct UseKeyed: DecodeIfPresentAllTypesConfig { - static let useKeyed = true - static let encodeNulls = true -} -internal struct UseUnkeyed: DecodeIfPresentAllTypesConfig { - static let useKeyed = false - static let encodeNulls = true -} -internal typealias KeyedEncodeWithNulls = UseKeyed -internal typealias UnkeyedEncodeWithNulls = UseUnkeyed -internal struct KeyedEncodeWithoutNulls: DecodeIfPresentAllTypesConfig { - static let useKeyed = true - static let encodeNulls = false -} -internal struct UnkeyedEncodeWithoutNulls: DecodeIfPresentAllTypesConfig { - static let useKeyed = false - static let encodeNulls = false -} - -internal struct DecodeIfPresentAllTypes: Codable, Equatable { - let bool: Bool? - let string: String? - let i: Int? - let i8: Int8? - let i16: Int16? - let i32: Int32? - let i64: Int64? - let u: UInt? - let u8: UInt8? - let u16: UInt16? - let u32: UInt32? - let u64: UInt64? - let float: Float? - let double: Double? - let other: [Int]? - - init(bool: Bool?, string: String?, i: Int?, i8: Int8?, i16: Int16?, i32: Int32?, i64: Int64?, u: UInt?, u8: UInt8?, u16: UInt16?, u32: UInt32?, u64: UInt64?, float: Float?, double: Double?, other: [Int]?) { - self.bool = bool - self.string = string - self.i = i - self.i8 = i8 - self.i16 = i16 - self.i32 = i32 - self.i64 = i64 - self.u = u - self.u8 = u8 - self.u16 = u16 - self.u32 = u32 - self.u64 = u64 - self.float = float - self.double = double - self.other = other - } - - enum CodingKeys: String, CodingKey { - case bool - case string - case i - case i8 - case i16 - case i32 - case i64 - case u - case u8 - case u16 - case u32 - case u64 - case float - case double - case other - } - - func encode(to encoder: Encoder) throws { - switch (Config.useKeyed, Config.encodeNulls) { - case (true, true): - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(bool, forKey: .bool) - try container.encode(string, forKey: .string) - try container.encode(i, forKey: .i) - try container.encode(i8, forKey: .i8) - try container.encode(i16, forKey: .i16) - try container.encode(i32, forKey: .i32) - try container.encode(i64, forKey: .i64) - try container.encode(u, forKey: .u) - try container.encode(u8, forKey: .u8) - try container.encode(u16, forKey: .u16) - try container.encode(u32, forKey: .u32) - try container.encode(u64, forKey: .u64) - try container.encode(float, forKey: .float) - try container.encode(double, forKey: .double) - try container.encode(other, forKey: .other) - case (true, false): - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(bool, forKey: .bool) - try container.encodeIfPresent(string, forKey: .string) - try container.encodeIfPresent(i, forKey: .i) - try container.encodeIfPresent(i8, forKey: .i8) - try container.encodeIfPresent(i16, forKey: .i16) - try container.encodeIfPresent(i32, forKey: .i32) - try container.encodeIfPresent(i64, forKey: .i64) - try container.encodeIfPresent(u, forKey: .u) - try container.encodeIfPresent(u8, forKey: .u8) - try container.encodeIfPresent(u16, forKey: .u16) - try container.encodeIfPresent(u32, forKey: .u32) - try container.encodeIfPresent(u64, forKey: .u64) - try container.encodeIfPresent(float, forKey: .float) - try container.encodeIfPresent(double, forKey: .double) - try container.encodeIfPresent(other, forKey: .other) - case (false, true): - var container = encoder.unkeyedContainer() - try container.encode(bool) - try container.encode(string) - try container.encode(i) - try container.encode(i8) - try container.encode(i16) - try container.encode(i32) - try container.encode(i64) - try container.encode(u) - try container.encode(u8) - try container.encode(u16) - try container.encode(u32) - try container.encode(u64) - try container.encode(float) - try container.encode(double) - try container.encode(other) - case (false, false): - var container = encoder.unkeyedContainer() - if let bool { try container.encode(bool) } - if let string { try container.encode(string) } - if let i { try container.encode(i) } - if let i8 { try container.encode(i8) } - if let i16 { try container.encode(i16) } - if let i32 { try container.encode(i32) } - if let i64 { try container.encode(i64) } - if let u { try container.encode(u) } - if let u8 { try container.encode(u8) } - if let u16 { try container.encode(u16) } - if let u32 { try container.encode(u32) } - if let u64 { try container.encode(u64) } - if let float { try container.encode(float) } - if let double { try container.encode(double) } - if let other { try container.encode(other) } - } - } - - init(from decoder: Decoder) throws { - switch Config.useKeyed { - case true: - let container = try decoder.container(keyedBy: CodingKeys.self) - bool = try container.decodeIfPresent(Bool.self, forKey: .bool) - string = try container.decodeIfPresent(String.self, forKey: .string) - i = try container.decodeIfPresent(Int.self, forKey: .i) - i8 = try container.decodeIfPresent(Int8.self, forKey: .i8) - i16 = try container.decodeIfPresent(Int16.self, forKey: .i16) - i32 = try container.decodeIfPresent(Int32.self, forKey: .i32) - i64 = try container.decodeIfPresent(Int64.self, forKey: .i64) - u = try container.decodeIfPresent(UInt.self, forKey: .u) - u8 = try container.decodeIfPresent(UInt8.self, forKey: .u8) - u16 = try container.decodeIfPresent(UInt16.self, forKey: .u16) - u32 = try container.decodeIfPresent(UInt32.self, forKey: .u32) - u64 = try container.decodeIfPresent(UInt64.self, forKey: .u64) - float = try container.decodeIfPresent(Float.self, forKey: .float) - double = try container.decodeIfPresent(Double.self, forKey: .double) - other = try container.decodeIfPresent([Int].self, forKey: .other) - case false: - var container = try decoder.unkeyedContainer() - bool = try container.decodeIfPresent(Bool.self) - string = try container.decodeIfPresent(String.self) - i = try container.decodeIfPresent(Int.self) - i8 = try container.decodeIfPresent(Int8.self) - i16 = try container.decodeIfPresent(Int16.self) - i32 = try container.decodeIfPresent(Int32.self) - i64 = try container.decodeIfPresent(Int64.self) - u = try container.decodeIfPresent(UInt.self) - u8 = try container.decodeIfPresent(UInt8.self) - u16 = try container.decodeIfPresent(UInt16.self) - u32 = try container.decodeIfPresent(UInt32.self) - u64 = try container.decodeIfPresent(UInt64.self) - float = try container.decodeIfPresent(Float.self) - double = try container.decodeIfPresent(Double.self) - other = try container.decodeIfPresent([Int].self) - } - } - - static var allOnes: Self { .init(bool: true, string: "1", i: 1, i8: 1, i16: 1, i32: 1, i64: 1, u: 1, u8: 1, u16: 1, u32: 1, u64: 1, float: 1, double: 1, other: [1]) } - static var allNils: Self { .init(bool: nil, string: nil, i: nil, i8: nil, i16: nil, i32: nil, i64: nil, u: nil, u8: nil, u16: nil, u32: nil, u64: nil, float: nil, double: nil, other: nil) } -} - -fileprivate enum EitherDecodable : Decodable { - case t(T) - case u(U) - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - do { - self = .t(try container.decode(T.self)) - } catch { - self = .u(try container.decode(U.self)) - } - } -} - -struct NullReader : Decodable, Equatable { - enum NullError : String, Error { - case expectedNull = "Expected a null value" - } - init(from decoder: Decoder) throws { - let c = try decoder.singleValueContainer() - guard c.decodeNil() else { - throw NullError.expectedNull - } - } -} - -enum JSONPass { } - -extension JSONPass { - struct Test1: Codable, Equatable { - let glossary: Glossary - - struct Glossary: Codable, Equatable { - let title: String - let glossDiv: GlossDiv - - enum CodingKeys: String, CodingKey { - case title - case glossDiv = "GlossDiv" - } - } - - struct GlossDiv: Codable, Equatable { - let title: String - let glossList: GlossList - - enum CodingKeys: String, CodingKey { - case title - case glossList = "GlossList" - } - } - - struct GlossList: Codable, Equatable { - let glossEntry: GlossEntry - - enum CodingKeys: String, CodingKey { - case glossEntry = "GlossEntry" - } - } - - struct GlossEntry: Codable, Equatable { - let id, sortAs, glossTerm, acronym: String - let abbrev: String - let glossDef: GlossDef - let glossSee: String - - enum CodingKeys: String, CodingKey { - case id = "ID" - case sortAs = "SortAs" - case glossTerm = "GlossTerm" - case acronym = "Acronym" - case abbrev = "Abbrev" - case glossDef = "GlossDef" - case glossSee = "GlossSee" - } - } - - struct GlossDef: Codable, Equatable { - let para: String - let glossSeeAlso: [String] - - enum CodingKeys: String, CodingKey { - case para - case glossSeeAlso = "GlossSeeAlso" - } - } - } -} - -extension JSONPass { - struct Test2: Codable, Equatable { - let menu: Menu - - struct Menu: Codable, Equatable { - let id, value: String - let popup: Popup - } - - struct Popup: Codable, Equatable { - let menuitem: [Menuitem] - } - - struct Menuitem: Codable, Equatable { - let value, onclick: String - } - } -} - -extension JSONPass { - struct Test3: Codable, Equatable { - let widget: Widget - - struct Widget: Codable, Equatable { - let debug: String - let window: Window - let image: Image - let text: Text - } - - struct Image: Codable, Equatable { - let src, name: String - let hOffset, vOffset: Int - let alignment: String - } - - struct Text: Codable, Equatable { - let data: String - let size: Int - let style, name: String - let hOffset, vOffset: Int - let alignment, onMouseUp: String - } - - struct Window: Codable, Equatable { - let title, name: String - let width, height: Int - } - } -} - -extension JSONPass { - struct Test4: Codable, Equatable { - let webApp: WebApp - - enum CodingKeys: String, CodingKey { - case webApp = "web-app" - } - - struct WebApp: Codable, Equatable { - let servlet: [Servlet] - let servletMapping: ServletMapping - let taglib: Taglib - - enum CodingKeys: String, CodingKey { - case servlet - case servletMapping = "servlet-mapping" - case taglib - } - } - - struct Servlet: Codable, Equatable { - let servletName, servletClass: String - let initParam: InitParam? - - enum CodingKeys: String, CodingKey { - case servletName = "servlet-name" - case servletClass = "servlet-class" - case initParam = "init-param" - } - } - - struct InitParam: Codable, Equatable { - let configGlossaryInstallationAt, configGlossaryAdminEmail, configGlossaryPoweredBy, configGlossaryPoweredByIcon: String? - let configGlossaryStaticPath, templateProcessorClass, templateLoaderClass, templatePath: String? - let templateOverridePath, defaultListTemplate, defaultFileTemplate: String? - let useJSP: Bool? - let jspListTemplate, jspFileTemplate: String? - let cachePackageTagsTrack, cachePackageTagsStore, cachePackageTagsRefresh, cacheTemplatesTrack: Int? - let cacheTemplatesStore, cacheTemplatesRefresh, cachePagesTrack, cachePagesStore: Int? - let cachePagesRefresh, cachePagesDirtyRead: Int? - let searchEngineListTemplate, searchEngineFileTemplate, searchEngineRobotsDB: String? - let useDataStore: Bool? - let dataStoreClass, redirectionClass, dataStoreName, dataStoreDriver: String? - let dataStoreURL, dataStoreUser, dataStorePassword, dataStoreTestQuery: String? - let dataStoreLogFile: String? - let dataStoreInitConns, dataStoreMaxConns, dataStoreConnUsageLimit: Int? - let dataStoreLogLevel: String? - let maxURLLength: Int? - let mailHost, mailHostOverride: String? - let log: Int? - let logLocation, logMaxSize: String? - let dataLog: Int? - let dataLogLocation, dataLogMaxSize, removePageCache, removeTemplateCache: String? - let fileTransferFolder: String? - let lookInContext, adminGroupID: Int? - let betaServer: Bool? - - enum CodingKeys: String, CodingKey { - case configGlossaryInstallationAt - case configGlossaryAdminEmail - case configGlossaryPoweredBy - case configGlossaryPoweredByIcon - case configGlossaryStaticPath - case templateProcessorClass, templateLoaderClass, templatePath, templateOverridePath, defaultListTemplate, defaultFileTemplate, useJSP, jspListTemplate, jspFileTemplate, cachePackageTagsTrack, cachePackageTagsStore, cachePackageTagsRefresh, cacheTemplatesTrack, cacheTemplatesStore, cacheTemplatesRefresh, cachePagesTrack, cachePagesStore, cachePagesRefresh, cachePagesDirtyRead, searchEngineListTemplate, searchEngineFileTemplate - case searchEngineRobotsDB - case useDataStore, dataStoreClass, redirectionClass, dataStoreName, dataStoreDriver - case dataStoreURL - case dataStoreUser, dataStorePassword, dataStoreTestQuery, dataStoreLogFile, dataStoreInitConns, dataStoreMaxConns, dataStoreConnUsageLimit, dataStoreLogLevel - case maxURLLength - case mailHost, mailHostOverride, log, logLocation, logMaxSize, dataLog, dataLogLocation, dataLogMaxSize, removePageCache, removeTemplateCache, fileTransferFolder, lookInContext, adminGroupID, betaServer - } - } - - struct ServletMapping: Codable, Equatable { - let cofaxCDS, cofaxEmail, cofaxAdmin, fileServlet: String - let cofaxTools: String - } - - struct Taglib: Codable, Equatable { - let taglibURI, taglibLocation: String - - enum CodingKeys: String, CodingKey { - case taglibURI = "taglib-uri" - case taglibLocation = "taglib-location" - } - } - } -} - -extension JSONPass { - struct Test5: Codable, Equatable { - let image: Image - - enum CodingKeys: String, CodingKey { - case image = "Image" - } - - struct Image: Codable, Equatable { - let width, height: Int - let title: String - let thumbnail: Thumbnail - let ids: [Int] - - enum CodingKeys: String, CodingKey { - case width = "Width" - case height = "Height" - case title = "Title" - case thumbnail = "Thumbnail" - case ids = "IDs" - } - } - - struct Thumbnail: Codable, Equatable { - let url: String - let height: Int - let width: String - - enum CodingKeys: String, CodingKey { - case url = "Url" - case height = "Height" - case width = "Width" - } - } - } -} - -extension JSONPass { - typealias Test6 = [Test6Element] - - struct Test6Element: Codable, Equatable { - let precision: String - let latitude, longitude: Double - let address, city, state, zip: String - let country: String - - enum CodingKeys: String, CodingKey { - case precision - case latitude = "Latitude" - case longitude = "Longitude" - case address = "Address" - case city = "City" - case state = "State" - case zip = "Zip" - case country = "Country" - } - - static func == (lhs: Self, rhs: Self) -> Bool { - guard lhs.precision == rhs.precision, lhs.address == rhs.address, lhs.city == rhs.city, lhs.zip == rhs.zip, lhs.country == rhs.country else { - return false - } - guard fabs(lhs.longitude - rhs.longitude) <= 1e-10 else { - return false - } - guard fabs(lhs.latitude - rhs.latitude) <= 1e-10 else { - return false - } - return true - } - } -} - -extension JSONPass { - struct Test7: Codable, Equatable { - let menu: Menu - - struct Menu: Codable, Equatable { - let header: String - let items: [Item] - } - - struct Item: Codable, Equatable { - let id: String - let label: String? - } - } -} - -extension JSONPass { - typealias Test8 = [[[[[[[[[[[[[[[[[[[String]]]]]]]]]]]]]]]]]]] -} - -extension JSONPass { - struct Test9: Codable, Equatable { - let objects : [AnyHashable] - - init(from decoder: Decoder) throws { - var container = try decoder.unkeyedContainer() - var decodedObjects = [AnyHashable]() - - decodedObjects.append(try container.decode(String.self)) - decodedObjects.append(try container.decode([String:[String]].self)) - decodedObjects.append(try container.decode([String:String].self)) - decodedObjects.append(try container.decode([String].self)) - decodedObjects.append(try container.decode(Int.self)) - decodedObjects.append(try container.decode(Bool.self)) - decodedObjects.append(try container.decode(Bool.self)) - if try container.decodeNil() { - decodedObjects.append("") - } - decodedObjects.append(try container.decode(SpecialCases.self)) - decodedObjects.append(try container.decode(Float.self)) - decodedObjects.append(try container.decode(Float.self)) - decodedObjects.append(try container.decode(Float.self)) - decodedObjects.append(try container.decode(Int.self)) - decodedObjects.append(try container.decode(Double.self)) - decodedObjects.append(try container.decode(Double.self)) - decodedObjects.append(try container.decode(Double.self)) - decodedObjects.append(try container.decode(Double.self)) - decodedObjects.append(try container.decode(Double.self)) - decodedObjects.append(try container.decode(Double.self)) - decodedObjects.append(try container.decode(String.self)) - - self.objects = decodedObjects - } - - func encode(to encoder: Encoder) throws { - var container = encoder.unkeyedContainer() - - try container.encode(objects[ 0] as! String) - try container.encode(objects[ 1] as! [String:[String]]) - try container.encode(objects[ 2] as! [String:String]) - try container.encode(objects[ 3] as! [String]) - try container.encode(objects[ 4] as! Int) - try container.encode(objects[ 5] as! Bool) - try container.encode(objects[ 6] as! Bool) - try container.encodeNil() - try container.encode(objects[ 8] as! SpecialCases) - try container.encode(objects[ 9] as! Float) - try container.encode(objects[10] as! Float) - try container.encode(objects[11] as! Float) - try container.encode(objects[12] as! Int) - try container.encode(objects[13] as! Double) - try container.encode(objects[14] as! Double) - try container.encode(objects[15] as! Double) - try container.encode(objects[16] as! Double) - try container.encode(objects[17] as! Double) - try container.encode(objects[18] as! Double) - try container.encode(objects[19] as! String) - } - - struct SpecialCases : Codable, Hashable { - let integer : UInt64 - let real : Double - let e : Double - let E : Double - let empty_key : Double - let zero : UInt8 - let one : UInt8 - let space : String - let quote : String - let backslash : String - let controls : String - let slash : String - let alpha : String - let ALPHA : String - let digit : String - let _0123456789 : String - let special : String - let hex: String - let `true` : Bool - let `false` : Bool - let null : Bool? - let array : [String] - let object : [String:String] - let address : String - let url : URL - let comment : String - let special_sequences_key : String - let spaced : [Int] - let compact : [Int] - let jsontext : String - let quotes : String - let escapedKey : String - - enum CodingKeys: String, CodingKey { - case integer - case real - case e - case E - case empty_key = "" - case zero - case one - case space - case quote - case backslash - case controls - case slash - case alpha - case ALPHA - case digit - case _0123456789 = "0123456789" - case special - case hex - case `true` - case `false` - case null - case array - case object - case address - case url - case comment - case special_sequences_key = "# -- --> */" - case spaced = " s p a c e d " - case compact - case jsontext - case quotes - case escapedKey = "/\\\"\u{CAFE}\u{BABE}\u{AB98}\u{FCDE}\u{bcda}\u{ef4A}\u{08}\u{0C}\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" - } - } - } -} - -extension JSONPass { - typealias Test10 = [String:[String:String]] - typealias Test11 = [String:String] -} - -extension JSONPass { - struct Test12: Codable, Equatable { - let query: Query - - struct Query: Codable, Equatable { - let pages: Pages - } - - struct Pages: Codable, Equatable { - let the80348: The80348 - - enum CodingKeys: String, CodingKey { - case the80348 = "80348" - } - } - - struct The80348: Codable, Equatable { - let pageid, ns: Int - let title: String - let langlinks: [Langlink] - } - - struct Langlink: Codable, Equatable { - let lang, asterisk: String - - enum CodingKeys: String, CodingKey { - case lang - case asterisk = "*" - } - } - } -} - -extension JSONPass { - typealias Test13 = [String:Int] - typealias Test14 = [String:[String:[String:String]]] -} - -extension JSONPass { - struct Test15: Codable, Equatable { - let attached: Bool - let klass: String - let errors: [String:[String]] - let gid: Int - let id: ID - let mpid, name: String - let properties: Properties - let state: State - let type: String - let version: Int - - enum CodingKeys: String, CodingKey { - case attached - case klass = "class" - case errors, gid, id, mpid, name, properties, state, type, version - } - - struct ID: Codable, Equatable { - let klass: String - let inc: Int - let machine: Int - let new: Bool - let time: UInt64 - let timeSecond: UInt64 - - enum CodingKeys: String, CodingKey { - case klass = "class" - case inc, machine, new, time, timeSecond - } - } - - class Properties: Codable, Equatable { - let mpid, type: String - let dbo: DBO? - let gid: Int - let name: String? - let state: State? - let apiTimestamp: String? - let gatewayTimestamp: String? - let eventData: [String:Float]? - - static func == (lhs: Properties, rhs: Properties) -> Bool { - return lhs.mpid == rhs.mpid && lhs.type == rhs.type && lhs.dbo == rhs.dbo && lhs.gid == rhs.gid && lhs.name == rhs.name && lhs.state == rhs.state && lhs.apiTimestamp == rhs.apiTimestamp && lhs.gatewayTimestamp == rhs.gatewayTimestamp && lhs.eventData == rhs.eventData - } - } - - struct DBO: Codable, Equatable { - let id: ID - let gid: Int - let mpid: String - let name: String - let type: String - let version: Int - - enum CodingKeys: String, CodingKey { - case id = "_id" - case gid, mpid, name, type, version - } - } - - struct State: Codable, Equatable { - let apiTimestamp: String - let attached: Bool - let klass : String - let errors: [String:[String]] - let eventData: [String:Float] - let gatewayTimestamp: String - let gid: Int - let id: ID - let mpid: String - let properties: Properties - let type: String - let version: Int? - - enum CodingKeys: String, CodingKey { - case apiTimestamp, attached - case klass = "class" - case errors, eventData, gatewayTimestamp, gid, id, mpid, properties, type, version - } - } - } -} - -enum JSONFail { - typealias Test1 = String - typealias Test2 = [String] - typealias Test3 = [String:String] - typealias Test4 = [String] - typealias Test5 = [String] - typealias Test6 = [String] - typealias Test7 = [String] - typealias Test8 = [String] - typealias Test9 = [String] - typealias Test10 = [String:Bool] - typealias Test11 = [String:Int] - typealias Test12 = [String:String] - typealias Test13 = [String:Int] - typealias Test14 = [String:Int] - typealias Test15 = [String] - typealias Test16 = [String] - typealias Test17 = [String] - typealias Test18 = [String] - typealias Test19 = [String:String?] - typealias Test21 = [String:String?] - typealias Test22 = [String] - typealias Test23 = [String] - typealias Test24 = [String] - typealias Test25 = [String] - typealias Test26 = [String] - typealias Test27 = [String] - typealias Test28 = [String] - typealias Test29 = [Float] - typealias Test30 = [Float] - typealias Test31 = [Float] - typealias Test32 = [String:Bool] - typealias Test33 = [String] - typealias Test34 = [String] - typealias Test35 = [String:String] - typealias Test36 = [String:Int] - typealias Test37 = [String:Int] - typealias Test38 = [String:Float] - typealias Test39 = [String:String] - typealias Test40 = [String:String] - typealias Test41 = [String:String] -} - -enum JSON5Pass { } - -extension JSON5Pass { - struct Example : Codable, Equatable { - let unquoted: String - let singleQuotes: String - let lineBreaks: String - let hexadecimal: UInt - let leadingDecimalPoint: Double - let andTrailing: Double - let positiveSign: Int - let trailingComma: String - let andIn: [String] - let backwardsCompatible: String - } -} - -extension JSON5Pass { - struct Hex : Codable, Equatable { - let `in`: [Int] - let out: [Int] - } -} - -extension JSON5Pass { - struct Numbers : Codable, Equatable { - let a: Double - let b: Double - let c: Double - let d: Int - } -} - -extension JSON5Pass { - struct Strings : Codable, Equatable { - let Hello: String - let Hello2: String - let Hello3: String - let hex1: String - let hex2: String - } -} - -extension JSON5Pass { - struct Whitespace : Codable, Equatable { - let Hello: String - } -} - -enum JSON5Spec { } - -extension JSON5Spec { - struct NPMPackage: Codable { - let name: String - let publishConfig: PublishConfig - let `description`: String - let keywords: [String] - let version: String - let preferGlobal: Bool - let config: Config - let homepage: String - let author: String - let repository: Repository - let bugs: Bugs - let directories: [String:String] - let main, bin: String - let dependencies: [String:String] - let bundleDependencies: [String] - let devDependencies: [String:String] - let engines: [String:String] - let scripts: [String:String] - let licenses: [License] - - struct PublishConfig: Codable { - let proprietaryAttribs: Bool - - enum CodingKeys: String, CodingKey { - case proprietaryAttribs = "proprietary-attribs" - } - } - - struct Config: Codable { - let publishtest: Bool - } - - struct Repository: Codable { - let type: String - let url: String - } - - struct Bugs: Codable { - let email: String - let url: String - } - - struct License: Codable { - let type: String - let url: String - } - } -} - -extension JSON5Spec { - struct ReadmeExample: Codable { - let foo: String - let `while`: Bool - let this: String - let here: String - let hex: UInt - let half: Double - let delta: Int - let to: Double - let finally: String - let oh: [String] - } -} diff --git a/Tests/FoundationEssentialsTests/LockedStateTests.swift b/Tests/FoundationEssentialsTests/LockedStateTests.swift deleted file mode 100644 index 3b1d59c89..000000000 --- a/Tests/FoundationEssentialsTests/LockedStateTests.swift +++ /dev/null @@ -1,138 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#else -@testable import FoundationEssentials -#endif - -final class LockedStateTests : XCTestCase { - final class TestObject { - var deinitBlock: () -> Void = {} - - deinit { - deinitBlock() - } - } - - struct TestError: Error {} - - func testWithLockDoesNotExtendLifetimeOfState() { - weak var state: TestObject? - let lockedState: LockedState - - (state, lockedState) = { - let state = TestObject() - return (state, LockedState(initialState: state)) - }() - - lockedState.withLock { state in - weak var oldState = state - state = TestObject() - XCTAssertNil(oldState, "State object lifetime was extended after reassignment within body") - } - - XCTAssertNil(state, "State object lifetime was extended beyond end of call") - } - - func testWithLockExtendingLifetimeExtendsLifetimeOfStatePastReassignment() { - let lockedState = LockedState(initialState: TestObject()) - - lockedState.withLockExtendingLifetimeOfState { state in - weak var oldState = state - state = TestObject() - XCTAssertNotNil(oldState, "State object lifetime was not extended after reassignment within body") - } - } - - func testWithLockExtendingLifetimeExtendsLifetimeOfStatePastEndOfLockedScope() { - let lockedState: LockedState = { - let state = TestObject() - let lockedState = LockedState(initialState: state) - - // `withLockExtendingLifetimeOfState()` should extend the lifetime of the state until after the lock is - // released. By asserting that the lock is not held when the state object is deinit-ed, we can confirm - // that the lifetime was extended past the end of the locked scope. - state.deinitBlock = { - assertLockNotHeld(lockedState, "State object lifetime was not extended to end of locked scope") - } - - return lockedState - }() - - lockedState.withLockExtendingLifetimeOfState { state in - state = TestObject() - } - } - - func testWithLockExtendingLifetimeDoesNotExtendLifetimeOfStatePastEndOfCall() { - weak var state: TestObject? - let lockedState: LockedState - - (state, lockedState) = { - let state = TestObject() - return (state, LockedState(initialState: state)) - }() - - lockedState.withLockExtendingLifetimeOfState { state in - state = TestObject() - } - - XCTAssertNil(state, "State object lifetime was extended beyond end of call") - } - - func testWithLockExtendingLifetimeReleasesLockWhenBodyThrows() { - let lockedState = LockedState(initialState: TestObject()) - - XCTAssertThrowsError( - try lockedState.withLockExtendingLifetimeOfState { _ in - throw TestError() - }, - "The body was expected to throw an error, but it did not." - ) - - assertLockNotHeld(lockedState, "Lock was not properly released by withLockExtendingLifetimeOfState()") - } - - func testWithLockExtendingLifespanDoesExtendLifetimeOfState() { - weak var state: TestObject? - let lockedState: LockedState - - (state, lockedState) = { - let state = TestObject() - return (state, LockedState(initialState: state)) - }() - - lockedState.withLockExtendingLifetimeOfState { state in - weak var oldState = state - state = TestObject() - XCTAssertNotNil(oldState, "State object lifetime was not extended after reassignment within body") - } - - XCTAssertNil(state, "State object lifetime was extended beyond end of call") - } -} - -/// Assert that the locked state is not currently locked. -/// -/// âš ï¸ This assertion fails by crashing. If the lock is currently held, the `withLock()` call will abort the program. -private func assertLockNotHeld(_ lockedState: LockedState, _ message: @autoclosure () -> String) { - // Note: Since the assertion fails by crashing, `message` is never logged. - lockedState.withLock { _ in - // PASS - } -} diff --git a/Tests/FoundationEssentialsTests/PredicateCodableTests.swift b/Tests/FoundationEssentialsTests/PredicateCodableTests.swift deleted file mode 100644 index f5fd7311a..000000000 --- a/Tests/FoundationEssentialsTests/PredicateCodableTests.swift +++ /dev/null @@ -1,564 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2022-2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if FOUNDATION_FRAMEWORK - -fileprivate protocol PredicateCodingConfigurationProviding : EncodingConfigurationProviding, DecodingConfigurationProviding where EncodingConfiguration == PredicateCodableConfiguration, DecodingConfiguration == PredicateCodableConfiguration { - static var config: PredicateCodableConfiguration { get } -} - -extension PredicateCodingConfigurationProviding { - static var encodingConfiguration: PredicateCodableConfiguration { - Self.config - } - - static var decodingConfiguration: PredicateCodableConfiguration { - Self.config - } -} - -extension DecodingError { - fileprivate var debugDescription: String? { - switch self { - case .typeMismatch(_, let context): - return context.debugDescription - case .valueNotFound(_, let context): - return context.debugDescription - case .keyNotFound(_, let context): - return context.debugDescription - case .dataCorrupted(let context): - return context.debugDescription - default: - return nil - } - } -} - -extension PredicateExpressions { - fileprivate struct TestNonStandardExpression : PredicateExpression, Decodable { - typealias Output = Bool - - func evaluate(_ bindings: PredicateBindings) throws -> Bool { - true - } - } -} - -final class PredicateCodableTests: XCTestCase { - - struct Object : Equatable, PredicateCodableKeyPathProviding { - var a: Int - var b: String - var c: Double - var d: Int - var e: Character - var f: Bool - var g: [Int] - var h: Object2 - - static var predicateCodableKeyPaths: [String : PartialKeyPath & Sendable] { - [ - "Object.f" : \.f, - "Object.g" : \.g, - "Object.h" : \.h - ] - } - - static let example = Object(a: 1, b: "Hello", c: 2.3, d: 4, e: "J", f: true, g: [9, 1, 4], h: Object2(a: 1, b: "Foo")) - } - - struct Object2 : Equatable, PredicateCodableKeyPathProviding { - var a: Int - var b: String - - static var predicateCodableKeyPaths: [String : PartialKeyPath & Sendable] { - ["Object2.a" : \.a] - } - } - - struct MinimalConfig : PredicateCodingConfigurationProviding { - static let config = PredicateCodableConfiguration.standardConfiguration - } - - struct StandardConfig : PredicateCodingConfigurationProviding { - static let config = { - var config = PredicateCodableConfiguration.standardConfiguration - config.allowType(Object.self, identifier: "Foundation.PredicateCodableTests.Object") - config.allowKeyPath(\Object.a, identifier: "Object.a") - config.allowKeyPath(\Object.b, identifier: "Object.b") - config.allowKeyPath(\Object.c, identifier: "Object.c") - return config - }() - } - - struct ProvidedKeyPathConfig : PredicateCodingConfigurationProviding { - static let config = { - var config = PredicateCodableConfiguration.standardConfiguration - config.allowType(Object.self, identifier: "Foundation.PredicateCodableTests.Object") - config.allowKeyPathsForPropertiesProvided(by: Object.self) - return config - }() - } - - struct RecursiveProvidedKeyPathConfig : PredicateCodingConfigurationProviding { - static let config = { - var config = PredicateCodableConfiguration.standardConfiguration - config.allowType(Object.self, identifier: "Foundation.PredicateCodableTests.Object") - config.allowKeyPathsForPropertiesProvided(by: Object.self, recursive: true) - return config - }() - } - - struct EmptyConfig : PredicateCodingConfigurationProviding { - static let config = PredicateCodableConfiguration() - } - - struct UUIDConfig : PredicateCodingConfigurationProviding { - static let config = { - var config = PredicateCodableConfiguration.standardConfiguration - config.allowType(UUID.self, identifier: "Foundation.UUID") - return config - }() - } - - struct MismatchedKeyPathConfig : PredicateCodingConfigurationProviding { - static let config = { - var config = PredicateCodableConfiguration.standardConfiguration - // Intentionally provide a keypath that doesn't match the signature of the identifier/ - config.allowKeyPath(\Object.b, identifier: "Object.a") - return config - }() - } - - struct TestExpressionConfig : PredicateCodingConfigurationProviding { - static let config = { - var config = PredicateCodableConfiguration.standardConfiguration - config.allowPartialType(PredicateExpressions.TestNonStandardExpression.self, identifier: "PredicateExpressions.TestNonStandardExpression") - return config - }() - } - - @discardableResult - private func _encodeDecode< - EncodingConfigurationProvider: PredicateCodingConfigurationProviding, - DecodingConfigurationProvider: PredicateCodingConfigurationProviding, - T: CodableWithConfiguration - >( - _ value: T, - encoding encodingConfig: EncodingConfigurationProvider.Type, - decoding decodingConfig: DecodingConfigurationProvider.Type - ) throws -> T where - T.EncodingConfiguration == EncodingConfigurationProvider.EncodingConfiguration, - T.DecodingConfiguration == DecodingConfigurationProvider.DecodingConfiguration - { - let encoder = JSONEncoder() - let data = try encoder.encode(CodableConfiguration(wrappedValue: value, from: encodingConfig)) - let decoder = JSONDecoder() - return try decoder.decode(CodableConfiguration.self, from: data).wrappedValue - } - - @discardableResult - private func _encodeDecode< - ConfigurationProvider: PredicateCodingConfigurationProviding, - T: CodableWithConfiguration - >( - _ value: T, - for configuration: ConfigurationProvider.Type - ) throws -> T where - T.EncodingConfiguration == ConfigurationProvider.EncodingConfiguration, - T.DecodingConfiguration == ConfigurationProvider.DecodingConfiguration - { - try _encodeDecode(value, encoding: configuration, decoding: configuration) - } - - @discardableResult - private func _encodeDecode(_ value: T) throws -> T { - let encoder = JSONEncoder() - let data = try encoder.encode(value) - let decoder = JSONDecoder() - return try decoder.decode(T.self, from: data) - } - - func testBasicEncodeDecode() throws { - let predicate = #Predicate { - $0.a == 2 - } - - let decoded = try _encodeDecode(predicate, for: StandardConfig.self) - var object = Object.example - XCTAssertEqual(try predicate.evaluate(object), try decoded.evaluate(object)) - object.a = 2 - XCTAssertEqual(try predicate.evaluate(object), try decoded.evaluate(object)) - object.a = 3 - XCTAssertEqual(try predicate.evaluate(object), try decoded.evaluate(object)) - - XCTAssertThrowsError(try _encodeDecode(predicate, for: EmptyConfig.self)) - XCTAssertThrowsError(try _encodeDecode(predicate)) - } - - func testDisallowedKeyPath() throws { - var predicate = #Predicate { - $0.f - } - - XCTAssertThrowsError(try _encodeDecode(predicate)) - XCTAssertThrowsError(try _encodeDecode(predicate, for: StandardConfig.self)) - - predicate = #Predicate { - $0.a == 1 - } - XCTAssertThrowsError(try _encodeDecode(predicate, encoding: StandardConfig.self, decoding: MinimalConfig.self)) { - guard let decodingError = $0 as? DecodingError else { - XCTFail("Incorrect error thrown: \($0)") - return - } - XCTAssertEqual(decodingError.debugDescription, "A keypath for the 'Object.a' identifier is not in the provided allowlist") - } - } - - func testKeyPathTypeMismatch() throws { - let predicate = #Predicate { - $0.a == 2 - } - - try _encodeDecode(predicate, for: StandardConfig.self) - XCTAssertThrowsError(try _encodeDecode(predicate, encoding: StandardConfig.self, decoding: MismatchedKeyPathConfig.self)) { - guard let decodingError = $0 as? DecodingError else { - XCTFail("Incorrect error thrown: \($0)") - return - } - XCTAssertEqual(decodingError.debugDescription, "Key path '\\Object.b' (KeyPath<\(_typeName(Object.self)), Swift.String>) for identifier 'Object.a' did not match the expression's requirement for KeyPath<\(_typeName(Object.self)), Swift.Int>") - } - } - - func testDisallowedType() throws { - let uuid = UUID() - let predicate = #Predicate { obj in - uuid == uuid - } - - XCTAssertThrowsError(try _encodeDecode(predicate)) - XCTAssertThrowsError(try _encodeDecode(predicate, for: StandardConfig.self)) - XCTAssertThrowsError(try _encodeDecode(predicate, encoding: UUIDConfig.self, decoding: MinimalConfig.self)) { - XCTAssertEqual(String(describing: $0), "The 'Foundation.UUID' identifier is not in the provided allowlist (required by /PredicateExpressions.Equal/PredicateExpressions.Value)") - } - - let decoded = try _encodeDecode(predicate, for: UUIDConfig.self) - XCTAssertEqual(try decoded.evaluate(.example), try predicate.evaluate(.example)) - } - - func testProvidedProperties() throws { - var predicate = #Predicate { - $0.a == 2 - } - - XCTAssertThrowsError(try _encodeDecode(predicate, for: ProvidedKeyPathConfig.self)) - XCTAssertThrowsError(try _encodeDecode(predicate, for: RecursiveProvidedKeyPathConfig.self)) - - predicate = #Predicate { - $0.f == false - } - - var decoded = try _encodeDecode(predicate, for: ProvidedKeyPathConfig.self) - XCTAssertEqual(try decoded.evaluate(.example), try predicate.evaluate(.example)) - decoded = try _encodeDecode(predicate, for: RecursiveProvidedKeyPathConfig.self) - XCTAssertEqual(try decoded.evaluate(.example), try predicate.evaluate(.example)) - - predicate = #Predicate { - $0.h.a == 1 - } - - XCTAssertThrowsError(try _encodeDecode(predicate, for: ProvidedKeyPathConfig.self)) - decoded = try _encodeDecode(predicate, for: RecursiveProvidedKeyPathConfig.self) - XCTAssertEqual(try decoded.evaluate(.example), try predicate.evaluate(.example)) - } - - func testDefaultAllowlist() throws { - var predicate = #Predicate { - $0.isEmpty - } - var decoded = try _encodeDecode(predicate) - XCTAssertEqual(try decoded.evaluate("Hello world"), try predicate.evaluate("Hello world")) - - predicate = #Predicate { - $0.count > 2 - } - decoded = try _encodeDecode(predicate) - XCTAssertEqual(try decoded.evaluate("Hello world"), try predicate.evaluate("Hello world")) - - predicate = #Predicate { - $0.contains(/[a-z]/) - } - decoded = try _encodeDecode(predicate) - XCTAssertEqual(try decoded.evaluate("Hello world"), try predicate.evaluate("Hello world")) - - let predicate2 = #Predicate { - $0 == $0 - } - let decoded2 = try _encodeDecode(predicate2) - XCTAssertEqual(try decoded2.evaluate(.example), try predicate2.evaluate(.example)) - - - var predicate3 = #Predicate> { - $0.isEmpty - } - var decoded3 = try _encodeDecode(predicate3) - XCTAssertEqual(try decoded3.evaluate(["A", "B", "C"]), try predicate3.evaluate(["A", "B", "C"])) - - predicate3 = #Predicate> { - $0.count == 2 - } - decoded3 = try _encodeDecode(predicate3) - XCTAssertEqual(try decoded3.evaluate(["A", "B", "C"]), try predicate3.evaluate(["A", "B", "C"])) - - var predicate4 = #Predicate> { - $0.isEmpty - } - var decoded4 = try _encodeDecode(predicate4) - XCTAssertEqual(try decoded4.evaluate(["A": 1, "B": 2, "C": 3]), try predicate4.evaluate(["A": 1, "B": 2, "C": 3])) - - predicate4 = #Predicate> { - $0.count == 2 - } - decoded4 = try _encodeDecode(predicate4) - XCTAssertEqual(try decoded4.evaluate(["A": 1, "B": 2, "C": 3]), try predicate4.evaluate(["A": 1, "B": 2, "C": 3])) - - let predicate5 = #Predicate { - (0 ..< 4).contains($0) - } - let decoded5 = try _encodeDecode(predicate5) - XCTAssertEqual(try decoded5.evaluate(2), try predicate5.evaluate(2)) - } - - func testMalformedData() { - func _malformedDecode(_ json: String, config: T.Type = StandardConfig.self, reason: String, file: StaticString = #filePath, line: UInt = #line) { - let data = Data(json.utf8) - let decoder = JSONDecoder() - XCTAssertThrowsError(try decoder.decode(CodableConfiguration, T>.self, from: data), file: file, line: line) { - XCTAssertTrue(String(describing: $0).contains(reason), "Error '\($0)' did not contain reason '\(reason)'", file: file, line: line) - } - } - - // expression is not a PredicateExpression - _malformedDecode( - """ - [ - { - "variable" : [{ - "key" : 0 - }], - "expression" : 0, - "structure" : "Swift.Int" - } - ] - """, - reason: "This type of this expression is unsupported" - ) - - // conjunction is missing generic arguments - _malformedDecode( - """ - [ - { - "variable" : [{ - "key" : 0 - }], - "expression" : 0, - "structure" : "PredicateExpressions.Conjunction" - } - ] - """, - reason: "Reconstruction of 'Conjunction' with the arguments [] failed" - ) - - // conjunction's generic arguments don't match constraint requirements - _malformedDecode( - """ - [ - { - "variable" : [{ - "key" : 0 - }], - "expression" : 0, - "structure" : { - "identifier": "PredicateExpressions.Conjunction", - "args": [ - "Swift.Int", - "Swift.Int" - ] - } - } - ] - """, - reason: "Reconstruction of 'Conjunction' with the arguments [Swift.Int, Swift.Int] failed" - ) - - // expression is not a StandardPredicateExpression - _malformedDecode( - """ - [ - { - "variable" : [{ - "key" : 0 - }], - "expression" : 0, - "structure" : "PredicateExpressions.TestNonStandardExpression" - } - ] - """, - config: TestExpressionConfig.self, - reason: "This expression is unsupported by this predicate" - ) - } - - func testBasicVariadic() throws { - let predicate = #Predicate { - $0.a == 2 && $1.a == 3 - } - - let decoded = try _encodeDecode(predicate, for: StandardConfig.self) - var object = Object.example - let object2 = Object.example - XCTAssertEqual(try predicate.evaluate(object, object2), try decoded.evaluate(object, object2)) - object.a = 2 - XCTAssertEqual(try predicate.evaluate(object, object2), try decoded.evaluate(object, object2)) - object.a = 3 - XCTAssertEqual(try predicate.evaluate(object, object2), try decoded.evaluate(object, object2)) - - XCTAssertThrowsError(try _encodeDecode(predicate, for: EmptyConfig.self)) - XCTAssertThrowsError(try _encodeDecode(predicate)) - } - - func testCapturedVariadicTypes() throws { - struct A : Equatable, Codable { - init(_: repeat (each T).Type) {} - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encodeNil() - } - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - guard container.decodeNil() else { - throw DecodingError.dataCorrupted(.init(codingPath: container.codingPath, debugDescription: "Did not find encoded nil")) - } - } - } - - let a = A(String.self, Int.self) - - let predicate = #Predicate { _ in - a == a - } - - - struct CustomConfig : PredicateCodingConfigurationProviding { - static let config = { - var configuration = PredicateCodableConfiguration.standardConfiguration - configuration.allowPartialType(A< >.self, identifier: "PredicateCodableTests.A") - return configuration - }() - } - - let decoded = try _encodeDecode(predicate, for: CustomConfig.self) - XCTAssertEqual(try decoded.evaluate(2), try predicate.evaluate(2)) - } - - func testNestedPredicates() throws { - let predicateA = #Predicate { - $0.a == 3 - } - - let predicateB = #Predicate { - predicateA.evaluate($0) && $0.a > 2 - } - - let decoded = try _encodeDecode(predicateB, for: StandardConfig.self) - - let objects = [ - Object(a: 3, b: "abc", c: 0.0, d: 0, e: "c", f: true, g: [1, 3], h: Object2(a: 1, b: "Foo")), - Object(a: 2, b: "abc", c: 0.0, d: 0, e: "c", f: true, g: [1, 3], h: Object2(a: 1, b: "Foo")), - Object(a: 3, b: "abc", c: 0.0, d: 0, e: "c", f: true, g: [1, 3], h: Object2(a: 1, b: "Foo")), - Object(a: 2, b: "abc", c: 0.0, d: 0, e: "c", f: true, g: [1, 3], h: Object2(a: 1, b: "Foo")), - Object(a: 4, b: "abc", c: 0.0, d: 0, e: "c", f: true, g: [1, 3], h: Object2(a: 1, b: "Foo")) - ] - - for object in objects { - XCTAssertEqual(try decoded.evaluate(object), try predicateB.evaluate(object), "Evaluation failed to produce equal results for \(object)") - } - } - - func testNestedPredicateRestrictedConfiguration() throws { - struct RestrictedBox : Codable { - let predicate: Predicate - - func encode(to encoder: any Encoder) throws { - var container = encoder.unkeyedContainer() - // Restricted empty configuration - try container.encode(predicate, configuration: PredicateCodableConfiguration()) - } - - init(_ predicate: Predicate) { - self.predicate = predicate - } - - init(from decoder: any Decoder) throws { - var container = try decoder.unkeyedContainer() - self.predicate = try container.decode(Predicate.self, configuration: PredicateCodableConfiguration()) - } - } - - let predicateA = #Predicate { - $0.a == 3 - } - let box = RestrictedBox(predicateA) - - let predicateB = #Predicate { - box.predicate.evaluate($0) && $0.a > 2 - } - - struct CustomConfig : PredicateCodingConfigurationProviding { - static let config = { - var configuration = PredicateCodableConfiguration.standardConfiguration - configuration.allowKeyPathsForPropertiesProvided(by: PredicateCodableTests.Object.self) - configuration.allowKeyPath(\RestrictedBox.predicate, identifier: "RestrictedBox.Predicate") - return configuration - }() - } - - // Throws an error because the sub-predicate's configuration won't contain anything in the allowlist - XCTAssertThrowsError(try _encodeDecode(predicateB, for: CustomConfig.self)) - } - - func testExpression() throws { - let expression = #Expression { - $0.a - } - let decoded = try _encodeDecode(expression, for: StandardConfig.self) - var object = Object.example - XCTAssertEqual(try expression.evaluate(object), try decoded.evaluate(object)) - object.a = 2 - XCTAssertEqual(try expression.evaluate(object), try decoded.evaluate(object)) - object.a = 3 - XCTAssertEqual(try expression.evaluate(object), try decoded.evaluate(object)) - - XCTAssertThrowsError(try _encodeDecode(expression, for: EmptyConfig.self)) - XCTAssertThrowsError(try _encodeDecode(expression)) - } -} - -#endif // FOUNDATION_FRAMEWORK diff --git a/Tests/FoundationEssentialsTests/PredicateConversionTests.swift b/Tests/FoundationEssentialsTests/PredicateConversionTests.swift deleted file mode 100644 index c41040edc..000000000 --- a/Tests/FoundationEssentialsTests/PredicateConversionTests.swift +++ /dev/null @@ -1,462 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2022-2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if FOUNDATION_FRAMEWORK - -final class NSPredicateConversionTests: XCTestCase { - private func convert(_ predicate: Predicate) -> NSPredicate? { - NSPredicate(predicate) - } - - private func convert(_ expression: Expression) -> NSExpression? { - NSExpression(expression) - } - - @objc class ObjCObject: NSObject { - @objc var a: Int - @objc var b: String - @objc var c: Double - @objc var d: Int - @objc var f: Bool - @objc var g: [Int] - @objc var h: [String : Int] - @objc var i: Date - @objc var j: String? - @objc var k: UUID - @objc var l: Data - @objc var m: URL - var nonObjCKeypath: Int - - override init() { - a = 1 - b = "Hello" - c = 2.3 - d = 4 - f = true - g = [5, 6, 7, 8, 9] - h = ["A" : 1, "B" : 2] - i = Date.distantFuture - j = nil - k = UUID() - l = Data([1, 2, 3]) - m = URL(string: "http://apple.com")! - nonObjCKeypath = 8 - super.init() - } - } - - struct NonObjCStruct : Codable, Sendable { - var a: Int - var b: [Int] - } - - func testBasics() { - let obj = ObjCObject() - let compareTo = 2 - var predicate = #Predicate { - $0.a == compareTo - } - var converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "a == 2")) - XCTAssertFalse(converted!.evaluate(with: obj)) - - predicate = #Predicate { - $0.a + 2 == 4 - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "a + 2 == 4")) - XCTAssertFalse(converted!.evaluate(with: obj)) - - predicate = #Predicate { - $0.b.count == 5 - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "b.length == 5")) - XCTAssertTrue(converted!.evaluate(with: obj)) - - predicate = #Predicate { - $0.g.count == 5 - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "g.@count == 5")) - XCTAssertTrue(converted!.evaluate(with: obj)) - - predicate = #Predicate { object in - object.g.filter { - $0 == object.d - }.count > 0 - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "SUBQUERY(g, $_local_1, $_local_1 == d).@count > 0")) - XCTAssertFalse(converted!.evaluate(with: obj)) - } - - func testEquality() { - var predicate = #Predicate { - $0.a == 0 - } - var converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "a == 0")) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - - predicate = #Predicate { - $0.a != 0 - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "a != 0")) - XCTAssertTrue(converted!.evaluate(with: ObjCObject())) - } - - func testRanges() { - let now = Date.now - let range = now ..< now - let closedRange = now ... now - let from = now... - let through = ...now - let upTo = .. { - ($0.i ... $0.i).contains($0.i) - } - var converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "i BETWEEN {i, i}")) - XCTAssertTrue(converted!.evaluate(with: ObjCObject())) - - // Non-closed Range Operator - predicate = #Predicate { - ($0.i ..< $0.i).contains($0.i) - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "i >= i AND i < i")) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - - // Various values - predicate = #Predicate { - range.contains($0.i) - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "i >= %@ AND i < %@", now as NSDate, now as NSDate)) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - predicate = #Predicate { - closedRange.contains($0.i) - } - converted = convert(predicate) - let other = NSPredicate(format: "i BETWEEN %@", [now, now]) - XCTAssertEqual(converted, other) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - predicate = #Predicate { - from.contains($0.i) - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "i >= %@", now as NSDate)) - XCTAssertTrue(converted!.evaluate(with: ObjCObject())) - predicate = #Predicate { - through.contains($0.i) - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "i <= %@", now as NSDate)) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - predicate = #Predicate { - upTo.contains($0.i) - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "i < %@", now as NSDate)) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - } - - func testNonObjC() { - let predicate = #Predicate { - $0.nonObjCKeypath == 2 - } - XCTAssertNil(convert(predicate)) - } - - func testNonObjCConstantKeyPath() { - let nonObjC = NonObjCStruct(a: 1, b: [1, 2, 3]) - var predicate = #Predicate { - $0.a == nonObjC.a - } - var converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "a == 1")) - XCTAssertTrue(converted!.evaluate(with: ObjCObject())) - - - predicate = #Predicate { - $0.f == nonObjC.b.contains([1, 2]) - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "f == YES")) - XCTAssertTrue(converted!.evaluate(with: ObjCObject())) - } - - func testSubscripts() { - let obj = ObjCObject() - var predicate = #Predicate { - $0.g[0] == 2 - } - var converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "(SELF.g)[0] == 2")) - XCTAssertFalse(converted!.evaluate(with: obj)) - - predicate = #Predicate { - $0.h["A"] == 1 - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "(SELF.h)['A'] == 1")) - XCTAssertTrue(converted!.evaluate(with: obj)) - } - - func testStringSearching() { - let obj = ObjCObject() - var predicate = #Predicate { - $0.b.contains("foo") - } - var converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "b CONTAINS 'foo'")) - XCTAssertFalse(converted!.evaluate(with: obj)) - - - predicate = #Predicate { - $0.b.starts(with: "foo") - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "b BEGINSWITH 'foo'")) - XCTAssertFalse(converted!.evaluate(with: obj)) - } - - func testExpressionEnforcement() { - var predicate = #Predicate { _ in - true - } - var converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "YES == YES")) - XCTAssertTrue(converted!.evaluate(with: "Hello")) - - predicate = #Predicate { _ in - false - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "NO == YES")) - XCTAssertFalse(converted!.evaluate(with: "Hello")) - - predicate = #Predicate { _ in - true && false - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "(YES == YES) && (NO == YES)")) - XCTAssertFalse(converted!.evaluate(with: "Hello")) - - predicate = #Predicate { - $0.f - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "f == YES")) - XCTAssertTrue(converted!.evaluate(with: ObjCObject())) - - predicate = #Predicate { - ($0.f && true) == false - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "TERNARY(f == YES AND YES == YES, YES, NO) == NO")) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - } - - func testConditional() { - let predicate = #Predicate { - $0.f ? true : false - } - let converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "TERNARY(f == YES, YES, NO) == YES")) - XCTAssertTrue(converted!.evaluate(with: ObjCObject())) - } - - func testOptionals() { - var predicate = #Predicate { - ($0.j ?? "").isEmpty - } - var converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "TERNARY(j != NULL, j, '').length == 0")) - XCTAssertTrue(converted!.evaluate(with: ObjCObject())) - - predicate = #Predicate { - ($0.j?.count ?? -1) > 1 - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "TERNARY(TERNARY(j != nil, j.length, nil) != nil, TERNARY(j != nil, j.length, nil), 1 * -1) > 1")) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - - predicate = #Predicate { - $0.j == nil - } - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "j == nil")) - XCTAssertTrue(converted!.evaluate(with: ObjCObject())) - } - - func testUUID() { - let obj = ObjCObject() - let uuid = obj.k - let predicate = #Predicate { - $0.k == uuid - } - - let converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "k == %@", uuid as NSUUID)) - XCTAssertTrue(converted!.evaluate(with: obj)) - let obj2 = ObjCObject() - XCTAssertNotEqual(obj2.k, uuid) - XCTAssertFalse(converted!.evaluate(with: obj2)) - } - - func testDate() { - let now = Date.now - let predicate = #Predicate { - $0.i > now - } - - let converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "i > %@", now as NSDate)) - XCTAssertTrue(converted!.evaluate(with: ObjCObject())) - } - - func testData() { - let data = Data([1, 2, 3]) - let predicate = #Predicate { - $0.l == data - } - let converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "l == %@", data as NSData)) - XCTAssertTrue(converted!.evaluate(with: ObjCObject())) - } - - func testURL() { - let url = URL(string: "http://apple.com")! - let predicate = #Predicate { - $0.m == url - } - let converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "m == %@", url as NSURL)) - XCTAssertTrue(converted!.evaluate(with: ObjCObject())) - } - - func testSequenceContainsWhere() { - let predicate = #Predicate { - $0.g.contains { $0 == 2 } - } - let converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "SUBQUERY(g, $_local_1, $_local_1 == 2).@count != 0")) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - } - - func testSequenceAllSatisfy() { - let predicate = #Predicate { - $0.g.allSatisfy { $0 == 2 } - } - let converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "SUBQUERY(g, $_local_1, NOT ($_local_1 == 2)).@count == 0")) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - } - - func testMaxMin() { - let predicate = #Predicate { - $0.g.max() == $0.g.min() - } - - let converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "g.@max.#self == g.@min.#self")) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - } - - func testStringComparison() { - let equal = ComparisonResult.orderedSame - var predicate = #Predicate { - $0.b.caseInsensitiveCompare("ABC") == equal - } - - var converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "TERNARY(b ==[c] 'ABC', 0, TERNARY(b <[c] 'ABC', -1, 1)) == 0")) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - - predicate = #Predicate { - $0.b.localizedCompare("ABC") == equal - } - - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "TERNARY(b ==[l] 'ABC', 0, TERNARY(b <[l] 'ABC', -1, 1)) == 0")) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - - predicate = #Predicate { - $0.b.localizedStandardContains("ABC") - } - - converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "b CONTAINS[cdl] 'ABC'")) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - } - - func testNested() { - let predicateA = Predicate { - PredicateExpressions.build_Equal( - lhs: PredicateExpressions.build_KeyPath( - root: PredicateExpressions.build_Arg($0), - keyPath: \.a - ), - rhs: PredicateExpressions.build_Arg(3) - ) - } - - let predicateB = Predicate { - PredicateExpressions.build_Conjunction( - lhs: PredicateExpressions.build_evaluate( - PredicateExpressions.build_Arg(predicateA), - PredicateExpressions.build_Arg($0) - ), - rhs: PredicateExpressions.build_Comparison( - lhs: PredicateExpressions.build_KeyPath( - root: PredicateExpressions.build_Arg($0), - keyPath: \.a - ), - rhs: PredicateExpressions.build_Arg(2), - op: .greaterThan - ) - ) - } - - let converted = convert(predicateB) - XCTAssertEqual(converted, NSPredicate(format: "a == 3 AND a > 2")) - XCTAssertFalse(converted!.evaluate(with: ObjCObject())) - } - - func testRegex() { - let regex = #/[e-f][l-m]/# - let predicate = #Predicate { - $0.b.contains(regex) - } - let converted = convert(predicate) - XCTAssertEqual(converted, NSPredicate(format: "b MATCHES '.*[e-f][l-m].*'")) - XCTAssertTrue(converted!.evaluate(with: ObjCObject())) - } - - func testExpression() { - let expression = #Expression { - $0.a - } - let converted = convert(expression) - XCTAssertEqual(converted, NSExpression(format: "a")) - let obj = ObjCObject() - let value = converted!.expressionValue(with: obj, context: nil) - XCTAssertEqual(value as? Int, obj.a, "Expression produced \(String(describing: value)) instead of \(obj.a)") - } -} - -#endif diff --git a/Tests/FoundationEssentialsTests/PredicateTests.swift b/Tests/FoundationEssentialsTests/PredicateTests.swift deleted file mode 100644 index 04f963508..000000000 --- a/Tests/FoundationEssentialsTests/PredicateTests.swift +++ /dev/null @@ -1,448 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2022-2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(RegexBuilder) -import RegexBuilder -#endif - -#if !FOUNDATION_FRAMEWORK -// Resolve ambiguity between Foundation.#Predicate and FoundationEssentials.#Predicate -@freestanding(expression) -@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *) -macro Predicate(_ body: (repeat each Input) -> Bool) -> Predicate = #externalMacro(module: "FoundationMacros", type: "PredicateMacro") -@freestanding(expression) -@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *) -macro Expression(_ body: (repeat each Input) -> Output) -> Expression = #externalMacro(module: "FoundationMacros", type: "ExpressionMacro") -#endif - -// Work around an issue issue on older Swift compilers -#if compiler(>=6.0) - -final class PredicateTests: XCTestCase { - - override func setUp() async throws { - guard #available(macOS 14, iOS 17, tvOS 17, watchOS 10, *) else { - throw XCTSkip("This test is not available on this OS version") - } - } - - struct Object { - var a: Int - var b: String - var c: Double - var d: Int - var e: Character - var f: Bool - var g: [Int] - var h: Date = .now - var i: Any = 3 - } - - struct Object2 { - var a: Bool - } - - func testBasic() throws { - let compareTo = 2 - let predicate = #Predicate { - $0.a == compareTo - } - try XCTAssertFalse(predicate.evaluate(Object(a: 1, b: "", c: 0, d: 0, e: "c", f: true, g: []))) - try XCTAssertTrue(predicate.evaluate(Object(a: 2, b: "", c: 0, d: 0, e: "c", f: true, g: []))) - } - - func testVariadic() throws { - let predicate = #Predicate { - $0.a == $1 + 1 - } - XCTAssert(try predicate.evaluate(Object(a: 3, b: "", c: 0, d: 0, e: "c", f: true, g: []), 2)) - } - - func testArithmetic() throws { - let predicate = #Predicate { - $0.a + 2 == 4 - } - XCTAssert(try predicate.evaluate(Object(a: 2, b: "", c: 0, d: 0, e: "c", f: true, g: []))) - } - - func testDivision() throws { - let predicate = #Predicate { - $0.a / 2 == 3 - } - let predicate2 = #Predicate { - $0.c / 2.1 <= 3.0 - } - XCTAssert(try predicate.evaluate(Object(a: 6, b: "", c: 0, d: 0, e: "c", f: true, g: []))) - XCTAssert(try predicate2.evaluate(Object(a: 2, b: "", c: 6.0, d: 0, e: "c", f: true, g: []))) - } - - func testBuildDivision() throws { - let predicate = #Predicate { - $0.a / 2 == 3 - } - XCTAssert(try predicate.evaluate(Object(a: 6, b: "", c: 0, d: 0, e: "c", f: true, g: []))) - } - - func testUnaryMinus() throws { - let predicate = #Predicate { - -$0.a == 17 - } - XCTAssert(try predicate.evaluate(Object(a: -17, b: "", c: 0, d: 0, e: "c", f: true, g: []))) - } - - func testCount() throws { - let predicate = #Predicate { - $0.g.count == 5 - } - XCTAssert(try predicate.evaluate(Object(a: 0, b: "", c: 0, d: 0, e: "c", f: true, g: [2, 3, 5, 7, 11]))) - } - - func testFilter() throws { - let predicate = #Predicate { object in - !object.g.filter { - $0 == object.d - }.isEmpty - } - XCTAssert(try predicate.evaluate(Object(a: 0, b: "", c: 0.0, d: 17, e: "c", f: true, g: [3, 5, 7, 11, 13, 17, 19]))) - } - - func testContains() throws { - let predicate = #Predicate { - $0.g.contains($0.a) - } - XCTAssert(try predicate.evaluate(Object(a: 13, b: "", c: 0.0, d: 0, e: "c", f: true, g: [2, 3, 5, 11, 13, 17]))) - } - - func testContainsWhere() throws { - let predicate = #Predicate { object in - object.g.contains { - $0 % object.a == 0 - } - } - XCTAssert(try predicate.evaluate(Object(a: 2, b: "", c: 0.0, d: 0, e: "c", f: true, g: [3, 5, 7, 2, 11, 13]))) - } - - func testAllSatisfy() throws { - let predicate = #Predicate { object in - object.g.allSatisfy { - $0 % object.d != 0 - } - } - XCTAssert(try predicate.evaluate(Object(a: 0, b: "", c: 0.0, d: 2, e: "c", f: true, g: [3, 5, 7, 11, 13, 17, 19]))) - } - - func testOptional() throws { - struct Wrapper { - let wrapped: T? - } - let predicate = #Predicate> { - ($0.wrapped.flatMap { $0 + 1 } ?? 7) % 2 == 1 - } - let predicate2 = #Predicate> { - $0.wrapped! == 19 - } - XCTAssert(try predicate.evaluate(Wrapper(wrapped: 4))) - XCTAssert(try predicate.evaluate(Wrapper(wrapped: nil))) - XCTAssert(try predicate2.evaluate(Wrapper(wrapped: 19))) - XCTAssertThrowsError(try predicate2.evaluate(Wrapper(wrapped: nil))) - - struct _NonCodableType : Equatable {} - let predicate3 = #Predicate> { - $0.wrapped == nil - } - XCTAssertFalse(try predicate3.evaluate(Wrapper(wrapped: _NonCodableType()))) - XCTAssertTrue(try predicate3.evaluate(Wrapper(wrapped: nil))) - } - - func testConditional() throws { - let predicate = #Predicate { - ($0 ? $1 : $2) == "if branch" - } - XCTAssert(try predicate.evaluate(true, "if branch", "else branch")) - } - - func testClosedRange() throws { - let predicate = #Predicate { - (3...5).contains($0.a) - } - let predicate2 = #Predicate { - ($0.a ... $0.d).contains(4) - } - XCTAssert(try predicate.evaluate(Object(a: 4, b: "", c: 0.0, d: 0, e: "c", f: true, g: []))) - XCTAssert(try predicate2.evaluate(Object(a: 3, b: "", c: 0.0, d: 5, e: "c", f: true, g: []))) - } - - func testRange() throws { - let predicate = #Predicate { - (3 ..< 5).contains($0.a) - } - let toMatch = 4 - let predicate2 = #Predicate { - ($0.a ..< $0.d).contains(toMatch) - } - XCTAssert(try predicate.evaluate(Object(a: 4, b: "", c: 0.0, d: 0, e: "c", f: true, g: []))) - XCTAssert(try predicate2.evaluate(Object(a: 3, b: "", c: 0.0, d: 5, e: "c", f: true, g: []))) - } - - func testRangeContains() throws { - let date = Date.distantPast - let predicate = #Predicate { - (date ..< date).contains($0.h) - } - - XCTAssertFalse(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 5, e: "c", f: true, g: []))) - } - - func testTypes() throws { - let predicate = #Predicate { - ($0.i as? Int).flatMap { $0 == 3 } ?? false - } - let predicate2 = #Predicate { - $0.i is Int - } - XCTAssert(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 0, e: "c", f: true, g: []))) - XCTAssert(try predicate2.evaluate(Object(a: 3, b: "", c: 0.0, d: 5, e: "c", f: true, g: []))) - } - - func testSubscripts() throws { - var predicate = #Predicate { - $0.g[0] == 0 - } - - XCTAssertTrue(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 0, e: "c", f: true, g: [0]))) - XCTAssertFalse(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 0, e: "c", f: true, g: [1]))) - XCTAssertThrowsError(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 0, e: "c", f: true, g: []))) - - predicate = #Predicate { - $0.g[0 ..< 2].isEmpty - } - - XCTAssertFalse(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 0, e: "c", f: true, g: [0, 1, 2]))) - XCTAssertFalse(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 0, e: "c", f: true, g: [0, 1]))) - XCTAssertThrowsError(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 0, e: "c", f: true, g: [0]))) - XCTAssertThrowsError(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 0, e: "c", f: true, g: []))) - } - - func testLazyDefaultValueSubscript() throws { - struct Foo : Codable, Sendable { - var property: Int { - fatalError("This property should not have been accessed") - } - } - - let foo = Foo() - let predicate = #Predicate<[String : Int]> { - $0["key", default: foo.property] == 1 - } - XCTAssertFalse(try predicate.evaluate(["key" : 2])) - } - - func testStaticValues() throws { - func assertPredicate(_ pred: Predicate, value: T, expected: Bool) throws { - XCTAssertEqual(try pred.evaluate(value), expected) - } - - try assertPredicate(.true, value: "Hello", expected: true) - try assertPredicate(.false, value: "Hello", expected: false) - } - - func testMaxMin() throws { - var predicate = #Predicate { - $0.g.max() == 2 - } - XCTAssertFalse(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 0, e: "c", f: true, g: [1, 3]))) - XCTAssertTrue(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 0, e: "c", f: true, g: [1, 2]))) - - predicate = #Predicate { - $0.g.min() == 2 - } - XCTAssertFalse(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 0, e: "c", f: true, g: [1, 3]))) - XCTAssertTrue(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 0, e: "c", f: true, g: [2, 3]))) - } - - #if FOUNDATION_FRAMEWORK - - func testCaseInsensitiveCompare() throws { - let equal = ComparisonResult.orderedSame - let predicate = #Predicate { - $0.b.caseInsensitiveCompare("ABC") == equal - } - XCTAssertTrue(try predicate.evaluate(Object(a: 3, b: "abc", c: 0.0, d: 0, e: "c", f: true, g: [1, 3]))) - XCTAssertFalse(try predicate.evaluate(Object(a: 3, b: "def", c: 0.0, d: 0, e: "c", f: true, g: [1, 3]))) - } - - #endif - - func testBuildDynamically() throws { - func _build(_ equal: Bool) -> Predicate { - Predicate { - if equal { - PredicateExpressions.Equal( - lhs: $0, - rhs: PredicateExpressions.Value(1) - ) - } else { - PredicateExpressions.NotEqual( - lhs: $0, - rhs: PredicateExpressions.Value(1) - ) - } - } - } - - XCTAssertTrue(try _build(true).evaluate(1)) - XCTAssertFalse(try _build(false).evaluate(1)) - } - - func testResilientKeyPaths() { - // Local, non-resilient type - struct Foo { - let a: String // Non-resilient - let b: Date // Resilient (in Foundation) - let c: String // Non-resilient - } - - let now = Date.now - let _ = #Predicate { - $0.a == $0.c && $0.b == now - } - } - - #if compiler(>=5.11) - func testRegex() throws { - guard #available(FoundationPredicateRegex 0.4, *) else { - throw XCTSkip("This test is not available on this OS version") - } - - let literalRegex = #/[AB0-9]\/?[^\n]+/# - var predicate = #Predicate { - $0.b.contains(literalRegex) - } - XCTAssertTrue(try predicate.evaluate(Object(a: 0, b: "_0/bc", c: 0, d: 0, e: " ", f: true, g: []))) - XCTAssertFalse(try predicate.evaluate(Object(a: 0, b: "_C/bc", c: 0, d: 0, e: " ", f: true, g: []))) - predicate = #Predicate { - $0.b.contains(#/[AB0-9]\/?[^\n]+/#) - } - XCTAssertTrue(try predicate.evaluate(Object(a: 0, b: "_0/bc", c: 0, d: 0, e: " ", f: true, g: []))) - XCTAssertFalse(try predicate.evaluate(Object(a: 0, b: "_C/bc", c: 0, d: 0, e: " ", f: true, g: []))) - } - - func testRegex_RegexBuilder() throws { - #if !canImport(RegexBuilder) - throw XCTSkip("RegexBuilder is unavavailable on this platform") - #elseif !os(Linux) && !os(Android) && !FOUNDATION_FRAMEWORK - // Disable this test in swift-foundation macOS CI because of incorrect availability annotations in the StringProcessing module - throw XCTSkip("This test is currently disabled on this platform") - #else - guard #available(FoundationPredicateRegex 0.4, *) else { - throw XCTSkip("This test is not available on this OS version") - } - - let builtRegex = Regex { - ChoiceOf { - "A" - "B" - CharacterClass.digit - } - Optionally("/") - OneOrMore(.anyNonNewline) - } - let predicate = #Predicate { - $0.b.contains(builtRegex) - } - XCTAssertTrue(try predicate.evaluate(Object(a: 0, b: "_0/bc", c: 0, d: 0, e: " ", f: true, g: []))) - XCTAssertFalse(try predicate.evaluate(Object(a: 0, b: "_C/bc", c: 0, d: 0, e: " ", f: true, g: []))) - #endif - } - #endif - - func testDebugDescription() throws { - guard #available(FoundationPredicate 0.3, *) else { - throw XCTSkip("This test is not available on this OS version") - } - - let date = Date.now - let predicate = #Predicate { - if let num = $0.i as? Int { - num == 3 - } else { - $0.h == date - } - } -#if FOUNDATION_FRAMEWORK - let moduleName = "Foundation" - let testModuleName = "Unit" -#else - let moduleName = "FoundationEssentials" - let testModuleName = "FoundationEssentialsTests" -#endif - XCTAssertEqual( - predicate.description, - """ - capture1 (Swift.Int): 3 - capture2 (\(moduleName).Date): - Predicate<\(testModuleName).PredicateTests.Object> { input1 in - (input1.i as? Swift.Int).flatMap({ variable1 in - variable1 == capture1 - }) ?? (input1.h == capture2) - } - """ - ) - - let debugDescription = predicate.debugDescription.replacing(#/Variable\([0-9]+\)/#, with: "Variable(#)") - XCTAssertEqual( - debugDescription, - "\(moduleName).Predicate(variable: (Variable(#)), expression: NilCoalesce(lhs: OptionalFlatMap(wrapped: ConditionalCast(input: KeyPath(root: Variable(#), keyPath: \\Object.i), desiredType: Swift.Int), variable: Variable(#), transform: Equal(lhs: Variable(#), rhs: Value(3))), rhs: Equal(lhs: KeyPath(root: Variable(#), keyPath: \\Object.h), rhs: Value<\(moduleName).Date>(\(date.debugDescription)))))" - ) - } - - #if FOUNDATION_FRAMEWORK - func testNested() throws { - guard #available(FoundationPredicate 0.3, *) else { - throw XCTSkip("This test is not available on this OS version") - } - - let predicateA = #Predicate { - $0.a == 3 - } - - let predicateB = #Predicate { - predicateA.evaluate($0) && $0.a > 2 - } - - XCTAssertTrue(try predicateA.evaluate(Object(a: 3, b: "abc", c: 0.0, d: 0, e: "c", f: true, g: [1, 3]))) - XCTAssertFalse(try predicateA.evaluate(Object(a: 2, b: "abc", c: 0.0, d: 0, e: "c", f: true, g: [1, 3]))) - XCTAssertTrue(try predicateB.evaluate(Object(a: 3, b: "abc", c: 0.0, d: 0, e: "c", f: true, g: [1, 3]))) - XCTAssertFalse(try predicateB.evaluate(Object(a: 2, b: "abc", c: 0.0, d: 0, e: "c", f: true, g: [1, 3]))) - XCTAssertFalse(try predicateB.evaluate(Object(a: 4, b: "abc", c: 0.0, d: 0, e: "c", f: true, g: [1, 3]))) - } - #endif - - func testExpression() throws { - guard #available(FoundationPredicate 0.4, *) else { - throw XCTSkip("This test is not available on this OS version") - } - - let expression = #Expression { - $0 + 1 - } - for i in 0 ..< 10 { - XCTAssertEqual(try expression.evaluate(i), i + 1) - } - } -} - -#endif // compiler(>=6.0) diff --git a/Tests/FoundationEssentialsTests/ProcessInfoTests.swift b/Tests/FoundationEssentialsTests/ProcessInfoTests.swift deleted file mode 100644 index 628c78773..000000000 --- a/Tests/FoundationEssentialsTests/ProcessInfoTests.swift +++ /dev/null @@ -1,219 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(FoundationEssentials) -@testable import FoundationEssentials -#else -@testable import Foundation -#endif - -#if canImport(Darwin) -import Darwin -#elseif canImport(Glibc) -@preconcurrency import Glibc -#endif - -/// Since we can't really mock system settings like OS name, -/// these tests simply check that the values returned are not empty -final class ProcessInfoTests : XCTestCase { - func testArguments() { - let args = ProcessInfo.processInfo.arguments - XCTAssertTrue( - !args.isEmpty,"arguments should not have been empty") - } - - func testEnvironment() { -#if os(Windows) - func setenv(_ key: String, _ value: String, _ overwrite: Int) -> Int32 { - assert(overwrite == 1) - guard !key.contains("=") else { - errno = EINVAL - return -1 - } - return _putenv("\(key)=\(value)") - } -#endif - let env = ProcessInfo.processInfo.environment - XCTAssertTrue( - !env.isEmpty, "environment should not have been empty") - - let preset = ProcessInfo.processInfo.environment["test"] - setenv("test", "worked", 1) - let postset = ProcessInfo.processInfo.environment["test"] - XCTAssertNil(preset) - XCTAssertEqual(postset, "worked") - } - - func testProcessIdentifier() { - let pid = ProcessInfo.processInfo.processIdentifier - XCTAssertEqual( - pid, getpid(), "ProcessInfo disagrees with getpid()") - } - - func testGlobalUniqueString() { - let unique = ProcessInfo.processInfo.globallyUniqueString - XCTAssertNotEqual( - unique, - ProcessInfo.processInfo.globallyUniqueString, - "globallyUniqueString should never return the same string twice") - } - - func testOperatingSystemVersionString() { - let version = ProcessInfo.processInfo.operatingSystemVersionString - XCTAssertFalse(version.isEmpty, "ProcessInfo returned empty string for operation system version") - #if os(Windows) - XCTAssertTrue(version.starts(with: "Windows"), "'\(version)' did not start with 'Windows'") - #endif - } - - func testProcessorCount() { - let count = ProcessInfo.processInfo.processorCount - XCTAssertTrue(count > 0, "ProcessInfo doesn't think we have any processors") - } - - func testActiveProcessorCount() { - let count = ProcessInfo.processInfo.activeProcessorCount - XCTAssertTrue(count > 0, "ProcessInfo doesn't think we have any active processors") - } - - func testPhysicalMemory() { - let memory = ProcessInfo.processInfo.physicalMemory - XCTAssertTrue(memory > 0, "ProcessInfo doesn't think we have any memory") - } - - func testSystemUpTime() async throws { - let now = ProcessInfo.processInfo.systemUptime - XCTAssertTrue( - now > 1, "ProcessInfo returned an unrealistically low system uptime") - // Sleep for 0.1s - try await Task.sleep(for: .milliseconds(100)) - XCTAssertTrue( - ProcessInfo.processInfo.systemUptime > now, - "ProcessInfo returned the same system uptime with 400") - - } - - func testOperatingSystemVersion() throws { - #if canImport(Darwin) - let version = ProcessInfo.processInfo.operatingSystemVersion - #if os(visionOS) - let expectedMinMajorVersion = 1 - #else - let expectedMinMajorVersion = 2 - #endif - XCTAssertGreaterThanOrEqual(version.majorVersion, expectedMinMajorVersion, "Unrealistic major system version") - #elseif os(Windows) || os(Linux) || os(Android) - let minVersion = OperatingSystemVersion(majorVersion: 1, minorVersion: 0, patchVersion: 0) - XCTAssertTrue(ProcessInfo.processInfo.isOperatingSystemAtLeast(minVersion)) - #else - throw XCTSkip("This test is not supported on this platform") - #endif - } - - func testOperatingSystemIsAtLeastVersion() throws { - #if !canImport(Darwin) - throw XCTSkip("This test is not supported on this platform") - #else - #if os(watchOS) - XCTAssertTrue(ProcessInfo.processInfo - .isOperatingSystemAtLeast( - OperatingSystemVersion(majorVersion: 1, minorVersion: 12, patchVersion: 0) - ), - "ProcessInfo thinks 1.12 is > than 2.something") - XCTAssertTrue(ProcessInfo.processInfo - .isOperatingSystemAtLeast( - OperatingSystemVersion(majorVersion: 1, minorVersion: 0, patchVersion: 0) - ), - "ProcessInfo thinks we are on watchOS 1") - #elseif os(macOS) || (os(iOS) && !os(visionOS)) - XCTAssertTrue(ProcessInfo.processInfo - .isOperatingSystemAtLeast( - OperatingSystemVersion(majorVersion: 6, minorVersion: 12, patchVersion: 0) - ), - "ProcessInfo thinks 6.12 is > than 10.something") - XCTAssertTrue(ProcessInfo.processInfo - .isOperatingSystemAtLeast( - OperatingSystemVersion(majorVersion: 6, minorVersion: 0, patchVersion: 0) - ), - "ProcessInfo thinks we are on System 5") - #endif - XCTAssertFalse(ProcessInfo.processInfo - .isOperatingSystemAtLeast( - OperatingSystemVersion(majorVersion: 70, minorVersion: 0, patchVersion: 0) - ), - "ProcessInfo thinks we are on System 70") - #endif - } - -#if os(macOS) - func testUserName() { - XCTAssertFalse(ProcessInfo.processInfo.userName.isEmpty) - } - - func testFullUserName() { - XCTAssertFalse(ProcessInfo.processInfo.fullUserName.isEmpty) - } -#endif - - func testProcessName() { -#if FOUNDATION_FRAMEWORK - let targetName = "TestHost" -#elseif os(Linux) || os(Windows) || os(Android) || os(FreeBSD) - let targetName = "swift-foundationPackageTests.xctest" -#else - let targetName = "xctest" -#endif - let processInfo = ProcessInfo.processInfo - let originalProcessName = processInfo.processName - XCTAssertEqual(originalProcessName, targetName) - - // Try assigning a new process name. - let newProcessName = "TestProcessName" - processInfo.processName = newProcessName - XCTAssertEqual(processInfo.processName, newProcessName) - - // Assign back to the original process name. - processInfo.processName = originalProcessName - XCTAssertEqual(processInfo.processName, originalProcessName) - } - - func testWindowsEnvironmentDoesNotContainMagicValues() { - // Windows GetEnvironmentStringsW API can return - // magic environment variables set by the cmd shell - // that starts with `=` - // This test makes sure we don't include these - // magic variables - let env = ProcessInfo.processInfo.environment - XCTAssertNil(env[""]) - } -} - -// MARK: - ThermalState and PowerState tests -#if FOUNDATION_FRAMEWORK -extension ProcessInfoTests { - func testThermalPowerState() { - // This test simply makes sure we can deliver the correct - // thermal and power state for all platforms. - // Fake a new value - _NSSwiftProcessInfo._globalState.withLock { - $0.thermalState = .critical - $0.powerState = .restricted - } - XCTAssertEqual(ProcessInfo.processInfo.thermalState, .critical) - XCTAssertEqual(ProcessInfo.processInfo.isLowPowerModeEnabled, true) - } -} -#endif // FOUDATION_FRAMEWORK diff --git a/Tests/FoundationEssentialsTests/PropertyListEncoderTests.swift b/Tests/FoundationEssentialsTests/PropertyListEncoderTests.swift deleted file mode 100644 index cd8336bd0..000000000 --- a/Tests/FoundationEssentialsTests/PropertyListEncoderTests.swift +++ /dev/null @@ -1,2099 +0,0 @@ -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#elseif canImport(FoundationEssentials) -@testable import FoundationEssentials -#endif - -// MARK: - Test Suite - -class TestPropertyListEncoder : XCTestCase { - // MARK: - Encoding Top-Level Empty Types -#if FIXED_64141381 - func testEncodingTopLevelEmptyStruct() { - let empty = EmptyStruct() - _testRoundTrip(of: empty, in: .binary, expectedPlist: _plistEmptyDictionaryBinary) - _testRoundTrip(of: empty, in: .xml, expectedPlist: _plistEmptyDictionaryXML) - } - - func testEncodingTopLevelEmptyClass() { - let empty = EmptyClass() - _testRoundTrip(of: empty, in: .binary, expectedPlist: _plistEmptyDictionaryBinary) - _testRoundTrip(of: empty, in: .xml, expectedPlist: _plistEmptyDictionaryXML) - } -#endif - - // MARK: - Encoding Top-Level Single-Value Types - func testEncodingTopLevelSingleValueEnum() { - let s1 = Switch.off - _testEncodeFailure(of: s1, in: .binary) - _testEncodeFailure(of: s1, in: .xml) - _testRoundTrip(of: TopLevelWrapper(s1), in: .binary) - _testRoundTrip(of: TopLevelWrapper(s1), in: .xml) - - let s2 = Switch.on - _testEncodeFailure(of: s2, in: .binary) - _testEncodeFailure(of: s2, in: .xml) - _testRoundTrip(of: TopLevelWrapper(s2), in: .binary) - _testRoundTrip(of: TopLevelWrapper(s2), in: .xml) - } - - func testEncodingTopLevelSingleValueStruct() { - let t = Timestamp(3141592653) - _testEncodeFailure(of: t, in: .binary) - _testEncodeFailure(of: t, in: .xml) - _testRoundTrip(of: TopLevelWrapper(t), in: .binary) - _testRoundTrip(of: TopLevelWrapper(t), in: .xml) - } - - func testEncodingTopLevelSingleValueClass() { - let c = Counter() - _testEncodeFailure(of: c, in: .binary) - _testEncodeFailure(of: c, in: .xml) - _testRoundTrip(of: TopLevelWrapper(c), in: .binary) - _testRoundTrip(of: TopLevelWrapper(c), in: .xml) - } - - // MARK: - Encoding Top-Level Structured Types - func testEncodingTopLevelStructuredStruct() { - // Address is a struct type with multiple fields. - let address = Address.testValue - _testRoundTrip(of: address, in: .binary) - _testRoundTrip(of: address, in: .xml) - } - - func testEncodingTopLevelStructuredClass() { - // Person is a class with multiple fields. - let person = Person.testValue - _testRoundTrip(of: person, in: .binary) - _testRoundTrip(of: person, in: .xml) - } - - func testEncodingTopLevelStructuredSingleStruct() { - // Numbers is a struct which encodes as an array through a single value container. - let numbers = Numbers.testValue - _testRoundTrip(of: numbers, in: .binary) - _testRoundTrip(of: numbers, in: .xml) - } - - func testEncodingTopLevelStructuredSingleClass() { - // Mapping is a class which encodes as a dictionary through a single value container. - let mapping = Mapping.testValue - _testRoundTrip(of: mapping, in: .binary) - _testRoundTrip(of: mapping, in: .xml) - } - - func testEncodingTopLevelDeepStructuredType() { - // Company is a type with fields which are Codable themselves. - let company = Company.testValue - _testRoundTrip(of: company, in: .binary) - _testRoundTrip(of: company, in: .xml) - } - - func testEncodingClassWhichSharesEncoderWithSuper() { - // Employee is a type which shares its encoder & decoder with its superclass, Person. - let employee = Employee.testValue - _testRoundTrip(of: employee, in: .binary) - _testRoundTrip(of: employee, in: .xml) - } - - func testEncodingTopLevelNullableType() { - // EnhancedBool is a type which encodes either as a Bool or as nil. - _testEncodeFailure(of: EnhancedBool.true, in: .binary) - _testEncodeFailure(of: EnhancedBool.true, in: .xml) - _testEncodeFailure(of: EnhancedBool.false, in: .binary) - _testEncodeFailure(of: EnhancedBool.false, in: .xml) - _testEncodeFailure(of: EnhancedBool.fileNotFound, in: .binary) - _testEncodeFailure(of: EnhancedBool.fileNotFound, in: .xml) - - _testRoundTrip(of: TopLevelWrapper(EnhancedBool.true), in: .binary) - _testRoundTrip(of: TopLevelWrapper(EnhancedBool.true), in: .xml) - _testRoundTrip(of: TopLevelWrapper(EnhancedBool.false), in: .binary) - _testRoundTrip(of: TopLevelWrapper(EnhancedBool.false), in: .xml) - _testRoundTrip(of: TopLevelWrapper(EnhancedBool.fileNotFound), in: .binary) - _testRoundTrip(of: TopLevelWrapper(EnhancedBool.fileNotFound), in: .xml) - } - - func testEncodingTopLevelWithConfiguration() throws { - // CodableTypeWithConfiguration is a struct that conforms to CodableWithConfiguration - let value = CodableTypeWithConfiguration.testValue - let encoder = PropertyListEncoder() - let decoder = PropertyListDecoder() - - var decoded = try decoder.decode(CodableTypeWithConfiguration.self, from: try encoder.encode(value, configuration: .init(1)), configuration: .init(1)) - XCTAssertEqual(decoded, value) - decoded = try decoder.decode(CodableTypeWithConfiguration.self, from: try encoder.encode(value, configuration: CodableTypeWithConfiguration.ConfigProviding.self), configuration: CodableTypeWithConfiguration.ConfigProviding.self) - XCTAssertEqual(decoded, value) - } - -#if FIXED_64141381 - func testEncodingMultipleNestedContainersWithTheSameTopLevelKey() { - struct Model : Codable, Equatable { - let first: String - let second: String - - init(from coder: Decoder) throws { - let container = try coder.container(keyedBy: TopLevelCodingKeys.self) - - let firstNestedContainer = try container.nestedContainer(keyedBy: FirstNestedCodingKeys.self, forKey: .top) - self.first = try firstNestedContainer.decode(String.self, forKey: .first) - - let secondNestedContainer = try container.nestedContainer(keyedBy: SecondNestedCodingKeys.self, forKey: .top) - self.second = try secondNestedContainer.decode(String.self, forKey: .second) - } - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: TopLevelCodingKeys.self) - - var firstNestedContainer = container.nestedContainer(keyedBy: FirstNestedCodingKeys.self, forKey: .top) - try firstNestedContainer.encode(self.first, forKey: .first) - - var secondNestedContainer = container.nestedContainer(keyedBy: SecondNestedCodingKeys.self, forKey: .top) - try secondNestedContainer.encode(self.second, forKey: .second) - } - - init(first: String, second: String) { - self.first = first - self.second = second - } - - static var testValue: Model { - return Model(first: "Johnny Appleseed", - second: "appleseed@apple.com") - } - enum TopLevelCodingKeys : String, CodingKey { - case top - } - - enum FirstNestedCodingKeys : String, CodingKey { - case first - } - enum SecondNestedCodingKeys : String, CodingKey { - case second - } - } - - let model = Model.testValue - let expectedXML = "\n\n\n\n\ttop\n\t\n\t\tfirst\n\t\tJohnny Appleseed\n\t\tsecond\n\t\tappleseed@apple.com\n\t\n\n\n".data(using: String._Encoding.utf8)! - _testRoundTrip(of: model, in: .xml, expectedPlist: expectedXML) - } -#endif - -#if false // FIXME: XCTest doesn't support crash tests yet rdar://20195010&22387653 - func testEncodingConflictedTypeNestedContainersWithTheSameTopLevelKey() { - struct Model : Encodable, Equatable { - let first: String - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: TopLevelCodingKeys.self) - - var firstNestedContainer = container.nestedContainer(keyedBy: FirstNestedCodingKeys.self, forKey: .top) - try firstNestedContainer.encode(self.first, forKey: .first) - - // The following line would fail as it attempts to re-encode into already encoded container is invalid. This will always fail - var secondNestedContainer = container.nestedUnkeyedContainer(forKey: .top) - try secondNestedContainer.encode("second") - } - - init(first: String) { - self.first = first - } - - static var testValue: Model { - return Model(first: "Johnny Appleseed") - } - enum TopLevelCodingKeys : String, CodingKey { - case top - } - - enum FirstNestedCodingKeys : String, CodingKey { - case first - } - } - - let model = Model.testValue - // This following test would fail as it attempts to re-encode into already encoded container is invalid. This will always fail - expectCrashLater() - _testEncodeFailure(of: model, in: .xml) - } -#endif - - // MARK: - Encoder Features - func testNestedContainerCodingPaths() { - let encoder = PropertyListEncoder() - do { - let _ = try encoder.encode(NestedContainersTestType()) - } catch let error as NSError { - XCTFail("Caught error during encoding nested container types: \(error)") - } - } - - func testSuperEncoderCodingPaths() { - let encoder = PropertyListEncoder() - do { - let _ = try encoder.encode(NestedContainersTestType(testSuperEncoder: true)) - } catch let error as NSError { - XCTFail("Caught error during encoding nested container types: \(error)") - } - } - -#if FOUNDATION_FRAMEWORK - // requires PropertyListSerialization, JSONSerialization - - func testEncodingTopLevelData() { - let data = try! JSONSerialization.data(withJSONObject: [String](), options: []) - _testRoundTrip(of: data, in: .binary, expectedPlist: try! PropertyListSerialization.data(fromPropertyList: data, format: .binary, options: 0)) - _testRoundTrip(of: data, in: .xml, expectedPlist: try! PropertyListSerialization.data(fromPropertyList: data, format: .xml, options: 0)) - } - - func testInterceptData() { - let data = try! JSONSerialization.data(withJSONObject: [String](), options: []) - let topLevel = TopLevelWrapper(data) - let plist = ["value": data] - _testRoundTrip(of: topLevel, in: .binary, expectedPlist: try! PropertyListSerialization.data(fromPropertyList: plist, format: .binary, options: 0)) - _testRoundTrip(of: topLevel, in: .xml, expectedPlist: try! PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0)) - } - - func testInterceptDate() { - let date = Date(timeIntervalSinceReferenceDate: 0) - let topLevel = TopLevelWrapper(date) - let plist = ["value": date] - _testRoundTrip(of: topLevel, in: .binary, expectedPlist: try! PropertyListSerialization.data(fromPropertyList: plist, format: .binary, options: 0)) - _testRoundTrip(of: topLevel, in: .xml, expectedPlist: try! PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0)) - } -#endif // FOUNDATION_FRaMEWORK - - // MARK: - Type coercion - func testTypeCoercion() { - func _testRoundTripTypeCoercionFailure(of value: T, as type: U.Type) where T : Codable, U : Codable { - let encoder = PropertyListEncoder() - - encoder.outputFormat = .xml - let xmlData = try! encoder.encode(value) - XCTAssertThrowsError(try PropertyListDecoder().decode(U.self, from: xmlData), "Coercion from \(T.self) to \(U.self) was expected to fail.") - - encoder.outputFormat = .binary - let binaryData = try! encoder.encode(value) - XCTAssertThrowsError(try PropertyListDecoder().decode(U.self, from: binaryData), "Coercion from \(T.self) to \(U.self) was expected to fail.") - } - - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Int].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Int8].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Int16].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Int32].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Int64].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [UInt].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [UInt8].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [UInt16].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [UInt32].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [UInt64].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Float].self) - _testRoundTripTypeCoercionFailure(of: [false, true], as: [Double].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [Int], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [Int8], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [Int16], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [Int32], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [Int64], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [UInt], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [UInt8], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [UInt16], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [UInt32], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0, 1] as [UInt64], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0.0, 1.0] as [Float], as: [Bool].self) - _testRoundTripTypeCoercionFailure(of: [0.0, 1.0] as [Double], as: [Bool].self) - - // Real -> Integer coercions that are impossible. - _testRoundTripTypeCoercionFailure(of: [256] as [Double], as: [UInt8].self) - _testRoundTripTypeCoercionFailure(of: [-129] as [Double], as: [Int8].self) - _testRoundTripTypeCoercionFailure(of: [-1.0] as [Double], as: [UInt64].self) - _testRoundTripTypeCoercionFailure(of: [3.14159] as [Double], as: [UInt64].self) - _testRoundTripTypeCoercionFailure(of: [.infinity] as [Double], as: [UInt64].self) - _testRoundTripTypeCoercionFailure(of: [.nan] as [Double], as: [UInt64].self) - - // Especially for binary plist, ensure we maintain different encoded representations of special values like Int64(-1) and UInt64.max, which have the same 8 byte representation. - _testRoundTripTypeCoercionFailure(of: [Int64(-1)], as: [UInt64].self) - _testRoundTripTypeCoercionFailure(of: [UInt64.max], as: [Int64].self) - } - - func testIntegerRealCoercion() throws { - func _testRoundTripTypeCoercion(of value: T, expectedCoercedValue: U) throws { - let encoder = PropertyListEncoder() - - encoder.outputFormat = .xml - - let xmlData = try encoder.encode([value]) - var decoded = try PropertyListDecoder().decode([U].self, from: xmlData) - XCTAssertEqual(decoded.first!, expectedCoercedValue) - - encoder.outputFormat = .binary - let binaryData = try encoder.encode([value]) - - decoded = try PropertyListDecoder().decode([U].self, from: binaryData) - XCTAssertEqual(decoded.first!, expectedCoercedValue) - } - - try _testRoundTripTypeCoercion(of: 1 as UInt64, expectedCoercedValue: 1.0 as Double) - try _testRoundTripTypeCoercion(of: -1 as Int64, expectedCoercedValue: -1.0 as Float) - try _testRoundTripTypeCoercion(of: UInt64.max, expectedCoercedValue: Double(UInt64.max)) - try _testRoundTripTypeCoercion(of: Int64.min, expectedCoercedValue: Double(Int64.min)) - - try _testRoundTripTypeCoercion(of: 1.0 as Double, expectedCoercedValue: 1 as UInt8) - try _testRoundTripTypeCoercion(of: 1.0 as Double, expectedCoercedValue: 1 as UInt64) - try _testRoundTripTypeCoercion(of: 1.0 as Double, expectedCoercedValue: 1 as Int32) - try _testRoundTripTypeCoercion(of: -1.0 as Double, expectedCoercedValue: -1 as Int8) - try _testRoundTripTypeCoercion(of: 255.0 as Double, expectedCoercedValue: 255 as UInt8) - try _testRoundTripTypeCoercion(of: -127.0 as Double, expectedCoercedValue: -127 as Int8) - try _testRoundTripTypeCoercion(of: 2.99792458e8 as Double, expectedCoercedValue: 299792458) - } - - func testDecodingConcreteTypeParameter() { - let encoder = PropertyListEncoder() - guard let plist = try? encoder.encode(Employee.testValue) else { - XCTFail("Unable to encode Employee.") - return - } - - let decoder = PropertyListDecoder() - guard let decoded = try? decoder.decode(Employee.self as Person.Type, from: plist) else { - XCTFail("Failed to decode Employee as Person from plist.") - return - } - - expectEqual(type(of: decoded), Employee.self, "Expected decoded value to be of type Employee; got \(type(of: decoded)) instead.") - } - - // MARK: - Encoder State - // SR-6078 - func testEncoderStateThrowOnEncode() { - struct Wrapper : Encodable { - let value: T - init(_ value: T) { self.value = value } - - func encode(to encoder: Encoder) throws { - // This approximates a subclass calling into its superclass, where the superclass encodes a value that might throw. - // The key here is that getting the superEncoder creates a referencing encoder. - var container = encoder.unkeyedContainer() - let superEncoder = container.superEncoder() - - // Pushing a nested container on leaves the referencing encoder with multiple containers. - var nestedContainer = superEncoder.unkeyedContainer() - try nestedContainer.encode(value) - } - } - - struct Throwing : Encodable { - func encode(to encoder: Encoder) throws { - enum EncodingError : Error { case foo } - throw EncodingError.foo - } - } - - // The structure that would be encoded here looks like - // - // - // - // - // [throwing] - // - // - // - // - // The wrapper asks for an unkeyed container ([^]), gets a super encoder, and creates a nested container into that ([[^]]). - // We then encode an array into that ([[[^]]]), which happens to be a value that causes us to throw an error. - // - // The issue at hand reproduces when you have a referencing encoder (superEncoder() creates one) that has a container on the stack (unkeyedContainer() adds one) that encodes a value going through box_() (Array does that) that encodes something which throws (Throwing does that). - // When reproducing, this will cause a test failure via fatalError(). - _ = try? PropertyListEncoder().encode(Wrapper([Throwing()])) - } - - // MARK: - Decoder State - // SR-6048 - func testDecoderStateThrowOnDecode() { - let plist = try! PropertyListEncoder().encode([1,2,3]) - let _ = try! PropertyListDecoder().decode(EitherDecodable<[String], [Int]>.self, from: plist) - } - -#if FOUNDATION_FRAMEWORK - // MARK: - NSKeyedArchiver / NSKeyedUnarchiver integration - func testArchiving() { - struct CodableType: Codable, Equatable { - let willBeNil: String? - let arrayOfOptionals: [String?] - let dictionaryOfArrays: [String: [Data]] - } - - - let keyedArchiver = NSKeyedArchiver(requiringSecureCoding: false) - keyedArchiver.outputFormat = .xml - - let value = CodableType(willBeNil: nil, - arrayOfOptionals: ["a", "b", nil, "c"], - dictionaryOfArrays: [ "data" : [Data([0xfe, 0xed, 0xfa, 0xce]), Data([0xba, 0xaa, 0xaa, 0xad])]]) - - do { - try keyedArchiver.encodeEncodable(value, forKey: "strings") - keyedArchiver.finishEncoding() - let data = keyedArchiver.encodedData - - let keyedUnarchiver = try NSKeyedUnarchiver(forReadingFrom: data) - let unarchived = try keyedUnarchiver.decodeTopLevelDecodable(CodableType.self, forKey: "strings") - - XCTAssertEqual(unarchived, value) - } catch { - XCTFail("Unexpected error: \(error)") - } - } -#endif - - // MARK: - Helper Functions - private var _plistEmptyDictionaryBinary: Data { - return Data(base64Encoded: "YnBsaXN0MDDQCAAAAAAAAAEBAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJ")! - } - - private var _plistEmptyDictionaryXML: Data { - return "\n\n\n\n\n".data(using: String._Encoding.utf8)! - } - - private func _testEncodeFailure(of value: T, in format: PropertyListDecoder.PropertyListFormat) { - do { - let encoder = PropertyListEncoder() - encoder.outputFormat = format - let _ = try encoder.encode(value) - XCTFail("Encode of top-level \(T.self) was expected to fail.") - } catch {} - } - - @discardableResult - private func _testRoundTrip(of value: T, in format: PropertyListDecoder.PropertyListFormat, expectedPlist plist: Data? = nil) -> T? where T : Codable, T : Equatable { - var payload: Data! = nil - do { - let encoder = PropertyListEncoder() - encoder.outputFormat = format - payload = try encoder.encode(value) - } catch { - XCTFail("Failed to encode \(T.self) to plist: \(error)") - } - - if let expectedPlist = plist { - XCTAssertEqual(expectedPlist, payload, "Produced plist not identical to expected plist.") - } - - do { - var decodedFormat: PropertyListDecoder.PropertyListFormat = format - let decoded = try PropertyListDecoder().decode(T.self, from: payload, format: &decodedFormat) - XCTAssertEqual(format, decodedFormat, "Encountered plist format differed from requested format.") - XCTAssertEqual(decoded, value, "\(T.self) did not round-trip to an equal value.") - return decoded - } catch { - XCTFail("Failed to decode \(T.self) from plist: \(error)") - return nil - } - } - - private func _forEachEncodingFormat(_ body: (PropertyListDecoder.PropertyListFormat) throws -> Void) rethrows { - try body(.xml) - try body(.binary) - } - - // MARK: - Other tests - func testUnkeyedContainerContainingNulls() throws { - struct UnkeyedContainerContainingNullTestType : Codable, Equatable { - var array = [String?]() - - func encode(to encoder: Encoder) throws { - var container = encoder.unkeyedContainer() - // We want to test this with explicit encodeNil calls. - for value in array { - if value == nil { - try container.encodeNil() - } else { - try container.encode(value!) - } - } - } - - init(from decoder: Decoder) throws { - var container = try decoder.unkeyedContainer() - while !container.isAtEnd { - if try container.decodeNil() { - array.append(nil) - } else { - array.append(try container.decode(String.self)) - } - } - } - - init(array: [String?]) { self.array = array } - } - - let array = [nil, "test", nil] - _testRoundTrip(of: UnkeyedContainerContainingNullTestType(array: array), in: .xml) - _testRoundTrip(of: UnkeyedContainerContainingNullTestType(array: array), in: .binary) - } - - func test_invalidNSDataKey_82142612() { - let data = testData(forResource: "Test_82142612", withExtension: "bad")! - - let decoder = PropertyListDecoder() - XCTAssertThrowsError(try decoder.decode([String:String].self, from: data)) - - // Repeat something similar with XML. - let xmlData = "abcdxyz".data(using: String._Encoding.utf8)! - XCTAssertThrowsError(try decoder.decode([String:String].self, from: xmlData)) - } - -#if FOUNDATION_FRAMEWORK - // TODO: Depends on data's range(of:) implementation - func test_nonStringDictionaryKey() { - let decoder = PropertyListDecoder() - let encoder = PropertyListEncoder() - encoder.outputFormat = .binary - var data = try! encoder.encode(["abcd":"xyz"]) - - // Replace the tag for the ASCII string (0101) that is length 4 ("abcd" => length: 0100) with a boolean "true" tag (0000_1001) - let range = data.range(of: Data([0b0101_0100]))! - data.replaceSubrange(range, with: Data([0b000_1001])) - XCTAssertThrowsError(try decoder.decode([String:String].self, from: data)) - - let xmlData = "abcdxyz".data(using: String._Encoding.utf8)! - XCTAssertThrowsError(try decoder.decode([String:String].self, from: xmlData)) - } -#endif - - struct GenericProperties : Decodable { - var assertionFailure: String? - - enum CodingKeys: String, CodingKey { - case array1, item1, item2 - } - - mutating func assertEqual(_ t1: T, _ t2: T) { - if t1 != t2 { - assertionFailure = "Values are not equal: \(t1) != \(t2)" - } - } - - init(from decoder: Decoder) throws { - let keyed = try decoder.container(keyedBy: CodingKeys.self) - - var arrayContainer = try keyed.nestedUnkeyedContainer(forKey: .array1) - assertEqual(try arrayContainer.decode(String.self), "arr0") - assertEqual(try arrayContainer.decode(Int.self), 42) - assertEqual(try arrayContainer.decode(Bool.self), false) - - let comps = DateComponents(calendar: .init(identifier: .gregorian), timeZone: .init(secondsFromGMT: 0), year: 1976, month: 04, day: 01, hour: 12, minute: 00, second: 00) - let date = comps.date! - assertEqual(try arrayContainer.decode(Date.self), date) - - let someData = Data([0xaa, 0xbb, 0xcc, 0xdd, 0x00, 0x11, 0x22, 0x33]) - assertEqual(try arrayContainer.decode(Data.self), someData) - - assertEqual(try keyed.decode(String.self, forKey: .item1), "value1") - assertEqual(try keyed.decode(String.self, forKey: .item2), "value2") - } - } - - func test_5616259() throws { - let plistData = testData(forResource: "Test_5616259", withExtension: "bad")! - XCTAssertThrowsError(try PropertyListDecoder().decode([String].self, from: plistData)) - } - - func test_genericProperties_XML() throws { - let data = testData(forResource: "Generic_XML_Properties", withExtension: "plist")! - - let props = try PropertyListDecoder().decode(GenericProperties.self, from: data) - XCTAssertNil(props.assertionFailure) - } - - func test_genericProperties_binary() throws { - let data = testData(forResource: "Generic_XML_Properties_Binary", withExtension: "plist")! - - let props = try PropertyListDecoder().decode(GenericProperties.self, from: data) - XCTAssertNil(props.assertionFailure) - } - - // Binary plist parser should parse any version 'bplist0?' - func test_5877417() throws { - var data = testData(forResource: "Generic_XML_Properties_Binary", withExtension: "plist")! - - // Modify the data so the header starts with bplist0x - data[7] = UInt8(ascii: "x") - - let props = try PropertyListDecoder().decode(GenericProperties.self, from: data) - XCTAssertNil(props.assertionFailure) - } - - func test_xmlErrors() { - let data = testData(forResource: "Generic_XML_Properties", withExtension: "plist")! - let originalXML = String(data: data, encoding: .utf8)! - - // Try an empty plist - XCTAssertThrowsError(try PropertyListDecoder().decode(GenericProperties.self, from: Data())) - // We'll modify this string in all kinds of nasty ways to introduce errors - // --- - /* - - - - - array1 - - arr0 - 42 - - 1976-04-01T12:00:00Z - - qrvM3QARIjM= - - - item1 - value1 - item2 - value2 - - - */ - - var errorPlists = [String : String]() - - errorPlists["Deleted leading <"] = String(originalXML[originalXML.index(after: originalXML.startIndex)...]) - errorPlists["Unterminated comment"] = originalXML.replacingOccurrences(of: "", with: "<-- unending comment\n") - errorPlists["Mess with DOCTYPE"] = originalXML.replacingOccurrences(of: "DOCTYPE", with: "foobar") - - let range = originalXML.range(of: "//EN")! - errorPlists["Early EOF"] = String(originalXML[originalXML.startIndex ..< range.lowerBound]) - - errorPlists["MalformedDTD"] = originalXML.replacingOccurrences(of: "", with: "") - errorPlists["Bad open tag"] = originalXML.replacingOccurrences(of: "", with: "") - errorPlists["Extra plist object"] = originalXML.replacingOccurrences(of: "", with: "hello\n") - errorPlists["Non-key inside dict"] = originalXML.replacingOccurrences(of: "array1", with: "hello\narray1") - errorPlists["Missing value for key"] = originalXML.replacingOccurrences(of: "value1", with: "") - errorPlists["Malformed real tag"] = originalXML.replacingOccurrences(of: "42", with: "abc123") - errorPlists["Empty int tag"] = originalXML.replacingOccurrences(of: "42", with: "") - errorPlists["Strange int tag"] = originalXML.replacingOccurrences(of: "42", with: "42q") - errorPlists["Hex digit in non-hex int"] = originalXML.replacingOccurrences(of: "42", with: "42A") - errorPlists["Enormous int"] = originalXML.replacingOccurrences(of: "42", with: "99999999999999999999999999999999999999999") - errorPlists["Empty plist"] = "" - errorPlists["Empty date"] = originalXML.replacingOccurrences(of: "1976-04-01T12:00:00Z", with: "") - errorPlists["Empty real"] = originalXML.replacingOccurrences(of: "42", with: "") - errorPlists["Fake inline DTD"] = originalXML.replacingOccurrences(of: "PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"", with: "[]") - for (name, badPlist) in errorPlists { - let data = badPlist.data(using: String._Encoding.utf8)! - XCTAssertThrowsError(try PropertyListDecoder().decode(GenericProperties.self, from: data), "Case \(name) did not fail as expected") - } - - } - - func test_6164184() throws { - let xml = "0x721B0x1111-0xFFFF" - let array = try PropertyListDecoder().decode([Int].self, from: xml.data(using: String._Encoding.utf8)!) - XCTAssertEqual([0x721B, 0x1111, -0xFFFF], array) - } - - func test_xmlIntegerEdgeCases() throws { - func checkValidEdgeCase(_ xml: String, type: T.Type, expected: T) throws { - let value = try PropertyListDecoder().decode(type, from: xml.data(using: String._Encoding.utf8)!) - XCTAssertEqual(value, expected) - } - - try checkValidEdgeCase("127", type: Int8.self, expected: .max) - try checkValidEdgeCase("-128", type: Int8.self, expected: .min) - try checkValidEdgeCase("32767", type: Int16.self, expected: .max) - try checkValidEdgeCase("-32768", type: Int16.self, expected: .min) - try checkValidEdgeCase("2147483647", type: Int32.self, expected: .max) - try checkValidEdgeCase("-2147483648", type: Int32.self, expected: .min) - try checkValidEdgeCase("9223372036854775807", type: Int64.self, expected: .max) - try checkValidEdgeCase("-9223372036854775808", type: Int64.self, expected: .min) - - try checkValidEdgeCase("0x7f", type: Int8.self, expected: .max) - try checkValidEdgeCase("-0x80", type: Int8.self, expected: .min) - try checkValidEdgeCase("0x7fff", type: Int16.self, expected: .max) - try checkValidEdgeCase("-0x8000", type: Int16.self, expected: .min) - try checkValidEdgeCase("0x7fffffff", type: Int32.self, expected: .max) - try checkValidEdgeCase("-0x80000000", type: Int32.self, expected: .min) - try checkValidEdgeCase("0x7fffffffffffffff", type: Int64.self, expected: .max) - try checkValidEdgeCase("-0x8000000000000000", type: Int64.self, expected: .min) - - try checkValidEdgeCase("255", type: UInt8.self, expected: .max) - try checkValidEdgeCase("65535", type: UInt16.self, expected: .max) - try checkValidEdgeCase("4294967295", type: UInt32.self, expected: .max) - try checkValidEdgeCase("18446744073709551615", type: UInt64.self, expected: .max) - - func checkInvalidEdgeCase(_ xml: String, type: T.Type) { - XCTAssertThrowsError(try PropertyListDecoder().decode(type, from: xml.data(using: String._Encoding.utf8)!)) - } - - checkInvalidEdgeCase("128", type: Int8.self) - checkInvalidEdgeCase("-129", type: Int8.self) - checkInvalidEdgeCase("32768", type: Int16.self) - checkInvalidEdgeCase("-32769", type: Int16.self) - checkInvalidEdgeCase("2147483648", type: Int32.self) - checkInvalidEdgeCase("-2147483649", type: Int32.self) - checkInvalidEdgeCase("9223372036854775808", type: Int64.self) - checkInvalidEdgeCase("-9223372036854775809", type: Int64.self) - - checkInvalidEdgeCase("0x80", type: Int8.self) - checkInvalidEdgeCase("-0x81", type: Int8.self) - checkInvalidEdgeCase("0x8000", type: Int16.self) - checkInvalidEdgeCase("-0x8001", type: Int16.self) - checkInvalidEdgeCase("0x80000000", type: Int32.self) - checkInvalidEdgeCase("-0x80000001", type: Int32.self) - checkInvalidEdgeCase("0x8000000000000000", type: Int64.self) - checkInvalidEdgeCase("-0x8000000000000001", type: Int64.self) - - checkInvalidEdgeCase("256", type: UInt8.self) - checkInvalidEdgeCase("65536", type: UInt16.self) - checkInvalidEdgeCase("4294967296", type: UInt32.self) - checkInvalidEdgeCase("18446744073709551616", type: UInt64.self) - } - - func test_xmlIntegerWhitespace() throws { - let xml = " +\t42\t- 99 -\t0xFACE" - - let value = try PropertyListDecoder().decode([Int].self, from: xml.data(using: String._Encoding.utf8)!) - XCTAssertEqual(value, [42, -99, -0xFACE]) - } - - func test_binaryNumberEdgeCases() throws { - _testRoundTrip(of: [Int8.max], in: .binary) - _testRoundTrip(of: [Int8.min], in: .binary) - _testRoundTrip(of: [Int16.max], in: .binary) - _testRoundTrip(of: [Int16.min], in: .binary) - _testRoundTrip(of: [Int32.max], in: .binary) - _testRoundTrip(of: [Int32.min], in: .binary) - _testRoundTrip(of: [Int64.max], in: .binary) - _testRoundTrip(of: [Int64.max], in: .binary) - - _testRoundTrip(of: [UInt8.max], in: .binary) - _testRoundTrip(of: [UInt16.max], in: .binary) - _testRoundTrip(of: [UInt32.max], in: .binary) - _testRoundTrip(of: [UInt64.max], in: .binary) - - _testRoundTrip(of: [Float.greatestFiniteMagnitude], in: .binary) - _testRoundTrip(of: [-Float.greatestFiniteMagnitude], in: .binary) -// _testRoundTrip(of: [Float.nan], in: .binary) // NaN can't be equated. - _testRoundTrip(of: [Float.infinity], in: .binary) - _testRoundTrip(of: [-Float.infinity], in: .binary) - - _testRoundTrip(of: [Double.greatestFiniteMagnitude], in: .binary) - _testRoundTrip(of: [-Double.greatestFiniteMagnitude], in: .binary) -// _testRoundTrip(of: [Double.nan], in: .binary) // NaN can't be equated. - _testRoundTrip(of: [Double.infinity], in: .binary) - _testRoundTrip(of: [-Double.infinity], in: .binary) - } - - func test_binaryReals() throws { - func encode(_: T.Type) -> (data: Data, expected: [T]) { - let expected: [T] = [ - 1.5, - 2, - -3.14, - 1.000000000000000000000001, - 31415.9e-4, - -.infinity, - .infinity - ] - let encoder = PropertyListEncoder() - encoder.outputFormat = .binary - let data = try! encoder.encode(expected) - return (data, expected) - } - - func test(_ type: T.Type) { - let (data, expected) = encode(type) - do { - let result = try PropertyListDecoder().decode([T].self, from: data) - XCTAssertEqual(result, expected, "Type: \(type)") - } catch { - XCTFail("Expected error \(error) for type: \(type)") - } - } - - test(Float.self) - test(Double.self) - } - - func test_XMLReals() throws { - let xml = "1.52 -3.141.00000000000000000000000131415.9e-4-iNfinfInItY" - let array = try PropertyListDecoder().decode([Float].self, from: xml.data(using: String._Encoding.utf8)!) - let expected: [Float] = [ - 1.5, - 2, - -3.14, - 1.000000000000000000000001, - 31415.9e-4, - -.infinity, - .infinity - ] - XCTAssertEqual(array, expected) - - // nan doesn't work with equality. - let xmlNAN = "nAnNANnan" - let arrayNAN = try PropertyListDecoder().decode([Float].self, from: xmlNAN.data(using: String._Encoding.utf8)!) - for val in arrayNAN { - XCTAssertTrue(val.isNaN) - } - } - - func test_bad_XMLReals() { - let badRealXMLs = [ - "0x10", - "notanumber", - "infinite", - "1.2.3", - "1.e", - "1.5 ", // Trailing whitespace is rejected, unlike leading whitespace. - "", - ] - for xml in badRealXMLs { - XCTAssertThrowsError(try PropertyListDecoder().decode(Float.self, from: xml.data(using: String._Encoding.utf8)!), "Input: \(xml)") - } - } - - - func test_oldStylePlist_invalid() { - let data = "goodbye cruel world".data(using: String._Encoding.utf16)! - XCTAssertThrowsError(try PropertyListDecoder().decode(String.self, from: data)) - } - - // Microsoft: Microsoft vso 1857102 : High Sierra regression that caused data loss : CFBundleCopyLocalizedString returns incorrect string - // Escaped octal chars can be shorter than 3 chars long; i.e. \5 ≡ \05 ≡ \005. - func test_oldStylePlist_getSlashedChars_octal() { - // ('\0', '\00', '\000', '\1', '\01', '\001', ..., '\777') - let data = testData(forResource: "test_oldStylePlist_getSlashedChars_octal", withExtension: "plist")! - let actualStrings = try! PropertyListDecoder().decode([String].self, from: data) - - let expectedData = testData(forResource: "test_oldStylePlist_getSlashedChars_octal_expected", withExtension: "plist")! - let expectedStrings = try! PropertyListDecoder().decode([String].self, from: expectedData) - - XCTAssertEqual(actualStrings, expectedStrings) - } - - // Old-style plists support Unicode literals via \U syntax. They can be 1–4 characters wide. - func test_oldStylePlist_getSlashedChars_unicode() { - // ('\U0', '\U00', '\U000', '\U0000', '\U1', ..., '\UFFFF') - let data = testData(forResource: "test_oldStylePlist_getSlashedChars_unicode", withExtension: "plist")! - let actualStrings = try! PropertyListDecoder().decode([String].self, from: data) - - let expectedData = testData(forResource: "test_oldStylePlist_getSlashedChars_unicode_expected", withExtension: "plist")! - let expectedStrings = try! PropertyListDecoder().decode([String].self, from: expectedData) - - XCTAssertEqual(actualStrings, expectedStrings) - } - - func test_oldStylePlist_getSlashedChars_literals() { - let literals = ["\u{7}", "\u{8}", "\u{12}", "\n", "\r", "\t", "\u{11}", "\"", "\\n"] - let data = "('\\a', '\\b', '\\f', '\\n', '\\r', '\\t', '\\v', '\\\"', '\\\\n')".data(using: String._Encoding.utf8)! - - let strings = try! PropertyListDecoder().decode([String].self, from: data) - XCTAssertEqual(strings, literals) - } - - func test_oldStylePlist_dictionary() { - let data = """ -{ "test key" = value; - testData = ; - "nested array" = (a, b, c); } -""".data(using: String._Encoding.utf16)! - - struct Values: Decodable { - let testKey: String - let testData: Data - let nestedArray: [String] - - enum CodingKeys: String, CodingKey { - case testKey = "test key" - case testData - case nestedArray = "nested array" - } - } - do { - let decoded = try PropertyListDecoder().decode(Values.self, from: data) - XCTAssertEqual(decoded.testKey, "value") - XCTAssertEqual(decoded.testData, Data([0xfe, 0xed, 0xfa, 0xce])) - XCTAssertEqual(decoded.nestedArray, ["a", "b", "c"]) - } catch { - XCTFail("Unexpected error: \(error)") - } - } - - func test_oldStylePlist_stringsFileFormat() { - let data = """ -string1 = "Good morning"; -string2 = "Good afternoon"; -string3 = "Good evening"; -""".data(using: String._Encoding.utf16)! - - do { - let decoded = try PropertyListDecoder().decode([String:String].self, from: data) - let expected = [ - "string1": "Good morning", - "string2": "Good afternoon", - "string3": "Good evening" - ] - XCTAssertEqual(decoded, expected) - } catch { - XCTFail("Unexpected error: \(error)") - } - } - - func test_oldStylePlist_comments() { - let data = """ -// Initial comment */ -string1 = /*Test*/ "Good morning"; // Test -string2 = "Good afternoon" /*Test// */; -string3 = "Good evening"; // Test -""".data(using: String._Encoding.utf16)! - - do { - let decoded = try PropertyListDecoder().decode([String:String].self, from: data) - let expected = [ - "string1": "Good morning", - "string2": "Good afternoon", - "string3": "Good evening" - ] - XCTAssertEqual(decoded, expected) - } catch { - XCTFail("Unexpected error: \(error)") - } - } - -#if FOUNDATION_FRAMEWORK - // Requires __PlistDictionaryDecoder - - func test_oldStylePlist_data() { - let data = """ -data1 = <7465 -73 74 -696E67 31 - -323334>; -""".data(using: String._Encoding.utf16)! - - do { - let decoded = try PropertyListDecoder().decode([String:Data].self, from: data) - let expected = ["data1" : "testing1234".data(using: String._Encoding.utf8)!] - XCTAssertEqual(decoded, expected) - } catch { - XCTFail("Unexpected error: \(error)") - } - } -#endif - -#if FOUNDATION_FRAMEWORK - // Requires PropertyListSerialization - - func test_BPlistCollectionReferences() { - // Use NSArray/NSDictionary and PropertyListSerialization so that we get a bplist with internal references. - let c: NSArray = [ "a", "a", "a" ] - let b: NSArray = [ c, c, c ] - let a: NSArray = [ b, b, b ] - let d: NSDictionary = ["a" : a, "b" : b, "c" : c] - let data = try! PropertyListSerialization.data(fromPropertyList: d, format: .binary, options: 0) - - do { - struct DecodedReferences: Decodable { - let a: [[[String]]] - let b: [[String]] - let c: [String] - } - - let decoded = try PropertyListDecoder().decode(DecodedReferences.self, from: data) - XCTAssertEqual(decoded.a, a as! [[[String]]]) - XCTAssertEqual(decoded.b, b as! [[String]]) - XCTAssertEqual(decoded.c, c as! [String]) - } catch { - XCTFail("Unexpected error: \(error)") - } - } -#endif - - - func test_reallyOldDates_5842198() throws { - let plist = "\n\n\n0009-09-15T23:16:13Z\n" - let data = plist.data(using: String._Encoding.utf8)! - - XCTAssertNoThrow(try PropertyListDecoder().decode(Date.self, from: data)) - } - - func test_badDates() throws { - let timeInterval = TimeInterval(-63145612800) // This is the equivalent of an all-zero gregorian date. - let date = Date(timeIntervalSinceReferenceDate: timeInterval) - - _testRoundTrip(of: [date], in: .xml) - _testRoundTrip(of: [date], in: .binary) - } - - func test_badDate_encode() throws { - let date = Date(timeIntervalSinceReferenceDate: -63145612800) // 0000-01-02 AD - - let encoder = PropertyListEncoder() - encoder.outputFormat = .xml - let data = try encoder.encode([date]) - let str = String(data: data, encoding: String.Encoding.utf8) - XCTAssertEqual(str, "\n\n\n\n\t0000-01-02T00:00:00Z\n\n\n") - } - - func test_badDate_decode() throws { - // Test that we can correctly decode a distant date in the past - let plist = "\n\n\n0000-01-02T00:00:00Z\n" - let data = plist.data(using: String._Encoding.utf8)! - - let d = try PropertyListDecoder().decode(Date.self, from: data) - XCTAssertEqual(d.timeIntervalSinceReferenceDate, -63145612800) - } - - func test_realEncodeRemoveZeroSuffix() throws { - // Tests that we encode "whole-value reals" (such as `2.0`, `-5.0`, etc) - // **without** the `.0` for backwards compactability - let encoder = PropertyListEncoder() - encoder.outputFormat = .xml - let template = "\(_XMLPlistEncodingFormat.Writer.header)\n\t<%EXPECTED%>\n\n\n" - - let wholeFloat: Float = 2.0 - var data = try encoder.encode([wholeFloat]) - var str = try XCTUnwrap(String(data: data, encoding: String.Encoding.utf8)) - var expected = template.replacingOccurrences( - of: "<%EXPECTED%>", with: "2") - XCTAssertEqual(str, expected) - - let wholeDouble: Double = -5.0 - data = try encoder.encode([wholeDouble]) - str = try XCTUnwrap(String(data: data, encoding: String.Encoding.utf8)) - expected = template.replacingOccurrences( - of: "<%EXPECTED%>", with: "-5") - XCTAssertEqual(str, expected) - - // Make sure other reals are not affacted - let notWholeDouble = 0.5 - data = try encoder.encode([notWholeDouble]) - str = try XCTUnwrap(String(data: data, encoding: String.Encoding.utf8)) - expected = template.replacingOccurrences( - of: "<%EXPECTED%>", with: "0.5") - XCTAssertEqual(str, expected) - } - - func test_farFutureDates() throws { - let date = Date(timeIntervalSince1970: 999999999999.0) - - _testRoundTrip(of: [date], in: .xml) - } - - func test_122065123_encode() throws { - let date = Date(timeIntervalSinceReferenceDate: 728512994) // 2024-02-01 20:43:14 UTC - - let encoder = PropertyListEncoder() - encoder.outputFormat = .xml - let data = try encoder.encode([date]) - let str = String(data: data, encoding: String.Encoding.utf8) - XCTAssertEqual(str, "\n\n\n\n\t2024-02-01T20:43:14Z\n\n\n") // Previously encoded as "2024-01-32T20:43:14Z" - } - - func test_122065123_decodingCompatibility() throws { - // Test that we can correctly decode an invalid date - let plist = "\n\n\n2024-01-32T20:43:14Z\n" - let data = plist.data(using: String._Encoding.utf8)! - - let d = try PropertyListDecoder().decode(Date.self, from: data) - XCTAssertEqual(d.timeIntervalSinceReferenceDate, 728512994) // 2024-02-01T20:43:14Z - } - - func test_multibyteCharacters_escaped_noencoding() throws { - let plistData = "These are copyright signs © © blah blah blah.".data(using: String._Encoding.utf8)! - let result = try PropertyListDecoder().decode(String.self, from: plistData) - XCTAssertEqual("These are copyright signs © © blah blah blah.", result) - } - - func test_escapedCharacters() throws { - let plistData = "&'<>"".data(using: String._Encoding.utf8)! - let result = try PropertyListDecoder().decode(String.self, from: plistData) - XCTAssertEqual("&'<>\"", result) - } - - func test_dataWithBOM_utf8() throws { - let bom = Data([0xef, 0xbb, 0xbf]) - let plist = bom + "\n\n\nhello\n".data(using: String._Encoding.utf8)! - - let result = try PropertyListDecoder().decode(String.self, from: plist) - XCTAssertEqual(result, "hello") - } - -#if FOUNDATION_FRAMEWORK - // TODO: Depends on UTF32 encoding on non-Darwin platforms - - func test_dataWithBOM_utf32be() throws { - let bom = Data([0x00, 0x00, 0xfe, 0xff]) - let plist = bom + "\n\n\nhello\n".data(using: String._Encoding.utf32BigEndian)! - - let result = try PropertyListDecoder().decode(String.self, from: plist) - XCTAssertEqual(result, "hello") - } - - func test_dataWithBOM_utf32le() throws { - let bom = Data([0xff, 0xfe]) - let plist = bom + "\n\n\nhello\n".data(using: String._Encoding.utf16LittleEndian)! - - let result = try PropertyListDecoder().decode(String.self, from: plist) - XCTAssertEqual(result, "hello") - } -#endif - - func test_plistWithBadUTF8() throws { - let data = testData(forResource: "bad_plist", withExtension: "bad")! - - XCTAssertThrowsError(try PropertyListDecoder().decode([String].self, from: data)) - } - - func test_plistWithEscapedCharacters() throws { - let plist = "com.apple.security.temporary-exception.sbpl(allow mach-lookup (global-name-regex #"^[0-9]+$"))".data(using: String._Encoding.utf8)! - let result = try PropertyListDecoder().decode([String:String].self, from: plist) - XCTAssertEqual(result, ["com.apple.security.temporary-exception.sbpl" : "(allow mach-lookup (global-name-regex #\"^[0-9]+$\"))"]) - } - -#if FOUNDATION_FRAMEWORK - // OpenStep format is not supported in Essentials - func test_returnRightFormatFromParse() throws { - let plist = "{ CFBundleDevelopmentRegion = en; }".data(using: String._Encoding.utf8)! - - var format : PropertyListDecoder.PropertyListFormat = .binary - let _ = try PropertyListDecoder().decode([String:String].self, from: plist, format: &format) - XCTAssertEqual(format, .openStep) - } -#endif - - func test_decodingEmoji() throws { - let plist = "emoji🚘".data(using: String._Encoding.utf8)! - - let result = try PropertyListDecoder().decode([String:String].self, from: plist) - let expected = "\u{0001F698}" - XCTAssertEqual(expected, result["emoji"]) - } - - func test_decodingTooManyCharactersError() throws { - // Try a plist with too many characters to be a unicode escape sequence - let plist = "emoji".data(using: String._Encoding.utf8)! - - XCTAssertThrowsError(try PropertyListDecoder().decode([String:String].self, from: plist)) - - // Try a plist with an invalid unicode escape sequence - let plist2 = "emoji".data(using: String._Encoding.utf8)! - - XCTAssertThrowsError(try PropertyListDecoder().decode([String:String].self, from: plist2)) - } - - func test_roundTripEmoji() throws { - let strings = ["🚘", "👩ðŸ»â€â¤ï¸â€ðŸ‘¨ðŸ¿", "ðŸ‹ðŸ½â€â™‚ï¸ðŸ•ºðŸ¼ðŸ¥Œ"] - - _testRoundTrip(of: strings, in: .xml) - _testRoundTrip(of: strings, in: .binary) - } - - func test_roundTripEscapedStrings() { - let strings = ["&", "<", ">"] - _testRoundTrip(of: strings, in: .xml) - } - - func test_unterminatedComment() { - let plist = "".data(using: String._Encoding.utf8)! - XCTAssertThrowsError(try PropertyListDecoder().decode([String].self, from: plist)) - } - - func test_incompleteOpenTag() { - let plist = "(_ t1: T, _ t2: T) { - if t1 != t2 { - assertionFailure = "Values are not equal: \(t1) != \(t2)" - } - } - - mutating func assertTrue( _ res: Bool) { - if !res { - assertionFailure = "Expected true result" - } - } - - enum CodingKeys: String, CodingKey { - case a, b, unkeyed - } - - func encode(to encoder: Encoder) throws { - var keyed = encoder.container(keyedBy: CodingKeys.self) - try keyed.encodeNil(forKey: .a) - - let superB = keyed.superEncoder(forKey: .b) - var bSVC = superB.singleValueContainer() - try bSVC.encode("b") - - let s = keyed.superEncoder() - var sSVC = s.singleValueContainer() - try sSVC.encode("super") - - let superUnkeyed = keyed.superEncoder(forKey: .unkeyed) - var unkeyed = superUnkeyed.unkeyedContainer() - - try unkeyed.encodeNil() - - let superInUnkeyed = unkeyed.superEncoder() - - try unkeyed.encode("final") - - var sIUSVC = superInUnkeyed.singleValueContainer() - try sIUSVC.encode("middle") - } - - init(from decoder: Decoder) throws { - let keyed = try decoder.container(keyedBy: CodingKeys.self) - assertTrue(try keyed.decodeNil(forKey: .a)) - - let superB = try keyed.superDecoder(forKey: .b) - let bSVC = try superB.singleValueContainer() - assertEqual("b", try bSVC.decode(String.self)) - - let s = try keyed.superDecoder() - let sSVC = try s.singleValueContainer() - assertEqual("super", try sSVC.decode(String.self)) - - let superUnkeyed = try keyed.superDecoder(forKey: .unkeyed) - var unkeyed = try superUnkeyed.unkeyedContainer() - - let gotNil = try unkeyed.decodeNil() - assertTrue(gotNil) - - let superInUnkeyed = try unkeyed.superDecoder() - let sIUSVC = try superInUnkeyed.singleValueContainer() - assertEqual("middle", try sIUSVC.decode(String.self)) - - assertEqual("final", try unkeyed.decode(String.self)) - } - - init() { } - } - - let result1 = try XCTUnwrap(_testRoundTrip(of: UsesSupers(), in: .xml)) - XCTAssertNil(result1.assertionFailure) - let result2 = try XCTUnwrap(_testRoundTrip(of: UsesSupers(), in: .binary)) - XCTAssertNil(result2.assertionFailure) - } - - func test_badReferenceIndex() { - // The following is the bplist representation of `[42, 314, 0xFF]` that has been corrupted. - let bplist = [ - 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, // bplist00 - 0xa3, 0x01, 0x02, /*0x03*/0xBD, // 3 elements array: indexes([42, 314, 0xFF]) -- BUT third index replaced with an invalid one (0xBD) which should throw an error intead of crashing. - 0x10, 0x2a, // integer 42 - 0x11, 0x01, 0x3a, // integer 314 - 0x10, 0xff, // integer 0xFF - 0x08, 0x0c, 0x0e, 0x11, // object offset table: offsets([array, 42, 314, 0xFF]) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13 // trailer - ] as [UInt8] - let data = Data(bplist) - - XCTAssertThrowsError(try PropertyListDecoder().decode([Int].self, from: data)) - } - - func test_badTopObjectIndex() { - // The following is the bplist representation of `[42, 314, 0xFF]` that has been corrupted. - let bplist = [ - 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, // bplist00 - 0xa3, 0x01, 0x02, 0x03, // 3 elements array: indexes([42, 314, 0xFF]) - 0x10, 0x2a, // integer 42 - 0x11, 0x01, 0x3a, // integer 314 - 0x10, 0xff, // integer 0xFF - 0x08, 0x0c, 0x0e, 0x11, // object offset table: offsets([array, 42, 314, 0xFF]) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Top object index -- CORRUPTED - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13 // trailer - ] as [UInt8] - let data = Data(bplist) - - XCTAssertThrowsError(try PropertyListDecoder().decode([Int].self, from: data)) - } - - func test_outOfBoundsObjectOffset() { - // The following is the bplist representation of `[42, 314, 0xFF]` that has been corrupted. - let bplist = [ - 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, // bplist00 - 0xa3, 0x01, 0x02, 0x03, // 3 elements array: indexes([42, 314, 0xFF]) - 0x10, 0x2a, // integer 42 - 0x11, 0x01, 0x3a, // integer 314 - 0x10, 0xff, // integer 0xFF - 0x08, 0x0c, 0x0e, /*0x11*/ 0xEE, // object offset table: offsets([array, 42, 314, 0xFF]) -- BUT one offset is out of range. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13 // trailer - ] as [UInt8] - let data = Data(bplist) - - XCTAssertThrowsError(try PropertyListDecoder().decode([Int].self, from: data)) - } - - func test_outOfBoundsOffsetTableStart() { - // The following is the bplist representation of `[42, 314, 0xFF]` that has been corrupted. - let bplist = [ - 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, // bplist00 - 0xa3, 0x01, 0x02, 0x03, // 3 elements array: indexes([42, 314, 0xFF]) - 0x10, 0x2a, // integer 42 - 0x11, 0x01, 0x3a, // integer 314 - 0x10, 0xff, // integer 0xFF - 0x08, 0x0c, 0x0e, 0x11, // object offset table: offsets([array, 42, 314, 0xFF]) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF // trailer -- CORRUPTED with out of bounds offset table start offset - ] as [UInt8] - let data = Data(bplist) - - XCTAssertThrowsError(try PropertyListDecoder().decode([Int].self, from: data)) - } - - func test_tooLargeObjectCount() { - // The following is the bplist representation of `[42, 314, 0xFF]` that has been corrupted. - let bplist = [ - 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, // bplist00 - 0xa3, 0x01, 0x02, 0x03, // 3 elements array: indexes([42, 314, 0xFF]) - 0x10, 0x2a, // integer 42 - 0x11, 0x01, 0x3a, // integer 314 - 0x10, 0xff, // integer 0xFF - 0x08, 0x0c, 0x0e, 0x11, // object offset table: offsets([array, 42, 314, 0xFF]) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // object count -- CORRUPTED - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13 // trailer - ] as [UInt8] - let data = Data(bplist) - - XCTAssertThrowsError(try PropertyListDecoder().decode([Int].self, from: data)) - } - - func test_tooLargeOffset() { - // The following is the bplist representation of `[42, 314, 0xFF]` that has been corrupted. - let bplist = [ - 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, // bplist00 - 0xa3, 0x01, 0x02, 0x03, // 3 elements array: indexes([42, 314, 0xFF]) - 0x10, 0x2a, // integer 42 - 0x11, 0x01, 0x3a, // integer 314 - 0x10, 0xff, // integer 0xFF - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, // offset(array) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, // offset(42) - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // offset(314) -- CORRUPTED - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, // offset(0xFF) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, // MODIFIED to make object offsets be 8 bytes instead of 1 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13 // trailer -- MODIFIED to accommodate larger object index size - ] as [UInt8] - let data = Data(bplist) - - XCTAssertThrowsError(try PropertyListDecoder().decode([Int].self, from: data)) - } - - func test_tooLargeIndex() { - // The following is the bplist representation of `[42, 314, 0xFF]` that has been corrupted. - let bplist = [ - 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, // bplist00 - 0xa3, // 3 element array - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // index(42) - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // index(314) -- CORRUPTED to a very large value - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, // index(0xFF) - 0x10, 0x2a, // integer 42 - 0x11, 0x01, 0x3a, // integer 314 - 0x10, 0xff, // integer 0xFF - 0x08, 0x21, 0x23, 0x26, // object offset table: offsets([array, 42, 314, 0xFF]) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, // MODIFIED to make object offsets be 8 bytes instead of 1 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28 // trailer -- MODIFIED to accommodate larger object index size - ] as [UInt8] - let data = Data(bplist) - - XCTAssertThrowsError(try PropertyListDecoder().decode([Int].self, from: data)) - } - - func test_uid() throws { - // There's no public interface where an NSKeyedArchiver UID value will correctly decode through PropertyListDecoder. This test ensures that it isn't mistaken for some other type. - - let xml = "CF$UID1" - let xmlData = xml.data(using: String._Encoding.utf8)! - - XCTAssertThrowsError(try PropertyListDecoder().decode([String:Int32].self, from: xmlData)) - - let bplist = [ - 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, // bplist00 - 0xa1, 0x01, // 1 element array: indexes([cfuid]) - 0x80, 0x01, // cfuid: 1 - 0x08, 0x0a, // object offset table: offsets([array, cfuid]) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c // trailer - ] as [UInt8] - let bplistData = Data(bplist) - - XCTAssertThrowsError(try PropertyListDecoder().decode([Int32].self, from: bplistData)) - } - - func test_fauxStability_struct() throws { - struct FauxStable: Encodable { - let a = "a" - let z = "z" - let n = "n" - } - - let encoder = PropertyListEncoder() - encoder.outputFormat = .binary - - let encoding = try encoder.encode(FauxStable()) - for _ in 0..<1000 { - let reencoding = try encoder.encode(FauxStable()) - XCTAssertEqual(encoding, reencoding) - } - } - - func test_fauxStability_dict() throws { - let encoder = PropertyListEncoder() - encoder.outputFormat = .binary - - let encoding = try encoder.encode(["a":"a", "z":"z", "n":"n"]) - for _ in 0..<1000 { - let reencoding = try encoder.encode(["a":"a", "z":"z", "n":"n"]) - XCTAssertEqual(encoding, reencoding) - } - } - - func testMultipleDecodeOptions() throws { - let cases = [ - MultipleDecodeOptionsTestType("1", .int), - MultipleDecodeOptionsTestType("1.2", .float), - MultipleDecodeOptionsTestType("foo", .string) - ] - for input in cases { - _testRoundTrip(of: input, in: .binary) - _testRoundTrip(of: input, in: .xml) - } - } - - func testCustomSubclass() throws { - // verify we consult the subclass for the output format - let encodeMe = ["hello":"world"] - let encoder = XMLOnlyEncoder() - let data = try encoder.encode(encodeMe) - let dataAsStr = String(data: data, encoding: .utf8)! - XCTAssertTrue(dataAsStr.hasPrefix(".allNils) - let testEmptyDict = try PropertyListDecoder().decode(DecodeIfPresentAllTypes.self, from: emptyDictEncoding) - XCTAssertEqual(testEmptyDict, .allNils) - - let allNullDictEncoding = try encoder.encode(DecodeIfPresentAllTypes.allNils) - let testAllNullDict = try PropertyListDecoder().decode(DecodeIfPresentAllTypes.self, from: allNullDictEncoding) - XCTAssertEqual(testAllNullDict, .allNils) - - let allOnesDictEncoding = try encoder.encode(DecodeIfPresentAllTypes.allOnes) - let testAllOnesDict = try PropertyListDecoder().decode(DecodeIfPresentAllTypes.self, from: allOnesDictEncoding) - XCTAssertEqual(testAllOnesDict, .allOnes) - - let emptyArrayEncoding = try encoder.encode(DecodeIfPresentAllTypes.allNils) - let testEmptyArray = try PropertyListDecoder().decode(DecodeIfPresentAllTypes.self, from: emptyArrayEncoding) - XCTAssertEqual(testEmptyArray, .allNils) - - let allNullArrayEncoding = try encoder.encode(DecodeIfPresentAllTypes.allNils) - let testAllNullArray = try PropertyListDecoder().decode(DecodeIfPresentAllTypes.self, from: allNullArrayEncoding) - XCTAssertEqual(testAllNullArray, .allNils) - - let allOnesArrayEncoding = try encoder.encode(DecodeIfPresentAllTypes.allOnes) - let testAllOnesArray = try PropertyListDecoder().decode(DecodeIfPresentAllTypes.self, from: allOnesArrayEncoding) - XCTAssertEqual(testAllOnesArray, .allOnes) - } - - } - - func test_garbageCharactersAfterXMLTagName() throws { - let garbage = "barfoo".data(using: String._Encoding.utf8)! - - XCTAssertThrowsError(try PropertyListDecoder().decode([String:String].self, from: garbage)) - - // Historical behavior allows for whitespace to immediately follow tag names - let acceptable = "barfoo".data(using: String._Encoding.utf8)! - - XCTAssertEqual(try PropertyListDecoder().decode([String:String].self, from: acceptable), ["bar":"foo"]) - } -} - - -// MARK: - Helper Global Functions -func XCTAssertEqualPaths(_ lhs: [CodingKey], _ rhs: [CodingKey], _ prefix: String) { - if lhs.count != rhs.count { - XCTFail("\(prefix) [CodingKey].count mismatch: \(lhs.count) != \(rhs.count)") - return - } - - for (key1, key2) in zip(lhs, rhs) { - switch (key1.intValue, key2.intValue) { - case (.none, .none): break - case (.some(let i1), .none): - XCTFail("\(prefix) CodingKey.intValue mismatch: \(type(of: key1))(\(i1)) != nil") - return - case (.none, .some(let i2)): - XCTFail("\(prefix) CodingKey.intValue mismatch: nil != \(type(of: key2))(\(i2))") - return - case (.some(let i1), .some(let i2)): - guard i1 == i2 else { - XCTFail("\(prefix) CodingKey.intValue mismatch: \(type(of: key1))(\(i1)) != \(type(of: key2))(\(i2))") - return - } - - break - } - - XCTAssertEqual(key1.stringValue, key2.stringValue, "\(prefix) CodingKey.stringValue mismatch: \(type(of: key1))('\(key1.stringValue)') != \(type(of: key2))('\(key2.stringValue)')") - } -} - -// MARK: - Test Types - -// MARK: - Empty Types -fileprivate struct EmptyStruct : Codable, Equatable { - static func ==(_ lhs: EmptyStruct, _ rhs: EmptyStruct) -> Bool { - return true - } -} - -fileprivate class EmptyClass : Codable, Equatable { - static func ==(_ lhs: EmptyClass, _ rhs: EmptyClass) -> Bool { - return true - } -} - -// MARK: - Single-Value Types -/// A simple on-off switch type that encodes as a single Bool value. -fileprivate enum Switch : Codable { - case off - case on - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - switch try container.decode(Bool.self) { - case false: self = .off - case true: self = .on - } - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - switch self { - case .off: try container.encode(false) - case .on: try container.encode(true) - } - } -} - -/// A simple timestamp type that encodes as a single Double value. -fileprivate struct Timestamp : Codable, Equatable { - let value: Double - - init(_ value: Double) { - self.value = value - } - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - value = try container.decode(Double.self) - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(self.value) - } - - static func ==(_ lhs: Timestamp, _ rhs: Timestamp) -> Bool { - return lhs.value == rhs.value - } -} - -/// A simple referential counter type that encodes as a single Int value. -fileprivate final class Counter : Codable, Equatable { - var count: Int = 0 - - init() {} - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - count = try container.decode(Int.self) - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(self.count) - } - - static func ==(_ lhs: Counter, _ rhs: Counter) -> Bool { - return lhs === rhs || lhs.count == rhs.count - } -} - -private struct CodableTypeWithConfiguration : CodableWithConfiguration, Equatable { - struct Config { - let num: Int - - init(_ num: Int) { - self.num = num - } - } - - struct ConfigProviding : EncodingConfigurationProviding, DecodingConfigurationProviding { - static var encodingConfiguration: Config { Config(2) } - static var decodingConfiguration: Config { Config(2) } - } - - typealias EncodingConfiguration = Config - typealias DecodingConfiguration = Config - - static let testValue = Self(3) - - let num: Int - - init(_ num: Int) { - self.num = num - } - - func encode(to encoder: Encoder, configuration: Config) throws { - var container = encoder.singleValueContainer() - try container.encode(num + configuration.num) - } - - init(from decoder: Decoder, configuration: Config) throws { - let container = try decoder.singleValueContainer() - num = try container.decode(Int.self) - configuration.num - } -} - -// MARK: - Structured Types -/// A simple address type that encodes as a dictionary of values. -fileprivate struct Address : Codable, Equatable { - let street: String - let city: String - let state: String - let zipCode: Int - let country: String - - init(street: String, city: String, state: String, zipCode: Int, country: String) { - self.street = street - self.city = city - self.state = state - self.zipCode = zipCode - self.country = country - } - - static func ==(_ lhs: Address, _ rhs: Address) -> Bool { - return lhs.street == rhs.street && - lhs.city == rhs.city && - lhs.state == rhs.state && - lhs.zipCode == rhs.zipCode && - lhs.country == rhs.country - } - - static var testValue: Address { - return Address(street: "1 Infinite Loop", - city: "Cupertino", - state: "CA", - zipCode: 95014, - country: "United States") - } -} - -/// A simple person class that encodes as a dictionary of values. -fileprivate class Person : Codable, Equatable { - let name: String - let email: String - let website: String? - - init(name: String, email: String, website: String? = nil) { - self.name = name - self.email = email - self.website = website - } - - func isEqual(_ other: Person) -> Bool { - return self.name == other.name && - self.email == other.email && - self.website == other.website - } - - static func ==(_ lhs: Person, _ rhs: Person) -> Bool { - return lhs.isEqual(rhs) - } - - class var testValue: Person { - return Person(name: "Johnny Appleseed", email: "appleseed@apple.com") - } -} - -/// A class which shares its encoder and decoder with its superclass. -fileprivate class Employee : Person { - let id: Int - - init(name: String, email: String, website: String? = nil, id: Int) { - self.id = id - super.init(name: name, email: email, website: website) - } - - enum CodingKeys : String, CodingKey { - case id - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - id = try container.decode(Int.self, forKey: .id) - try super.init(from: decoder) - } - - override func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(id, forKey: .id) - try super.encode(to: encoder) - } - - override func isEqual(_ other: Person) -> Bool { - if let employee = other as? Employee { - guard self.id == employee.id else { return false } - } - - return super.isEqual(other) - } - - override class var testValue: Employee { - return Employee(name: "Johnny Appleseed", email: "appleseed@apple.com", id: 42) - } -} - -/// A simple company struct which encodes as a dictionary of nested values. -fileprivate struct Company : Codable, Equatable { - let address: Address - var employees: [Employee] - - init(address: Address, employees: [Employee]) { - self.address = address - self.employees = employees - } - - static func ==(_ lhs: Company, _ rhs: Company) -> Bool { - return lhs.address == rhs.address && lhs.employees == rhs.employees - } - - static var testValue: Company { - return Company(address: Address.testValue, employees: [Employee.testValue]) - } -} - -/// An enum type which decodes from Bool?. -fileprivate enum EnhancedBool : Codable { - case `true` - case `false` - case fileNotFound - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - if container.decodeNil() { - self = .fileNotFound - } else { - let value = try container.decode(Bool.self) - self = value ? .true : .false - } - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - switch self { - case .true: try container.encode(true) - case .false: try container.encode(false) - case .fileNotFound: try container.encodeNil() - } - } -} - -/// A type which encodes as an array directly through a single value container. -private struct Numbers : Codable, Equatable { - let values = [4, 8, 15, 16, 23, 42] - - init() {} - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - let decodedValues = try container.decode([Int].self) - guard decodedValues == values else { - throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "The Numbers are wrong!")) - } - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(values) - } - - static func ==(_ lhs: Numbers, _ rhs: Numbers) -> Bool { - return lhs.values == rhs.values - } - - static var testValue: Numbers { - return Numbers() - } -} - -/// A type which encodes as a dictionary directly through a single value container. -fileprivate final class Mapping : Codable, Equatable { - let values: [String : String] - - init(values: [String : String]) { - self.values = values - } - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - values = try container.decode([String : String].self) - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(values) - } - - static func ==(_ lhs: Mapping, _ rhs: Mapping) -> Bool { - return lhs === rhs || lhs.values == rhs.values - } - - static var testValue: Mapping { - return Mapping(values: ["Apple": "http://apple.com", - "localhost": "http://127.0.0.1"]) - } -} - -private struct NestedContainersTestType : Encodable { - let testSuperEncoder: Bool - - init(testSuperEncoder: Bool = false) { - self.testSuperEncoder = testSuperEncoder - } - - enum TopLevelCodingKeys : Int, CodingKey { - case a - case b - case c - } - - enum IntermediateCodingKeys : Int, CodingKey { - case one - case two - } - - func encode(to encoder: Encoder) throws { - if self.testSuperEncoder { - var topLevelContainer = encoder.container(keyedBy: TopLevelCodingKeys.self) - XCTAssertEqualPaths(encoder.codingPath, [], "Top-level Encoder's codingPath changed.") - XCTAssertEqualPaths(topLevelContainer.codingPath, [], "New first-level keyed container has non-empty codingPath.") - - let superEncoder = topLevelContainer.superEncoder(forKey: .a) - XCTAssertEqualPaths(encoder.codingPath, [], "Top-level Encoder's codingPath changed.") - XCTAssertEqualPaths(topLevelContainer.codingPath, [], "First-level keyed container's codingPath changed.") - XCTAssertEqualPaths(superEncoder.codingPath, [TopLevelCodingKeys.a], "New superEncoder had unexpected codingPath.") - _testNestedContainers(in: superEncoder, baseCodingPath: [TopLevelCodingKeys.a]) - } else { - _testNestedContainers(in: encoder, baseCodingPath: []) - } - } - - func _testNestedContainers(in encoder: Encoder, baseCodingPath: [CodingKey]) { - XCTAssertEqualPaths(encoder.codingPath, baseCodingPath, "New encoder has non-empty codingPath.") - - // codingPath should not change upon fetching a non-nested container. - var firstLevelContainer = encoder.container(keyedBy: TopLevelCodingKeys.self) - XCTAssertEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.") - XCTAssertEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "New first-level keyed container has non-empty codingPath.") - - // Nested Keyed Container - do { - // Nested container for key should have a new key pushed on. - var secondLevelContainer = firstLevelContainer.nestedContainer(keyedBy: IntermediateCodingKeys.self, forKey: .a) - XCTAssertEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.") - XCTAssertEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "First-level keyed container's codingPath changed.") - XCTAssertEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.a], "New second-level keyed container had unexpected codingPath.") - - // Inserting a keyed container should not change existing coding paths. - let thirdLevelContainerKeyed = secondLevelContainer.nestedContainer(keyedBy: IntermediateCodingKeys.self, forKey: .one) - XCTAssertEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.") - XCTAssertEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "First-level keyed container's codingPath changed.") - XCTAssertEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.a], "Second-level keyed container's codingPath changed.") - XCTAssertEqualPaths(thirdLevelContainerKeyed.codingPath, baseCodingPath + [TopLevelCodingKeys.a, IntermediateCodingKeys.one], "New third-level keyed container had unexpected codingPath.") - - // Inserting an unkeyed container should not change existing coding paths. - let thirdLevelContainerUnkeyed = secondLevelContainer.nestedUnkeyedContainer(forKey: .two) - XCTAssertEqualPaths(encoder.codingPath, baseCodingPath + [], "Top-level Encoder's codingPath changed.") - XCTAssertEqualPaths(firstLevelContainer.codingPath, baseCodingPath + [], "First-level keyed container's codingPath changed.") - XCTAssertEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.a], "Second-level keyed container's codingPath changed.") - XCTAssertEqualPaths(thirdLevelContainerUnkeyed.codingPath, baseCodingPath + [TopLevelCodingKeys.a, IntermediateCodingKeys.two], "New third-level unkeyed container had unexpected codingPath.") - } - - // Nested Unkeyed Container - do { - // Nested container for key should have a new key pushed on. - var secondLevelContainer = firstLevelContainer.nestedUnkeyedContainer(forKey: .b) - XCTAssertEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.") - XCTAssertEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "First-level keyed container's codingPath changed.") - XCTAssertEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.b], "New second-level keyed container had unexpected codingPath.") - - // Appending a keyed container should not change existing coding paths. - let thirdLevelContainerKeyed = secondLevelContainer.nestedContainer(keyedBy: IntermediateCodingKeys.self) - XCTAssertEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.") - XCTAssertEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "First-level keyed container's codingPath changed.") - XCTAssertEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.b], "Second-level unkeyed container's codingPath changed.") - XCTAssertEqualPaths(thirdLevelContainerKeyed.codingPath, baseCodingPath + [TopLevelCodingKeys.b, _TestKey(index: 0)], "New third-level keyed container had unexpected codingPath.") - - // Appending an unkeyed container should not change existing coding paths. - let thirdLevelContainerUnkeyed = secondLevelContainer.nestedUnkeyedContainer() - XCTAssertEqualPaths(encoder.codingPath, baseCodingPath, "Top-level Encoder's codingPath changed.") - XCTAssertEqualPaths(firstLevelContainer.codingPath, baseCodingPath, "First-level keyed container's codingPath changed.") - XCTAssertEqualPaths(secondLevelContainer.codingPath, baseCodingPath + [TopLevelCodingKeys.b], "Second-level unkeyed container's codingPath changed.") - XCTAssertEqualPaths(thirdLevelContainerUnkeyed.codingPath, baseCodingPath + [TopLevelCodingKeys.b, _TestKey(index: 1)], "New third-level unkeyed container had unexpected codingPath.") - } - } -} - -// MARK: - Helper Types - -/// A key type which can take on any string or integer value. -/// This needs to mirror _PlistKey. -fileprivate struct _TestKey : CodingKey { - var stringValue: String - var intValue: Int? - - init?(stringValue: String) { - self.stringValue = stringValue - self.intValue = nil - } - - init?(intValue: Int) { - self.stringValue = "\(intValue)" - self.intValue = intValue - } - - init(index: Int) { - self.stringValue = "Index \(index)" - self.intValue = index - } -} - -/// Wraps a type T so that it can be encoded at the top level of a payload. -fileprivate struct TopLevelWrapper : Codable, Equatable where T : Codable, T : Equatable { - let value: T - - init(_ value: T) { - self.value = value - } - - static func ==(_ lhs: TopLevelWrapper, _ rhs: TopLevelWrapper) -> Bool { - return lhs.value == rhs.value - } -} - -fileprivate enum EitherDecodable : Decodable { - case t(T) - case u(U) - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - if let t = try? container.decode(T.self) { - self = .t(t) - } else if let u = try? container.decode(U.self) { - self = .u(u) - } else { - throw DecodingError.dataCorruptedError(in: container, debugDescription: "Data was neither \(T.self) nor \(U.self).") - } - } -} - -private struct MultipleDecodeOptionsTestType : Codable, Equatable { - enum EncodingOption: Equatable { - case string - case int - case float - } - - let value: String - let encodingOption: EncodingOption - - init(_ value: String, _ encodingOption: EncodingOption) { - self.value = value - self.encodingOption = encodingOption - } - - func encode(to encoder: any Encoder) throws { - var container = encoder.unkeyedContainer() - switch encodingOption { - case .string: try container.encode(value) - case .int: try container.encode(Int(value)!) - case .float: try container.encode(Float(value)!) - } - - } - - init(from decoder: any Decoder) throws { - var container = try decoder.unkeyedContainer() - if let int = try? container.decode(Int.self) { - value = "\(int)" - encodingOption = .int - } else if let float = try? container.decode(Float.self) { - value = "\(float)" - encodingOption = .float - } else { - value = try container.decode(String.self) - encodingOption = .string - } - } -} - -// MARK: - Helper Class - -class XMLOnlyEncoder : PropertyListEncoder, @unchecked Sendable { - override var outputFormat: PropertyListDecoder.PropertyListFormat { - get { return .xml } - set { } - } -} diff --git a/Tests/FoundationEssentialsTests/ResourceUtilities.swift b/Tests/FoundationEssentialsTests/ResourceUtilities.swift deleted file mode 100644 index 57247e74a..000000000 --- a/Tests/FoundationEssentialsTests/ResourceUtilities.swift +++ /dev/null @@ -1,83 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(Glibc) -@preconcurrency import Glibc -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#else -@testable import FoundationEssentials -#endif // FOUNDATION_FRAMEWORK - -#if FOUNDATION_FRAMEWORK -// Always compiled into the Tests project -final internal class Canary { } -#endif - -func testData(forResource resource: String, withExtension ext: String, subdirectory: String? = nil) -> Data? { -#if FOUNDATION_FRAMEWORK - guard let url = Bundle(for: Canary.self).url(forResource: resource, withExtension: ext, subdirectory: subdirectory) else { - return nil - } - return try? Data(contentsOf: url) -#else -#if os(macOS) - let subdir: String - if let subdirectory { - subdir = "Resources/" + subdirectory - } else { - subdir = "Resources" - } - - guard let url = Bundle.module.url(forResource: resource, withExtension: ext, subdirectory: subdir) else { - return nil - } - - let essentialsURL = FoundationEssentials.URL(filePath: url.path) - - return try? Data(contentsOf: essentialsURL) -#else - // swiftpm drops the resources next to the executable, at: - // ./swift-foundation_FoundationEssentialsTests.resources/Resources/ - // Hard-coding the path is unfortunate, but a temporary need until we have a better way to handle this - - var toolsResourcesDir = URL(filePath: ProcessInfo.processInfo.arguments[0]) - .deletingLastPathComponent() - .appending(component: "swift-foundation_FoundationEssentialsTests-tool.resources", directoryHint: .isDirectory) - - // On Linux the tests are built for the "host" because there are macro tests, on Windows - // the tests are only built for the "target" so we need to figure out whether `-tools` - // resources exist and if so, use them. - let resourcesDir = if FileManager.default.fileExists(atPath: toolsResourcesDir.path) { - toolsResourcesDir - } else { - URL(filePath: ProcessInfo.processInfo.arguments[0]) - .deletingLastPathComponent() - .appending(component: "swift-foundation_FoundationEssentialsTests.resources", directoryHint: .isDirectory) - } - - var path = resourcesDir.appending(component: "Resources", directoryHint: .isDirectory) - if let subdirectory { - path.append(path: subdirectory, directoryHint: .isDirectory) - } - path.append(component: resource + "." + ext, directoryHint: .notDirectory) - return try? Data(contentsOf: path) -#endif -#endif -} diff --git a/Tests/FoundationEssentialsTests/Resources/Generic_XML_Properties.plist b/Tests/FoundationEssentialsTests/Resources/Generic_XML_Properties.plist deleted file mode 100644 index fbd2c390a..000000000 --- a/Tests/FoundationEssentialsTests/Resources/Generic_XML_Properties.plist +++ /dev/null @@ -1,20 +0,0 @@ - - - - - array1 - - arr0 - 42 - - 1976-04-01T12:00:00Z - - qrvM3QARIjM= - - - item1 - value1 - item2 - value2 - - diff --git a/Tests/FoundationEssentialsTests/Resources/Generic_XML_Properties_Binary.plist b/Tests/FoundationEssentialsTests/Resources/Generic_XML_Properties_Binary.plist deleted file mode 100644 index 149c0e359..000000000 Binary files a/Tests/FoundationEssentialsTests/Resources/Generic_XML_Properties_Binary.plist and /dev/null differ diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail1.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail1.json deleted file mode 100644 index 6216b865f..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail1.json +++ /dev/null @@ -1 +0,0 @@ -"A JSON payload should be an object or array, not a string." \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail10.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail10.json deleted file mode 100644 index 5d8c0047b..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail10.json +++ /dev/null @@ -1 +0,0 @@ -{"Extra value after close": true} "misplaced quoted value" \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail11.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail11.json deleted file mode 100644 index 76eb95b45..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail11.json +++ /dev/null @@ -1 +0,0 @@ -{"Illegal expression": 1 + 2} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail12.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail12.json deleted file mode 100644 index 77580a452..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail12.json +++ /dev/null @@ -1 +0,0 @@ -{"Illegal invocation": alert()} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail13.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail13.json deleted file mode 100644 index 379406b59..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail13.json +++ /dev/null @@ -1 +0,0 @@ -{"Numbers cannot have leading zeroes": 013} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail14.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail14.json deleted file mode 100644 index 0ed366b38..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail14.json +++ /dev/null @@ -1 +0,0 @@ -{"Numbers cannot be hex": 0x14} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail15.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail15.json deleted file mode 100644 index fc8376b60..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail15.json +++ /dev/null @@ -1 +0,0 @@ -["Illegal backslash escape: \x15"] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail16.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail16.json deleted file mode 100644 index 3fe21d4b5..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail16.json +++ /dev/null @@ -1 +0,0 @@ -[\naked] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail17.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail17.json deleted file mode 100644 index 62b9214ae..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail17.json +++ /dev/null @@ -1 +0,0 @@ -["Illegal backslash escape: \017"] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail18.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail18.json deleted file mode 100644 index 9bb89e2d6..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail18.json +++ /dev/null @@ -1 +0,0 @@ -["no" "seperator"] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail19.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail19.json deleted file mode 100644 index 3b9c46fa9..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail19.json +++ /dev/null @@ -1 +0,0 @@ -{"Missing colon" null} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail2.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail2.json deleted file mode 100644 index 6b7c11e5a..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail2.json +++ /dev/null @@ -1 +0,0 @@ -["Unclosed array" \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail21.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail21.json deleted file mode 100644 index 62474573b..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail21.json +++ /dev/null @@ -1 +0,0 @@ -{"Comma instead of colon", null} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail22.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail22.json deleted file mode 100644 index a7752581b..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail22.json +++ /dev/null @@ -1 +0,0 @@ -["Colon instead of comma": false] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail23.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail23.json deleted file mode 100644 index 494add1ca..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail23.json +++ /dev/null @@ -1 +0,0 @@ -["Bad value", truth] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail24.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail24.json deleted file mode 100644 index caff239bf..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail24.json +++ /dev/null @@ -1 +0,0 @@ -['single quote'] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail25.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail25.json deleted file mode 100644 index 8b7ad23e0..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail25.json +++ /dev/null @@ -1 +0,0 @@ -[" tab character in string "] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail26.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail26.json deleted file mode 100644 index 845d26a6a..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail26.json +++ /dev/null @@ -1 +0,0 @@ -["tab\ character\ in\ string\ "] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail27.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail27.json deleted file mode 100644 index 6b01a2ca4..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail27.json +++ /dev/null @@ -1,2 +0,0 @@ -["line -break"] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail28.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail28.json deleted file mode 100644 index 621a0101c..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail28.json +++ /dev/null @@ -1,2 +0,0 @@ -["line\ -break"] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail29.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail29.json deleted file mode 100644 index 47ec421bb..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail29.json +++ /dev/null @@ -1 +0,0 @@ -[0e] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail3.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail3.json deleted file mode 100644 index 168c81eb7..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail3.json +++ /dev/null @@ -1 +0,0 @@ -{unquoted_key: "keys must be quoted"} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail30.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail30.json deleted file mode 100644 index 8ab0bc4b8..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail30.json +++ /dev/null @@ -1 +0,0 @@ -[0e+] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail31.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail31.json deleted file mode 100644 index 1cce602b5..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail31.json +++ /dev/null @@ -1 +0,0 @@ -[0e+-1] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail32.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail32.json deleted file mode 100644 index 45cba7396..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail32.json +++ /dev/null @@ -1 +0,0 @@ -{"Comma instead if closing brace": true, \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail33.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail33.json deleted file mode 100644 index ca5eb19dc..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail33.json +++ /dev/null @@ -1 +0,0 @@ -["mismatch"} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail34.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail34.json deleted file mode 100644 index 24b2606b8..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail34.json +++ /dev/null @@ -1 +0,0 @@ -["apple¹ÙÍø"] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail35.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail35.json deleted file mode 100644 index 9ee1d6ecd..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail35.json +++ /dev/null @@ -1 +0,0 @@ -{"end of string" : "hello \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail36.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail36.json deleted file mode 100644 index c2604b2b8..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail36.json +++ /dev/null @@ -1,2 +0,0 @@ -{"minus but no digits": -} - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail37.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail37.json deleted file mode 100644 index f8c50aab0..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail37.json +++ /dev/null @@ -1 +0,0 @@ -{"malformed number": -31ABCq42} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail38.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail38.json deleted file mode 100644 index 27941195a..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail38.json +++ /dev/null @@ -1,2 +0,0 @@ -{"malformed number":3.} - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail39.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail39.json deleted file mode 100644 index 0d276c7f1..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail39.json +++ /dev/null @@ -1 +0,0 @@ -{"early escape end": "42\u3", "foo": "bar"} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail4.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail4.json deleted file mode 100644 index ca5eb19dc..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail4.json +++ /dev/null @@ -1 +0,0 @@ -["mismatch"} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail40.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail40.json deleted file mode 100644 index 75ff12c89..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail40.json +++ /dev/null @@ -1,2 +0,0 @@ -{"invalid hex": "This is a test: \uAB9Q That was a test"} - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail41.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail41.json deleted file mode 100644 index 37906c9ae..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail41.json +++ /dev/null @@ -1 +0,0 @@ -{"eof":" \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail5.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail5.json deleted file mode 100644 index ddf3ce3d2..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail5.json +++ /dev/null @@ -1 +0,0 @@ -["double extra comma",,] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail6.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail6.json deleted file mode 100644 index ed91580e1..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail6.json +++ /dev/null @@ -1 +0,0 @@ -[ , "<-- missing value"] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail7.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail7.json deleted file mode 100644 index 8a96af3e4..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail7.json +++ /dev/null @@ -1 +0,0 @@ -["Comma after the close"], \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail8.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail8.json deleted file mode 100644 index b28479c6e..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail8.json +++ /dev/null @@ -1 +0,0 @@ -["Extra close"]] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail9.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail9.json deleted file mode 100644 index ca5eb19dc..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail9.json +++ /dev/null @@ -1 +0,0 @@ -["mismatch"} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/javascriptcore_tests.plist b/Tests/FoundationEssentialsTests/Resources/JSON/javascriptcore_tests.plist deleted file mode 100644 index 1b714cea7..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/javascriptcore_tests.plist +++ /dev/null @@ -1,2224 +0,0 @@ - - - - - - input - __null__ - fails - - - - input - - fails - - - - fails - - input - 1 - structure - 1 - - - fails - - input - -1 - structure - -1 - - - input - Infinity - fails - - - - input - NaN - fails - - - - fails - - input - null - structure - __null__ - - - input - undefined - fails - - - - fails - - input - {} - structure - - - - - input - ({}) - fails - - - - input - {a} - fails - - - - input - {a:} - fails - - - - input - {a:5} - fails - - - - input - {a:5,} - fails - - - - input - {\"a\"} - fails - - - - input - {\"a\":} - fails - - - - fails - - input - {\"a\":5} - structure - - a - 5 - - - - input - {\"a\":5,} - fails - - - - input - {\"a\":5,,} - fails - - - - input - {\"a\":5,\"a\",} - fails - - - - input - {\"a\":(5,\"a\"),} - fails - - - - fails - - input - [] - structure - - - - - fails - - input - [1] - structure - - 1 - - - - fails - - input - [1,] - structure - - 1 - - - - fails - - input - [1,2] - structure - - 1 - 2 - - - - input - [1,2,,] - fails - - - - input - [1,2,,4] - fails - - - - fails - - input - \"\" - structure - - - - fails - - input - \"'\" - structure - ' - - - fails - - input - \"a\" - structure - a - - - input - \"a\\" - fails - - - - input - \"a\z\" - fails - - - - input - \"a\z\" - fails - - - - fails - - input - \"a\\z\" - structure - a\z - - - fails - - input - \"a z\" - structure - a z - - - fails - - input - \"a\tz\" - structure - a z - - - input - \"a z\" - fails - - - - fails - - input - \"a\nz\" - structure - a z - - - input - \"a z\" - fails - - - - fails - - input - \"a\rz\" - structure - a z - - - fails - - input - \"a/z\" - structure - a/z - - - fails - - input - \"a\/z\" - structure - a/z - - - input - \"az\" - fails - - - - fails - - input - \"a\bz\" - structure - az - - - input - \"a z\" - fails - - - - fails - - input - \"a\rz\" - structure - a z - - - input - \"a\uz\" - fails - - - - input - \"a\u0z\" - fails - - - - input - \"a\u00z\" - fails - - - - input - \"a\u000z\" - fails - - - - fails - - input - \"a\u0000z\" - structure - a�z - - - fails - - input - \"a\u000Az\" - structure - a z - - - fails - - input - \"a\u000az\" - structure - a z - - - input - \"a\u000Gz\" - fails - - - - input - \"a\u000gz\" - fails - - - - fails - - input - \"a\u00A0z\" - structure - a z - - - fails - - input - \"a\u00a0z\" - structure - a z - - - input - \"a\u00G0z\" - fails - - - - input - \"a\u00g0z\" - fails - - - - fails - - input - \"a\u0A00z\" - structure - a਀z - - - fails - - input - \"a\u0a00z\" - structure - a਀z - - - input - \"a\u0G00z\" - fails - - - - input - \"a\u0g00z\" - fails - - - - fails - - input - \"a\uA000z\" - structure - aꀀz - - - fails - - input - \"a\ua000z\" - structure - aꀀz - - - input - \"a\uG000z\" - fails - - - - input - \"a\ug000z\" - fails - - - - input - 00 - fails - - - - input - 01 - fails - - - - input - 0.a - fails - - - - input - 0x0 - fails - - - - input - 2e1.3 - fails - - - - input - 2e-+10 - fails - - - - input - 2e+-10 - fails - - - - input - 2e3e4 - fails - - - - input - -01.0 - fails - - - - input - -01 - fails - - - - input - -01.a - fails - - - - input - 1.e1 - fails - - - - fails - - input - true - structure - - - - fails - - input - false - structure - - - - fails - - input - {\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"} - structure - - a - 1 - b - 2 - c - 3 - - - - fails - - input - {\"a\":\"1\",\"b\":\"2\",\"c\":\"3\",\"d\":45000000000,\"g\":0.0000045,\"h\":0,\"i\":0,\"j\":0.5,\"k\":0,\"l\":-0,\"m\":-0,\"n\":-0,\"o\":-0.5,\"p\":-4.5e-11,\"q\":-45000000000,\"e\":null,\"\":12,\"f\":[\"a\",\"b\",\"c\"],\"array\":[\"a\",\"b\",\"c\",null,null,{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"],[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"]]]} - structure - - a - 1 - b - 2 - c - 3 - d - 45000000000 - g - 0.0000045 - h - 0 - i - 0 - j - 0.5 - k - 0 - l - 0 - m - 0 - n - 0 - o - -0.5 - p - -4.5e-11 - q - -45000000000 - e - __null__ - - 12 - f - - a - b - c - - array - - a - b - c - __null__ - __null__ - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - - - - fails - - input - {\"a\":\"1\",\"b\":\"2\",\"c\":\"3\",\"d\":45000000000,\"g\":0.0000045,\"h\":0,\"i\":0,\"j\":0.5,\"k\":0,\"l\":-0,\"m\":-0,\"n\":-0,\"o\":-0.5,\"p\":-4.5e-11,\"q\":-45000000000,\"e\":null,\"\":12,\"f\":[\"a\",\"b\",\"c\"],\"array\":[\"a\",\"b\",\"c\",null,null,{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"],[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"]]]} - structure - - a - 1 - b - 2 - c - 3 - d - 45000000000 - g - 0.0000045 - h - 0 - i - 0 - j - 0.5 - k - 0 - l - 0 - m - 0 - n - 0 - o - -0.5 - p - -4.5e-11 - q - -45000000000 - e - __null__ - - 12 - f - - a - b - c - - array - - a - b - c - __null__ - __null__ - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - - - - fails - - input - { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" } - structure - - a - 1 - b - 2 - c - 3 - - - - fails - - input - { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\", \"d\": 45000000000, \"g\": 0.0000045, \"h\": 0, \"i\": 0, \"j\": 0.5, \"k\": 0, \"l\": -0, \"m\": -0, \"n\": -0, \"o\": -0.5, \"p\": -4.5e-11, \"q\": -45000000000, \"e\": null, \"\": 12, \"f\": [ \"a\", \"b\", \"c\" ], \"array\": [ \"a\", \"b\", \"c\", null, null, { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ], [ { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ] ] ] } - structure - - a - 1 - b - 2 - c - 3 - d - 45000000000 - g - 0.0000045 - h - 0 - i - 0 - j - 0.5 - k - 0 - l - 0 - m - 0 - n - 0 - o - -0.5 - p - -4.5e-11 - q - -45000000000 - e - __null__ - - 12 - f - - a - b - c - - array - - a - b - c - __null__ - __null__ - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - - - - fails - - input - { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\", \"d\": 45000000000, \"g\": 0.0000045, \"h\": 0, \"i\": 0, \"j\": 0.5, \"k\": 0, \"l\": -0, \"m\": -0, \"n\": -0, \"o\": -0.5, \"p\": -4.5e-11, \"q\": -45000000000, \"e\": null, \"\": 12, \"f\": [ \"a\", \"b\", \"c\" ], \"array\": [ \"a\", \"b\", \"c\", null, null, { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ], [ { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ] ] ] } - structure - - a - 1 - b - 2 - c - 3 - d - 45000000000 - g - 0.0000045 - h - 0 - i - 0 - j - 0.5 - k - 0 - l - 0 - m - 0 - n - 0 - o - -0.5 - p - -4.5e-11 - q - -45000000000 - e - __null__ - - 12 - f - - a - b - c - - array - - a - b - c - __null__ - __null__ - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - - - - fails - - input - { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" } - structure - - a - 1 - b - 2 - c - 3 - - - - fails - - input - { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\", \"d\": 45000000000, \"g\": 0.0000045, \"h\": 0, \"i\": 0, \"j\": 0.5, \"k\": 0, \"l\": -0, \"m\": -0, \"n\": -0, \"o\": -0.5, \"p\": -4.5e-11, \"q\": -45000000000, \"e\": null, \"\": 12, \"f\": [ \"a\", \"b\", \"c\" ], \"array\": [ \"a\", \"b\", \"c\", null, null, { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ], [ { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ] ] ] } - structure - - a - 1 - b - 2 - c - 3 - d - 45000000000 - g - 0.0000045 - h - 0 - i - 0 - j - 0.5 - k - 0 - l - 0 - m - 0 - n - 0 - o - -0.5 - p - -4.5e-11 - q - -45000000000 - e - __null__ - - 12 - f - - a - b - c - - array - - a - b - c - __null__ - __null__ - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - - - - fails - - input - { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\", \"d\": 45000000000, \"g\": 0.0000045, \"h\": 0, \"i\": 0, \"j\": 0.5, \"k\": 0, \"l\": -0, \"m\": -0, \"n\": -0, \"o\": -0.5, \"p\": -4.5e-11, \"q\": -45000000000, \"e\": null, \"\": 12, \"f\": [ \"a\", \"b\", \"c\" ], \"array\": [ \"a\", \"b\", \"c\", null, null, { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ], [ { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ] ] ] } - structure - - a - 1 - b - 2 - c - 3 - d - 45000000000 - g - 0.0000045 - h - 0 - i - 0 - j - 0.5 - k - 0 - l - 0 - m - 0 - n - 0 - o - -0.5 - p - -4.5e-11 - q - -45000000000 - e - __null__ - - 12 - f - - a - b - c - - array - - a - b - c - __null__ - __null__ - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - - - - fails - - input - { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" } - structure - - a - 1 - b - 2 - c - 3 - - - - fails - - input - { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\", \"d\": 45000000000, \"g\": 0.0000045, \"h\": 0, \"i\": 0, \"j\": 0.5, \"k\": 0, \"l\": -0, \"m\": -0, \"n\": -0, \"o\": -0.5, \"p\": -4.5e-11, \"q\": -45000000000, \"e\": null, \"\": 12, \"f\": [ \"a\", \"b\", \"c\" ], \"array\": [ \"a\", \"b\", \"c\", null, null, { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ], [ { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ] ] ] } - structure - - a - 1 - b - 2 - c - 3 - d - 45000000000 - g - 0.0000045 - h - 0 - i - 0 - j - 0.5 - k - 0 - l - 0 - m - 0 - n - 0 - o - -0.5 - p - -4.5e-11 - q - -45000000000 - e - __null__ - - 12 - f - - a - b - c - - array - - a - b - c - __null__ - __null__ - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - - - - fails - - input - { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\", \"d\": 45000000000, \"g\": 0.0000045, \"h\": 0, \"i\": 0, \"j\": 0.5, \"k\": 0, \"l\": -0, \"m\": -0, \"n\": -0, \"o\": -0.5, \"p\": -4.5e-11, \"q\": -45000000000, \"e\": null, \"\": 12, \"f\": [ \"a\", \"b\", \"c\" ], \"array\": [ \"a\", \"b\", \"c\", null, null, { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ], [ { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ] ] ] } - structure - - a - 1 - b - 2 - c - 3 - d - 45000000000 - g - 0.0000045 - h - 0 - i - 0 - j - 0.5 - k - 0 - l - 0 - m - 0 - n - 0 - o - -0.5 - p - -4.5e-11 - q - -45000000000 - e - __null__ - - 12 - f - - a - b - c - - array - - a - b - c - __null__ - __null__ - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - - - - fails - - input - { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" } - structure - - a - 1 - b - 2 - c - 3 - - - - fails - - input - { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\", \"d\": 45000000000, \"g\": 0.0000045, \"h\": 0, \"i\": 0, \"j\": 0.5, \"k\": 0, \"l\": -0, \"m\": -0, \"n\": -0, \"o\": -0.5, \"p\": -4.5e-11, \"q\": -45000000000, \"e\": null, \"\": 12, \"f\": [ \"a\", \"b\", \"c\" ], \"array\": [ \"a\", \"b\", \"c\", null, null, { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ], [ { \"a\": \"1\", \"b\": \"2\", \"c\": \"3\" }, [ \"a\", \"b\", \"c\" ] ] ] } - structure - - a - 1 - b - 2 - c - 3 - d - 45000000000 - g - 0.0000045 - h - 0 - i - 0 - j - 0.5 - k - 0 - l - 0 - m - 0 - n - 0 - o - -0.5 - p - -4.5e-11 - q - -45000000000 - e - __null__ - - 12 - f - - a - b - c - - array - - a - b - c - __null__ - __null__ - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - a - 1 - b - 2 - c - 3 - - - a - b - c - - - - - - - fails - - input - true - structure - - - - keyType - string - - - - fails - - input - false - structure - - - - keyType - string - - - - fails - - input - null - structure - - - __null__ - keyType - string - - - - fails - - input - 1 - structure - - - 1 - keyType - string - - - - fails - - input - 1.5 - structure - - - 1.5 - keyType - string - - - - fails - - input - \"a string\" - structure - - - a string - keyType - string - - - - fails - - input - [\"a\",\"b\",\"c\"] - structure - - - - - 0 - a - keyType - string - - - 1 - b - keyType - string - - - 2 - c - keyType - string - - - keyType - string - - - - fails - - input - [\"a\",\"b\",\"c\",null,null,{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"],[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"]]] - structure - - - - - 0 - a - keyType - string - - - 1 - b - keyType - string - - - 2 - c - keyType - string - - - 3 - __null__ - keyType - string - - - 4 - __null__ - keyType - string - - - 5 - - a - - a - 1 - keyType - string - - b - - b - 2 - keyType - string - - c - - c - 3 - keyType - string - - - keyType - string - - - 6 - - - 0 - a - keyType - string - - - 1 - b - keyType - string - - - 2 - c - keyType - string - - - keyType - string - - - 7 - - - 0 - - a - - a - 1 - keyType - string - - b - - b - 2 - keyType - string - - c - - c - 3 - keyType - string - - - keyType - string - - - 1 - - - 0 - a - keyType - string - - - 1 - b - keyType - string - - - 2 - c - keyType - string - - - keyType - string - - - keyType - string - - - keyType - string - - - - fails - - input - {\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"} - structure - - - - a - - a - 1 - keyType - string - - b - - b - 2 - keyType - string - - c - - c - 3 - keyType - string - - - keyType - string - - - - fails - - input - {\"a\":\"1\",\"b\":\"2\",\"c\":\"3\",\"d\":45000000000,\"g\":0.0000045,\"h\":0,\"i\":0,\"j\":0.5,\"k\":0,\"l\":-0,\"m\":-0,\"n\":-0,\"o\":-0.5,\"p\":-4.5e-11,\"q\":-45000000000,\"e\":null,\"\":12,\"f\":[\"a\",\"b\",\"c\"],\"array\":[\"a\",\"b\",\"c\",null,null,{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"],[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"]]]} - structure - - - - a - - a - 1 - keyType - string - - b - - b - 2 - keyType - string - - c - - c - 3 - keyType - string - - d - - d - 45000000000 - keyType - string - - g - - g - 0.0000045 - keyType - string - - h - - h - 0 - keyType - string - - i - - i - 0 - keyType - string - - j - - j - 0.5 - keyType - string - - k - - k - 0 - keyType - string - - l - - l - 0 - keyType - string - - m - - m - 0 - keyType - string - - n - - n - 0 - keyType - string - - o - - o - -0.5 - keyType - string - - p - - p - -4.5e-11 - keyType - string - - q - - q - -45000000000 - keyType - string - - e - - e - __null__ - keyType - string - - - - - 12 - keyType - string - - f - - f - - - 0 - a - keyType - string - - - 1 - b - keyType - string - - - 2 - c - keyType - string - - - keyType - string - - array - - array - - - 0 - a - keyType - string - - - 1 - b - keyType - string - - - 2 - c - keyType - string - - - 3 - __null__ - keyType - string - - - 4 - __null__ - keyType - string - - - 5 - - a - - a - 1 - keyType - string - - b - - b - 2 - keyType - string - - c - - c - 3 - keyType - string - - - keyType - string - - - 6 - - - 0 - a - keyType - string - - - 1 - b - keyType - string - - - 2 - c - keyType - string - - - keyType - string - - - 7 - - - 0 - - a - - a - 1 - keyType - string - - b - - b - 2 - keyType - string - - c - - c - 3 - keyType - string - - - keyType - string - - - 1 - - - 0 - a - keyType - string - - - 1 - b - keyType - string - - - 2 - c - keyType - string - - - keyType - string - - - keyType - string - - - keyType - string - - - keyType - string - - - - fails - - input - true - structure - __null__ - - - fails - - input - false - structure - __null__ - - - fails - - input - null - structure - __null__ - - - fails - - input - 1 - structure - __null__ - - - fails - - input - 1.5 - structure - __null__ - - - fails - - input - \"a string\" - structure - __null__ - - - fails - - input - [\"a\",\"b\",\"c\"] - structure - __null__ - - - fails - - input - [\"a\",\"b\",\"c\",null,null,{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"],[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"]]] - structure - __null__ - - - fails - - input - {\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"} - structure - __null__ - - - fails - - input - {\"a\":\"1\",\"b\":\"2\",\"c\":\"3\",\"d\":45000000000,\"g\":0.0000045,\"h\":0,\"i\":0,\"j\":0.5,\"k\":0,\"l\":-0,\"m\":-0,\"n\":-0,\"o\":-0.5,\"p\":-4.5e-11,\"q\":-45000000000,\"e\":null,\"\":12,\"f\":[\"a\",\"b\",\"c\"],\"array\":[\"a\",\"b\",\"c\",null,null,{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"],[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"]]]} - structure - __null__ - - - fails - - input - true - structure - :true - - - fails - - input - false - structure - :false - - - fails - - input - null - structure - :null - - - fails - - input - 1 - structure - :1 - - - fails - - input - 1.5 - structure - :1.5 - - - fails - - input - \"a string\" - structure - :\"a string\" - - - fails - - input - [\"a\",\"b\",\"c\"] - structure - 0:\"a\"1:\"b\"2:\"c\":[null,null,null] - - - fails - - input - [\"a\",\"b\",\"c\",null,null,{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"],[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"]]] - structure - 0:\"a\"1:\"b\"2:\"c\"3:null4:nulla:\"1\"b:\"2\"c:\"3\"5:{\"a\":null,\"b\":null,\"c\":null}0:\"a\"1:\"b\"2:\"c\"6:[null,null,null]a:\"1\"b:\"2\"c:\"3\"0:{\"a\":null,\"b\":null,\"c\":null}0:\"a\"1:\"b\"2:\"c\"1:[null,null,null]7:[null,null]:[null,null,null,null,null,null,null,null] - - - fails - - input - {\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"} - structure - a:\"1\"b:\"2\"c:\"3\":{\"a\":null,\"b\":null,\"c\":null} - - - fails - - input - {\"a\":\"1\",\"b\":\"2\",\"c\":\"3\",\"d\":45000000000,\"g\":0.0000045,\"h\":0,\"i\":0,\"j\":0.5,\"k\":0,\"l\":-0,\"m\":-0,\"n\":-0,\"o\":-0.5,\"p\":-4.5e-11,\"q\":-45000000000,\"e\":null,\"\":12,\"f\":[\"a\",\"b\",\"c\"],\"array\":[\"a\",\"b\",\"c\",null,null,{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"],[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"]]]} - structure - a:\"1\"b:\"2\"c:\"3\"d:45000000000g:0.0000045h:0i:0j:0.5k:0l:-0m:-0n:-0o:-0.5p:-4.5e-11q:-45000000000e:null:120:\"a\"1:\"b\"2:\"c\"f:[null,null,null]0:\"a\"1:\"b\"2:\"c\"3:null4:nulla:\"1\"b:\"2\"c:\"3\"5:{\"a\":null,\"b\":null,\"c\":null}0:\"a\"1:\"b\"2:\"c\"6:[null,null,null]a:\"1\"b:\"2\"c:\"3\"0:{\"a\":null,\"b\":null,\"c\":null}0:\"a\"1:\"b\"2:\"c\"1:[null,null,null]7:[null,null]array:[null,null,null,null,null,null,null,null]:{\"a\":null,\"b\":null,\"c\":null,\"d\":null,\"g\":null,\"h\":null,\"i\":null,\"j\":null,\"k\":null,\"l\":null,\"m\":null,\"n\":null,\"o\":null,\"p\":null,\"q\":null,\"e\":null,\"\":null,\"f\":null,\"array\":null} - - - input - [\"a\",\"b\",\"c\",null,null,{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"],[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"]]] - fails - - - - fails - - input - {\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"} - structure - __null__ - - - input - {\"a\":\"1\",\"b\":\"2\",\"c\":\"3\",\"d\":45000000000,\"g\":0.0000045,\"h\":0,\"i\":0,\"j\":0.5,\"k\":0,\"l\":-0,\"m\":-0,\"n\":-0,\"o\":-0.5,\"p\":-4.5e-11,\"q\":-45000000000,\"e\":null,\"\":12,\"f\":[\"a\",\"b\",\"c\"],\"array\":[\"a\",\"b\",\"c\",null,null,{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"],[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"]]]} - fails - - - - fails - - input - [\"a\",\"b\",\"c\",null,null,{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"],[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"]]] - structure - 0:\"a\"1:\"b\"2:\"c\"3:null4:nulla:\"1\" - - - fails - - input - {\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"} - structure - a:\"1\"b:\"2\"c:\"3\":{\"a\":null,\"b\":null,\"c\":null} - - - fails - - input - {\"a\":\"1\",\"b\":\"2\",\"c\":\"3\",\"d\":45000000000,\"g\":0.0000045,\"h\":0,\"i\":0,\"j\":0.5,\"k\":0,\"l\":-0,\"m\":-0,\"n\":-0,\"o\":-0.5,\"p\":-4.5e-11,\"q\":-45000000000,\"e\":null,\"\":12,\"f\":[\"a\",\"b\",\"c\"],\"array\":[\"a\",\"b\",\"c\",null,null,{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"],[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"},[\"a\",\"b\",\"c\"]]]} - structure - a:\"1\"b:\"2\"c:\"3\"d:45000000000g:0.0000045h:0 - - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf16be.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf16be.json deleted file mode 100644 index 5e1567fcd..000000000 Binary files a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf16be.json and /dev/null differ diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf16be.plist b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf16be.plist deleted file mode 100644 index 68c4a7f06..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf16be.plist +++ /dev/null @@ -1,44 +0,0 @@ - - - - - glossary - - GlossDiv - - GlossList - - GlossEntry - - Abbrev - ISO 8879:1986 - Acronym - SGML - GlossDef - - GlossSeeAlso - - GML - XML - - para - A meta-markup language, used to create markup languages such as DocBook. - - GlossSee - markup - GlossTerm - Standard Generalized Markup Language - ID - SGML - SortAs - SGML - - - title - S - - title - example glossary - - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf16le.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf16le.json deleted file mode 100644 index 915f6c552..000000000 Binary files a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf16le.json and /dev/null differ diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf16le.plist b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf16le.plist deleted file mode 100644 index 68c4a7f06..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf16le.plist +++ /dev/null @@ -1,44 +0,0 @@ - - - - - glossary - - GlossDiv - - GlossList - - GlossEntry - - Abbrev - ISO 8879:1986 - Acronym - SGML - GlossDef - - GlossSeeAlso - - GML - XML - - para - A meta-markup language, used to create markup languages such as DocBook. - - GlossSee - markup - GlossTerm - Standard Generalized Markup Language - ID - SGML - SortAs - SGML - - - title - S - - title - example glossary - - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf32be.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf32be.json deleted file mode 100644 index 006adb7f6..000000000 Binary files a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf32be.json and /dev/null differ diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf32be.plist b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf32be.plist deleted file mode 100644 index 68c4a7f06..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf32be.plist +++ /dev/null @@ -1,44 +0,0 @@ - - - - - glossary - - GlossDiv - - GlossList - - GlossEntry - - Abbrev - ISO 8879:1986 - Acronym - SGML - GlossDef - - GlossSeeAlso - - GML - XML - - para - A meta-markup language, used to create markup languages such as DocBook. - - GlossSee - markup - GlossTerm - Standard Generalized Markup Language - ID - SGML - SortAs - SGML - - - title - S - - title - example glossary - - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf32le.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf32le.json deleted file mode 100644 index 897049809..000000000 Binary files a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf32le.json and /dev/null differ diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf32le.plist b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf32le.plist deleted file mode 100644 index 68c4a7f06..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf32le.plist +++ /dev/null @@ -1,44 +0,0 @@ - - - - - glossary - - GlossDiv - - GlossList - - GlossEntry - - Abbrev - ISO 8879:1986 - Acronym - SGML - GlossDef - - GlossSeeAlso - - GML - XML - - para - A meta-markup language, used to create markup languages such as DocBook. - - GlossSee - markup - GlossTerm - Standard Generalized Markup Language - ID - SGML - SortAs - SGML - - - title - S - - title - example glossary - - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf8.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf8.json deleted file mode 100644 index c8f1d8c61..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf8.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "glossary": { - "title": "example glossary", - "GlossDiv": { - "title": "S", - "GlossList": { - "GlossEntry": { - "ID": "SGML", - "SortAs": "SGML", - "GlossTerm": "Standard Generalized Markup Language", - "Acronym": "SGML", - "Abbrev": "ISO 8879:1986", - "GlossDef": { - "para": "A meta-markup language, used to create markup languages such as DocBook.", - "GlossSeeAlso": ["GML", "XML"] - }, - "GlossSee": "markup" - } - } - } - } -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf8.plist b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf8.plist deleted file mode 100644 index 68c4a7f06..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass1-utf8.plist +++ /dev/null @@ -1,44 +0,0 @@ - - - - - glossary - - GlossDiv - - GlossList - - GlossEntry - - Abbrev - ISO 8879:1986 - Acronym - SGML - GlossDef - - GlossSeeAlso - - GML - XML - - para - A meta-markup language, used to create markup languages such as DocBook. - - GlossSee - markup - GlossTerm - Standard Generalized Markup Language - ID - SGML - SortAs - SGML - - - title - S - - title - example glossary - - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass10.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass10.json deleted file mode 100644 index 4528d51f1..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass10.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "JSON Test Pattern pass3": { - "The outermost value": "must be an object or array.", - "In this test": "It is an object." - } -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass11.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass11.json deleted file mode 100644 index d40c64739..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass11.json +++ /dev/null @@ -1 +0,0 @@ -{"$t":"\"1\""} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass12.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass12.json deleted file mode 100644 index 4d506b08b..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass12.json +++ /dev/null @@ -1 +0,0 @@ -{"query":{"pages":{"80348":{"pageid":80348,"ns":0,"title":"\u866b","langlinks":[{"lang":"oc","*":"V\u00e8rm"}]}}}} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass13.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass13.json deleted file mode 100644 index 2cc6f2d55..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass13.json +++ /dev/null @@ -1 +0,0 @@ -{"a":1, "a":1} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass13.plist b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass13.plist deleted file mode 100644 index 3d66b9fef..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass13.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - a - 1 - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass14.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass14.json deleted file mode 100644 index 4b90b75e6..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass14.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "a2": - { - "x": - { - "abcdef\/":"c" - } - }, - "abcdefg": - { - "y": - { - "abcdef\/":"a", - "abcdefg":"b" - } - } -} - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass14.plist b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass14.plist deleted file mode 100644 index 1f239968c..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass14.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - a2 - - x - - abcdef/ - c - - - abcdefg - - y - - abcdef/ - a - abcdefg - b - - - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass15.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass15.json deleted file mode 100644 index 0b1bc7bfb..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass15.json +++ /dev/null @@ -1 +0,0 @@ -{"attached":true,"class":"mobiplug.api.Device","errors":{"errors":[]},"gid":65,"id":{"class":"org.bson.types.ObjectId","inc":-1173779709,"machine":805607832,"new":false,"time":1356650722000,"timeSecond":1356650722},"mpid":"00000101:ZWAV:0000000000000004","name":"New","properties":{"mpid":"00000101:ZWAV:0000000000000004","type":"dimmer","dbo":{"_id":{"class":"org.bson.types.ObjectId","inc":-1173779709,"machine":805607832,"new":false,"time":1356650722000,"timeSecond":1356650722},"gid":65,"mpid":"00000101:ZWAV:0000000000000004","name":"New","type":"dimmer","version":0},"gid":65,"name":"New","state":{"apiTimestamp":"2013-01-03T00:58:08Z","attached":false,"class":"mobiplug.api.DeviceEvent","errors":{"errors":[]},"eventData":{"value":0.7024794},"gatewayTimestamp":"1970-01-01T00:00:00Z","gid":65,"id":{"class":"org.bson.types.ObjectId","inc":912584452,"machine":805602242,"new":false,"time":1357178318000,"timeSecond":1357178318},"mpid":"00000101:ZWAV:0000000000000004","properties":{"mpid":"00000101:ZWAV:0000000000000004","apiTimestamp":"2013-01-03T00:58:08Z","gatewayTimestamp":"1970-01-01T00:00:00Z","type":"dimmer","gid":65,"eventData":{"value":0.7024794},"dbo":null},"type":"dimmer","version":null,"errors":{"errors":[]}}},"state":{"apiTimestamp":"2013-01-03T00:58:08Z","attached":true,"class":"mobiplug.api.DeviceEvent","errors":{"errors":[]},"eventData":{"value":0.7024794},"gatewayTimestamp":"1970-01-01T00:00:00Z","gid":65,"id":{"class":"org.bson.types.ObjectId","inc":912584452,"machine":805602242,"new":false,"time":1357178318000,"timeSecond":1357178318},"mpid":"00000101:ZWAV:0000000000000004","properties":{"mpid":"00000101:ZWAV:0000000000000004","apiTimestamp":"2013-01-03T00:58:08Z","gatewayTimestamp":"1970-01-01T00:00:00Z","type":"dimmer","gid":65,"eventData":{"value":0.7024794},"dbo":null},"type":"dimmer","version":null,"errors":{"errors":[]}},"type":"dimmer","version":0,"errors":{"errors":[]}} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass2.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass2.json deleted file mode 100644 index 5600991a4..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass2.json +++ /dev/null @@ -1,11 +0,0 @@ -{"menu": { - "id": "file", - "value": "File", - "popup": { - "menuitem": [ - {"value": "New", "onclick": "CreateNewDoc()"}, - {"value": "Open", "onclick": "OpenDoc()"}, - {"value": "Close", "onclick": "CloseDoc()"} - ] - } -}} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass2.plist b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass2.plist deleted file mode 100644 index ddd8e34ca..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass2.plist +++ /dev/null @@ -1,37 +0,0 @@ - - - - - menu - - id - file - popup - - menuitem - - - onclick - CreateNewDoc() - value - New - - - onclick - OpenDoc() - value - Open - - - onclick - CloseDoc() - value - Close - - - - value - File - - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass3.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass3.json deleted file mode 100644 index 9b820d853..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass3.json +++ /dev/null @@ -1,26 +0,0 @@ -{"widget": { - "debug": "on", - "window": { - "title": "Sample Konfabulator Widget", - "name": "main_window", - "width": 500, - "height": 500 - }, - "image": { - "src": "Images/Sun.png", - "name": "sun1", - "hOffset": 250, - "vOffset": 250, - "alignment": "center" - }, - "text": { - "data": "Click Here", - "size": 36, - "style": "bold", - "name": "text1", - "hOffset": 250, - "vOffset": 100, - "alignment": "center", - "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" - } -}} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass3.plist b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass3.plist deleted file mode 100644 index 4ca28ef5e..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass3.plist +++ /dev/null @@ -1,54 +0,0 @@ - - - - - widget - - debug - on - image - - alignment - center - hOffset - 250 - name - sun1 - src - Images/Sun.png - vOffset - 250 - - text - - alignment - center - data - Click Here - hOffset - 250 - name - text1 - onMouseUp - sun1.opacity = (sun1.opacity / 100) * 90; - size - 36 - style - bold - vOffset - 100 - - window - - height - 500 - name - main_window - title - Sample Konfabulator Widget - width - 500 - - - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass4.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass4.json deleted file mode 100644 index d540b57f0..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass4.json +++ /dev/null @@ -1,88 +0,0 @@ -{"web-app": { - "servlet": [ - { - "servlet-name": "cofaxCDS", - "servlet-class": "org.cofax.cds.CDSServlet", - "init-param": { - "configGlossary:installationAt": "Philadelphia, PA", - "configGlossary:adminEmail": "ksm@pobox.com", - "configGlossary:poweredBy": "Cofax", - "configGlossary:poweredByIcon": "/images/cofax.gif", - "configGlossary:staticPath": "/content/static", - "templateProcessorClass": "org.cofax.WysiwygTemplate", - "templateLoaderClass": "org.cofax.FilesTemplateLoader", - "templatePath": "templates", - "templateOverridePath": "", - "defaultListTemplate": "listTemplate.htm", - "defaultFileTemplate": "articleTemplate.htm", - "useJSP": false, - "jspListTemplate": "listTemplate.jsp", - "jspFileTemplate": "articleTemplate.jsp", - "cachePackageTagsTrack": 200, - "cachePackageTagsStore": 200, - "cachePackageTagsRefresh": 60, - "cacheTemplatesTrack": 100, - "cacheTemplatesStore": 50, - "cacheTemplatesRefresh": 15, - "cachePagesTrack": 200, - "cachePagesStore": 100, - "cachePagesRefresh": 10, - "cachePagesDirtyRead": 10, - "searchEngineListTemplate": "forSearchEnginesList.htm", - "searchEngineFileTemplate": "forSearchEngines.htm", - "searchEngineRobotsDb": "WEB-INF/robots.db", - "useDataStore": true, - "dataStoreClass": "org.cofax.SqlDataStore", - "redirectionClass": "org.cofax.SqlRedirection", - "dataStoreName": "cofax", - "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver", - "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon", - "dataStoreUser": "sa", - "dataStorePassword": "dataStoreTestQuery", - "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';", - "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log", - "dataStoreInitConns": 10, - "dataStoreMaxConns": 100, - "dataStoreConnUsageLimit": 100, - "dataStoreLogLevel": "debug", - "maxUrlLength": 500}}, - { - "servlet-name": "cofaxEmail", - "servlet-class": "org.cofax.cds.EmailServlet", - "init-param": { - "mailHost": "mail1", - "mailHostOverride": "mail2"}}, - { - "servlet-name": "cofaxAdmin", - "servlet-class": "org.cofax.cds.AdminServlet"}, - - { - "servlet-name": "fileServlet", - "servlet-class": "org.cofax.cds.FileServlet"}, - { - "servlet-name": "cofaxTools", - "servlet-class": "org.cofax.cms.CofaxToolsServlet", - "init-param": { - "templatePath": "toolstemplates/", - "log": 1, - "logLocation": "/usr/local/tomcat/logs/CofaxTools.log", - "logMaxSize": "", - "dataLog": 1, - "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log", - "dataLogMaxSize": "", - "removePageCache": "/content/admin/remove?cache=pages&id=", - "removeTemplateCache": "/content/admin/remove?cache=templates&id=", - "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder", - "lookInContext": 1, - "adminGroupID": 4, - "betaServer": true}}], - "servlet-mapping": { - "cofaxCDS": "/", - "cofaxEmail": "/cofaxutil/aemail/*", - "cofaxAdmin": "/admin/*", - "fileServlet": "/static/*", - "cofaxTools": "/tools/*"}, - - "taglib": { - "taglib-uri": "cofax.tld", - "taglib-location": "/WEB-INF/tlds/cofax.tld"}}} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass4.plist b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass4.plist deleted file mode 100644 index a4ad2cbcb..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass4.plist +++ /dev/null @@ -1,185 +0,0 @@ - - - - - web-app - - servlet - - - init-param - - cachePackageTagsRefresh - 60 - cachePackageTagsStore - 200 - cachePackageTagsTrack - 200 - cachePagesDirtyRead - 10 - cachePagesRefresh - 10 - cachePagesStore - 100 - cachePagesTrack - 200 - cacheTemplatesRefresh - 15 - cacheTemplatesStore - 50 - cacheTemplatesTrack - 100 - configGlossary:adminEmail - ksm@pobox.com - configGlossary:installationAt - Philadelphia, PA - configGlossary:poweredBy - Cofax - configGlossary:poweredByIcon - /images/cofax.gif - configGlossary:staticPath - /content/static - dataStoreClass - org.cofax.SqlDataStore - dataStoreConnUsageLimit - 100 - dataStoreDriver - com.microsoft.jdbc.sqlserver.SQLServerDriver - dataStoreInitConns - 10 - dataStoreLogFile - /usr/local/tomcat/logs/datastore.log - dataStoreLogLevel - debug - dataStoreMaxConns - 100 - dataStoreName - cofax - dataStorePassword - dataStoreTestQuery - dataStoreTestQuery - SET NOCOUNT ON;select test='test'; - dataStoreUrl - jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon - dataStoreUser - sa - defaultFileTemplate - articleTemplate.htm - defaultListTemplate - listTemplate.htm - jspFileTemplate - articleTemplate.jsp - jspListTemplate - listTemplate.jsp - maxUrlLength - 500 - redirectionClass - org.cofax.SqlRedirection - searchEngineFileTemplate - forSearchEngines.htm - searchEngineListTemplate - forSearchEnginesList.htm - searchEngineRobotsDb - WEB-INF/robots.db - templateLoaderClass - org.cofax.FilesTemplateLoader - templateOverridePath - - templatePath - templates - templateProcessorClass - org.cofax.WysiwygTemplate - useDataStore - - useJSP - - - servlet-class - org.cofax.cds.CDSServlet - servlet-name - cofaxCDS - - - init-param - - mailHost - mail1 - mailHostOverride - mail2 - - servlet-class - org.cofax.cds.EmailServlet - servlet-name - cofaxEmail - - - servlet-class - org.cofax.cds.AdminServlet - servlet-name - cofaxAdmin - - - servlet-class - org.cofax.cds.FileServlet - servlet-name - fileServlet - - - init-param - - adminGroupID - 4 - betaServer - - dataLog - 1 - dataLogLocation - /usr/local/tomcat/logs/dataLog.log - dataLogMaxSize - - fileTransferFolder - /usr/local/tomcat/webapps/content/fileTransferFolder - log - 1 - logLocation - /usr/local/tomcat/logs/CofaxTools.log - logMaxSize - - lookInContext - 1 - removePageCache - /content/admin/remove?cache=pages&id= - removeTemplateCache - /content/admin/remove?cache=templates&id= - templatePath - toolstemplates/ - - servlet-class - org.cofax.cms.CofaxToolsServlet - servlet-name - cofaxTools - - - servlet-mapping - - cofaxAdmin - /admin/* - cofaxCDS - / - cofaxEmail - /cofaxutil/aemail/* - cofaxTools - /tools/* - fileServlet - /static/* - - taglib - - taglib-location - /WEB-INF/tlds/cofax.tld - taglib-uri - cofax.tld - - - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass5.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass5.json deleted file mode 100644 index 8454dc278..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass5.json +++ /dev/null @@ -1,13 +0,0 @@ - { - "Image": { - "Width": 800, - "Height": 600, - "Title": "View from 15th Floor", - "Thumbnail": { - "Url": "http://www.example.com/image/481989943", - "Height": 125, - "Width": "100" - }, - "IDs": [116, 943, 234, 38793] - } - } \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass5.plist b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass5.plist deleted file mode 100644 index 738b4cab0..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass5.plist +++ /dev/null @@ -1,31 +0,0 @@ - - - - - Image - - Height - 600 - IDs - - 116 - 943 - 234 - 38793 - - Thumbnail - - Height - 125 - Url - http://www.example.com/image/481989943 - Width - 100 - - Title - View from 15th Floor - Width - 800 - - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass6.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass6.json deleted file mode 100644 index 29cc77620..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass6.json +++ /dev/null @@ -1,22 +0,0 @@ - [ - { - "precision": "zip", - "Latitude": 37.7668, - "Longitude": -122.3959, - "Address": "", - "City": "SAN FRANCISCO", - "State": "CA", - "Zip": "94107", - "Country": "US" - }, - { - "precision": "zip", - "Latitude": 37.371991, - "Longitude": -122.026020, - "Address": "", - "City": "SUNNYVALE", - "State": "CA", - "Zip": "94085", - "Country": "US" - } - ] diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass6.plist b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass6.plist deleted file mode 100644 index 2a11e8c08..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass6.plist +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - Address - - City - SAN FRANCISCO - Country - US - Latitude - 37.766800000000003 - Longitude - -122.39590000000001 - State - CA - Zip - 94107 - precision - zip - - - Address - - City - SUNNYVALE - Country - US - Latitude - 37.371991000000001 - Longitude - -122.02601999999999 - State - CA - Zip - 94085 - precision - zip - - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass7.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass7.json deleted file mode 100644 index 7cd3f07b5..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass7.json +++ /dev/null @@ -1,23 +0,0 @@ -{"menu": { - "header": "SVG Viewer", - "items": [ - {"id": "Open"}, - {"id": "OpenNew", "label": "Open New"}, - {"id": "ZoomIn", "label": "Zoom In"}, - {"id": "ZoomOut", "label": "Zoom Out"}, - {"id": "OriginalView", "label": "Original View"}, - {"id": "Quality"}, - {"id": "Pause"}, - {"id": "Mute"}, - {"id": "Find", "label": "Find..."}, - {"id": "FindAgain", "label": "Find Again"}, - {"id": "Copy"}, - {"id": "CopyAgain", "label": "Copy Again"}, - {"id": "CopySVG", "label": "Copy SVG"}, - {"id": "ViewSVG", "label": "View SVG"}, - {"id": "ViewSource", "label": "View Source"}, - {"id": "SaveAs", "label": "Save As"}, - {"id": "Help"}, - {"id": "About", "label": "About Adobe CVG Viewer..."} - ] -}} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass8.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass8.json deleted file mode 100644 index d3c63c7ad..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass8.json +++ /dev/null @@ -1 +0,0 @@ -[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass9.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass9.json deleted file mode 100644 index 70e268543..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass9.json +++ /dev/null @@ -1,58 +0,0 @@ -[ - "JSON Test Pattern pass1", - {"object with 1 member":["array with 1 element"]}, - {}, - [], - -42, - true, - false, - null, - { - "integer": 1234567890, - "real": -9876.543210, - "e": 0.123456789e-12, - "E": 1.234567890E+34, - "": 23456789012E66, - "zero": 0, - "one": 1, - "space": " ", - "quote": "\"", - "backslash": "\\", - "controls": "\b\f\n\r\t", - "slash": "/ & \/", - "alpha": "abcdefghijklmnopqrstuvwyz", - "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", - "digit": "0123456789", - "0123456789": "digit", - "special": "`1~!@#$%^&*()_+-={':[,]}|;.?", - "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", - "true": true, - "false": false, - "null": null, - "array":[ ], - "object":{ }, - "address": "50 St. James Street", - "url": "http://www.JSON.org/", - "comment": "// /* */": " ", - " s p a c e d " :[1,2 , 3 - -, - -4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], - "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", - "quotes": "" \u0022 %22 0x22 034 "", - "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" -: "A key can be any string" - }, - 0.5 ,98.6 -, -99.44 -, - -1066, -1e1, -0.1e1, -1e-1, -1e00,2e+00,2e-00 -,"rosebud"] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/example.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/pass/example.json5 deleted file mode 100644 index 1f8e7aea5..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/example.json5 +++ /dev/null @@ -1,13 +0,0 @@ -// https://json5.org -{ - // comments - unquoted: 'and you can quote me on that', - singleQuotes: 'I can use "double quotes" here', - lineBreaks: "Look, Mom! \ -No \\n's!", - hexadecimal: 0xdecaf, - leadingDecimalPoint: .8675309, andTrailing: 8675309., - positiveSign: +1, - trailingComma: 'in objects', andIn: ['arrays',], - "backwardsCompatible": "with JSON", -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/hex.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/pass/hex.json5 deleted file mode 100644 index 51a721aaf..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/hex.json5 +++ /dev/null @@ -1,4 +0,0 @@ -{ - "in": [1, 16, 15, 15, -10, -1, -16, 10, 12], - "out": [0x1, 0x10, 0xf, 0x0f, -0xa, -0x1, -0x10, 0xa, 0xc], -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/hex.plist b/Tests/FoundationEssentialsTests/Resources/JSON5/pass/hex.plist deleted file mode 100644 index 1c7be6e31..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/hex.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - out - - 1 - 16 - 15 - 15 - -10 - -1 - -16 - 10 - 12 - - in - - 1 - 16 - 15 - 15 - -10 - -1 - -16 - 10 - 12 - - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/numbers.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/pass/numbers.json5 deleted file mode 100644 index c65c7804c..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/numbers.json5 +++ /dev/null @@ -1,6 +0,0 @@ -{ - a: .0123, - b: 0.0123, - c: 10., - d: 10 -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/numbers.plist b/Tests/FoundationEssentialsTests/Resources/JSON5/pass/numbers.plist deleted file mode 100644 index de6a702fd..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/numbers.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - a - 0.0123 - b - 0.0123 - c - 10 - d - 10 - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/strings.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/pass/strings.json5 deleted file mode 100644 index 42f60cd86..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/strings.json5 +++ /dev/null @@ -1,7 +0,0 @@ -{ - "Hello" : "World", - 'Hello2' : 'World2', - "Hello3" : 'World3', - "hex1" : "hi\x7a", - "hex2" : "hi\x7a\x7a\x7aa", -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/strings.plist b/Tests/FoundationEssentialsTests/Resources/JSON5/pass/strings.plist deleted file mode 100644 index f66e81bba..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/strings.plist +++ /dev/null @@ -1,16 +0,0 @@ - - - - - Hello - World - Hello2 - World2 - Hello3 - World3 - hex1 - hiz - hex2 - hizzza - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/whitespace.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/pass/whitespace.json5 deleted file mode 100644 index 523dfafa1..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/whitespace.json5 +++ /dev/null @@ -1,5 +0,0 @@ -/*this is a comment at the start*/{ - "Hello" :/* this is an inline comment*/ "World" - // This is a comment in an object -}/*inline comment with ****** **/ -// This is a comment at the end \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/whitespace.plist b/Tests/FoundationEssentialsTests/Resources/JSON5/pass/whitespace.plist deleted file mode 100644 index 586225ed7..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/pass/whitespace.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - Hello - World - - diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/LICENSE.md b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/LICENSE.md deleted file mode 100644 index ae4049bbf..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2012-2016 Aseem Kishore, and [others](https://github.com/json5/json5/contributors). - -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: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/README.md b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/README.md deleted file mode 100644 index 76b9c81e5..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Parse Test Cases for JSON5 - -The test cases' file extension signals the expected behavior: - -- Valid JSON should remain valid JSON5. These cases have a `.json` extension - and are tested via `JSON.parse()`. - -- JSON5's new features should remain valid ES5. These cases have a `.json5` - extension are tested via `eval()`. - -- Valid ES5 that's explicitly disallowed by JSON5 is also invalid JSON. These - cases have a `.js` extension and are expected to fail. - -- Invalid ES5 should remain invalid JSON5. These cases have a `.txt` extension - and are expected to fail. - -This should cover all our bases. Most of the cases are unit tests for each -supported data type, but aggregate test cases are welcome, too. - -## License - -MIT. See [LICENSE.md](./LICENSE.md) for details. diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/empty-array.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/empty-array.json deleted file mode 100644 index 0637a088a..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/empty-array.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/leading-comma-array.js b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/leading-comma-array.js deleted file mode 100644 index 23c097c06..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/leading-comma-array.js +++ /dev/null @@ -1,3 +0,0 @@ -[ - ,null -] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/lone-trailing-comma-array.js b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/lone-trailing-comma-array.js deleted file mode 100644 index 013b45c5b..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/lone-trailing-comma-array.js +++ /dev/null @@ -1,3 +0,0 @@ -[ - , -] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/no-comma-array.errorSpec b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/no-comma-array.errorSpec deleted file mode 100644 index b476eca84..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/no-comma-array.errorSpec +++ /dev/null @@ -1,6 +0,0 @@ -{ - at: 16, - lineNumber: 3, - columnNumber: 5, - message: "Expected ']' instead of 'f'" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/no-comma-array.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/no-comma-array.txt deleted file mode 100644 index 22b41c10c..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/no-comma-array.txt +++ /dev/null @@ -1,4 +0,0 @@ -[ - true - false -] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/regular-array.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/regular-array.json deleted file mode 100644 index 907278029..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/regular-array.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - true, - false, - null -] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/trailing-comma-array.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/trailing-comma-array.json5 deleted file mode 100644 index 6e6b6ede5..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/arrays/trailing-comma-array.json5 +++ /dev/null @@ -1,3 +0,0 @@ -[ - null, -] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-following-array-element.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-following-array-element.json5 deleted file mode 100644 index 8677f63db..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-following-array-element.json5 +++ /dev/null @@ -1,6 +0,0 @@ -[ - false - /* - true - */ -] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-following-top-level-value.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-following-top-level-value.json5 deleted file mode 100644 index 1e6ccfd27..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-following-top-level-value.json5 +++ /dev/null @@ -1,5 +0,0 @@ -null -/* - Some non-comment top-level value is needed; - we use null above. -*/ \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-in-string.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-in-string.json deleted file mode 100644 index 7d2916c50..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-in-string.json +++ /dev/null @@ -1 +0,0 @@ -"This /* block comment */ isn't really a block comment." \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-preceding-top-level-value.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-preceding-top-level-value.json5 deleted file mode 100644 index df1e52044..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-preceding-top-level-value.json5 +++ /dev/null @@ -1,5 +0,0 @@ -/* - Some non-comment top-level value is needed; - we use null below. -*/ -null \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-with-asterisks.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-with-asterisks.json5 deleted file mode 100644 index 94c44e79e..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/block-comment-with-asterisks.json5 +++ /dev/null @@ -1,7 +0,0 @@ -/** - * This is a JavaDoc-like block comment. - * It contains asterisks inside of it. - * It might also be closed with multiple asterisks. - * Like this: - **/ -true \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/inline-comment-following-array-element.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/inline-comment-following-array-element.json5 deleted file mode 100644 index d6a3f8c64..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/inline-comment-following-array-element.json5 +++ /dev/null @@ -1,3 +0,0 @@ -[ - false // true -] \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/inline-comment-following-top-level-value.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/inline-comment-following-top-level-value.json5 deleted file mode 100644 index cf9ed019b..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/inline-comment-following-top-level-value.json5 +++ /dev/null @@ -1 +0,0 @@ -null // Some non-comment top-level value is needed; we use null here. \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/inline-comment-in-string.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/inline-comment-in-string.json deleted file mode 100644 index f0fb14f69..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/inline-comment-in-string.json +++ /dev/null @@ -1 +0,0 @@ -"This inline comment // isn't really an inline comment." \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/inline-comment-preceding-top-level-value.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/inline-comment-preceding-top-level-value.json5 deleted file mode 100644 index d4b9b4d13..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/inline-comment-preceding-top-level-value.json5 +++ /dev/null @@ -1,2 +0,0 @@ -// Some non-comment top-level value is needed; we use null below. -null \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/top-level-block-comment.errorSpec b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/top-level-block-comment.errorSpec deleted file mode 100644 index 9bf5cf517..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/top-level-block-comment.errorSpec +++ /dev/null @@ -1,6 +0,0 @@ -{ - at: 77, - lineNumber: 4, - columnNumber: 3, - message: "Unexpected EOF" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/top-level-block-comment.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/top-level-block-comment.txt deleted file mode 100644 index 7466bd2c0..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/top-level-block-comment.txt +++ /dev/null @@ -1,4 +0,0 @@ -/* - This should fail; - comments cannot be the only top-level value. -*/ \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/top-level-inline-comment.errorSpec b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/top-level-inline-comment.errorSpec deleted file mode 100644 index 3d915cd40..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/top-level-inline-comment.errorSpec +++ /dev/null @@ -1,6 +0,0 @@ -{ - at: 66, - lineNumber: 1, - columnNumber: 67, - message: "Unexpected EOF" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/top-level-inline-comment.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/top-level-inline-comment.txt deleted file mode 100644 index c5577f19d..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/top-level-inline-comment.txt +++ /dev/null @@ -1 +0,0 @@ -// This should fail; comments cannot be the only top-level value. \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/unterminated-block-comment.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/unterminated-block-comment.txt deleted file mode 100644 index 627b7bd17..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/comments/unterminated-block-comment.txt +++ /dev/null @@ -1,5 +0,0 @@ -true -/* - This block comment doesn't terminate. - There was a legitimate value before this, - but this is still invalid JS/JSON5. diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/empty.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/empty.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/npm-package.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/npm-package.json deleted file mode 100644 index 85568da17..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/npm-package.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "name": "npm", - "publishConfig": { - "proprietary-attribs": false - }, - "description": "A package manager for node", - "keywords": [ - "package manager", - "modules", - "install", - "package.json" - ], - "version": "1.1.22", - "preferGlobal": true, - "config": { - "publishtest": false - }, - "homepage": "http://npmjs.org/", - "author": "Isaac Z. Schlueter (http://blog.izs.me)", - "repository": { - "type": "git", - "url": "https://github.com/isaacs/npm" - }, - "bugs": { - "email": "npm-@googlegroups.com", - "url": "http://github.com/isaacs/npm/issues" - }, - "directories": { - "doc": "./doc", - "man": "./man", - "lib": "./lib", - "bin": "./bin" - }, - "main": "./lib/npm.js", - "bin": "./bin/npm-cli.js", - "dependencies": { - "semver": "~1.0.14", - "ini": "1", - "slide": "1", - "abbrev": "1", - "graceful-fs": "~1.1.1", - "minimatch": "~0.2", - "nopt": "1", - "node-uuid": "~1.3", - "proto-list": "1", - "rimraf": "2", - "request": "~2.9", - "which": "1", - "tar": "~0.1.12", - "fstream": "~0.1.17", - "block-stream": "*", - "inherits": "1", - "mkdirp": "0.3", - "read": "0", - "lru-cache": "1", - "node-gyp": "~0.4.1", - "fstream-npm": "0 >=0.0.5", - "uid-number": "0", - "archy": "0", - "chownr": "0" - }, - "bundleDependencies": [ - "slide", - "ini", - "semver", - "abbrev", - "graceful-fs", - "minimatch", - "nopt", - "node-uuid", - "rimraf", - "request", - "proto-list", - "which", - "tar", - "fstream", - "block-stream", - "inherits", - "mkdirp", - "read", - "lru-cache", - "node-gyp", - "fstream-npm", - "uid-number", - "archy", - "chownr" - ], - "devDependencies": { - "ronn": "https://github.com/isaacs/ronnjs/tarball/master" - }, - "engines": { - "node": "0.6 || 0.7 || 0.8", - "npm": "1" - }, - "scripts": { - "test": "node ./test/run.js", - "prepublish": "npm prune; rm -rf node_modules/*/{test,example,bench}*; make -j4 doc", - "dumpconf": "env | grep npm | sort | uniq" - }, - "licenses": [ - { - "type": "MIT +no-false-attribs", - "url": "http://github.com/isaacs/npm/raw/master/LICENSE" - } - ] -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/npm-package.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/npm-package.json5 deleted file mode 100644 index 699440659..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/npm-package.json5 +++ /dev/null @@ -1,106 +0,0 @@ -{ - name: 'npm', - publishConfig: { - 'proprietary-attribs': false, - }, - description: 'A package manager for node', - keywords: [ - 'package manager', - 'modules', - 'install', - 'package.json', - ], - version: '1.1.22', - preferGlobal: true, - config: { - publishtest: false, - }, - homepage: 'http://npmjs.org/', - author: 'Isaac Z. Schlueter (http://blog.izs.me)', - repository: { - type: 'git', - url: 'https://github.com/isaacs/npm', - }, - bugs: { - email: 'npm-@googlegroups.com', - url: 'http://github.com/isaacs/npm/issues', - }, - directories: { - doc: './doc', - man: './man', - lib: './lib', - bin: './bin', - }, - main: './lib/npm.js', - bin: './bin/npm-cli.js', - dependencies: { - semver: '~1.0.14', - ini: '1', - slide: '1', - abbrev: '1', - 'graceful-fs': '~1.1.1', - minimatch: '~0.2', - nopt: '1', - 'node-uuid': '~1.3', - 'proto-list': '1', - rimraf: '2', - request: '~2.9', - which: '1', - tar: '~0.1.12', - fstream: '~0.1.17', - 'block-stream': '*', - inherits: '1', - mkdirp: '0.3', - read: '0', - 'lru-cache': '1', - 'node-gyp': '~0.4.1', - 'fstream-npm': '0 >=0.0.5', - 'uid-number': '0', - archy: '0', - chownr: '0', - }, - bundleDependencies: [ - 'slide', - 'ini', - 'semver', - 'abbrev', - 'graceful-fs', - 'minimatch', - 'nopt', - 'node-uuid', - 'rimraf', - 'request', - 'proto-list', - 'which', - 'tar', - 'fstream', - 'block-stream', - 'inherits', - 'mkdirp', - 'read', - 'lru-cache', - 'node-gyp', - 'fstream-npm', - 'uid-number', - 'archy', - 'chownr', - ], - devDependencies: { - ronn: 'https://github.com/isaacs/ronnjs/tarball/master', - }, - engines: { - node: '0.6 || 0.7 || 0.8', - npm: '1', - }, - scripts: { - test: 'node ./test/run.js', - prepublish: 'npm prune; rm -rf node_modules/*/{test,example,bench}*; make -j4 doc', - dumpconf: 'env | grep npm | sort | uniq', - }, - licenses: [ - { - type: 'MIT +no-false-attribs', - url: 'http://github.com/isaacs/npm/raw/master/LICENSE', - }, - ], -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/readme-example.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/readme-example.json5 deleted file mode 100644 index 25c920a3c..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/readme-example.json5 +++ /dev/null @@ -1,25 +0,0 @@ -{ - foo: 'bar', - while: true, - - this: 'is a \ -multi-line string', - - // this is an inline comment - here: 'is another', // inline comment - - /* this is a block comment - that continues on another line */ - - hex: 0xDEADbeef, - half: .5, - delta: +10, - to: Infinity, // and beyond! - - finally: 'a trailing comma', - oh: [ - "we shouldn't forget", - 'arrays can have', - 'trailing commas too', - ], -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/valid-whitespace.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/valid-whitespace.json5 deleted file mode 100644 index 5cb57d364..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/misc/valid-whitespace.json5 +++ /dev/null @@ -1,5 +0,0 @@ -{ - // An invalid form feed character (\x0c) has been entered before this comment. - // Be careful not to delete it. - "a": true -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/.editorconfig b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/.editorconfig deleted file mode 100644 index 1784f9e32..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/.editorconfig +++ /dev/null @@ -1,13 +0,0 @@ -# Since we're testing different representations of new lines, -# make sure the editor doesn't mangle line endings. -# Don't commit files in this directory unless you've checked -# their escaped new lines. - -[*-lf.*] -end_of_line = lf - -[*-cr.*] -end_of_line = cr - -[*-crlf.*] -end_of_line = crlf diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/.gitattributes b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/.gitattributes deleted file mode 100644 index 2b3eea695..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -# Since we're testing different representations of new lines, -# treat all tests in this folder as binary files. - -* binary diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/comment-cr.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/comment-cr.json5 deleted file mode 100644 index e55aff883..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/comment-cr.json5 +++ /dev/null @@ -1 +0,0 @@ -{ // This comment is terminated with `\r`. } \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/comment-crlf.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/comment-crlf.json5 deleted file mode 100644 index 3791ee6bd..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/comment-crlf.json5 +++ /dev/null @@ -1,3 +0,0 @@ -{ - // This comment is terminated with `\r\n`. -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/comment-lf.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/comment-lf.json5 deleted file mode 100644 index e17dd72c6..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/comment-lf.json5 +++ /dev/null @@ -1,3 +0,0 @@ -{ - // This comment is terminated with `\n`. -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/escaped-cr.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/escaped-cr.json5 deleted file mode 100644 index 38e55b6cc..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/escaped-cr.json5 +++ /dev/null @@ -1 +0,0 @@ -{ // the following string contains an escaped `\r` a: 'line 1 \ line 2' } \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/escaped-crlf.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/escaped-crlf.json5 deleted file mode 100644 index 7e3f1ce4d..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/escaped-crlf.json5 +++ /dev/null @@ -1,5 +0,0 @@ -{ - // the following string contains an escaped `\r\n` - a: 'line 1 \ -line 2' -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/escaped-lf.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/escaped-lf.json5 deleted file mode 100644 index 2235e8c7f..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/new-lines/escaped-lf.json5 +++ /dev/null @@ -1,5 +0,0 @@ -{ - // the following string contains an escaped `\n` - a: 'line 1 \ -line 2' -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-leading-decimal-point.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-leading-decimal-point.json5 deleted file mode 100644 index d6c9fff3d..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-leading-decimal-point.json5 +++ /dev/null @@ -1 +0,0 @@ -.5 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-leading-zero.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-leading-zero.json deleted file mode 100644 index 2eb3c4fe4..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-leading-zero.json +++ /dev/null @@ -1 +0,0 @@ -0.5 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-trailing-decimal-point-with-integer-exponent.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-trailing-decimal-point-with-integer-exponent.json5 deleted file mode 100644 index 70b872070..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-trailing-decimal-point-with-integer-exponent.json5 +++ /dev/null @@ -1 +0,0 @@ -5.e4 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-trailing-decimal-point.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-trailing-decimal-point.json5 deleted file mode 100644 index e4c8c3130..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-trailing-decimal-point.json5 +++ /dev/null @@ -1 +0,0 @@ -5. diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-with-integer-exponent.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-with-integer-exponent.json deleted file mode 100644 index 0e957c633..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float-with-integer-exponent.json +++ /dev/null @@ -1 +0,0 @@ -1.2e3 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float.json deleted file mode 100644 index 5625e59da..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/float.json +++ /dev/null @@ -1 +0,0 @@ -1.2 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal-empty.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal-empty.txt deleted file mode 100644 index ec687260b..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal-empty.txt +++ /dev/null @@ -1 +0,0 @@ -0x diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal-lowercase-letter.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal-lowercase-letter.json5 deleted file mode 100644 index 57e27eede..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal-lowercase-letter.json5 +++ /dev/null @@ -1 +0,0 @@ -0xc8 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal-uppercase-x.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal-uppercase-x.json5 deleted file mode 100644 index 1a35066be..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal-uppercase-x.json5 +++ /dev/null @@ -1 +0,0 @@ -0XC8 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal-with-integer-exponent.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal-with-integer-exponent.json5 deleted file mode 100644 index 3c2204af8..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal-with-integer-exponent.json5 +++ /dev/null @@ -1 +0,0 @@ -0xc8e4 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal.json5 deleted file mode 100644 index cf832ed1d..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/hexadecimal.json5 +++ /dev/null @@ -1 +0,0 @@ -0xC8 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/infinity.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/infinity.json5 deleted file mode 100644 index 3c62151db..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/infinity.json5 +++ /dev/null @@ -1 +0,0 @@ -Infinity diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-float-exponent.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-float-exponent.txt deleted file mode 100644 index fa0688c93..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-float-exponent.txt +++ /dev/null @@ -1 +0,0 @@ -1e2.3 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-hexadecimal-exponent.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-hexadecimal-exponent.txt deleted file mode 100644 index 0f58237dc..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-hexadecimal-exponent.txt +++ /dev/null @@ -1 +0,0 @@ -1e0x4 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-integer-exponent.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-integer-exponent.json deleted file mode 100644 index 0d5cde84b..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-integer-exponent.json +++ /dev/null @@ -1 +0,0 @@ -2e23 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-negative-float-exponent.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-negative-float-exponent.txt deleted file mode 100644 index 5be09158f..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-negative-float-exponent.txt +++ /dev/null @@ -1 +0,0 @@ -1e-2.3 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-negative-hexadecimal-exponent.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-negative-hexadecimal-exponent.txt deleted file mode 100644 index adeb2b983..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-negative-hexadecimal-exponent.txt +++ /dev/null @@ -1 +0,0 @@ -1e-0x4 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-negative-integer-exponent.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-negative-integer-exponent.json deleted file mode 100644 index 6118c3ecd..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-negative-integer-exponent.json +++ /dev/null @@ -1 +0,0 @@ -2e-23 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-negative-zero-integer-exponent.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-negative-zero-integer-exponent.json deleted file mode 100644 index eb67bf46c..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-negative-zero-integer-exponent.json +++ /dev/null @@ -1 +0,0 @@ -5e-0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-positive-float-exponent.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-positive-float-exponent.txt deleted file mode 100644 index f89d55ecf..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-positive-float-exponent.txt +++ /dev/null @@ -1 +0,0 @@ -1e+2.3 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-positive-hexadecimal-exponent.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-positive-hexadecimal-exponent.txt deleted file mode 100644 index a6c75d949..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-positive-hexadecimal-exponent.txt +++ /dev/null @@ -1 +0,0 @@ -1e+0x4 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-positive-integer-exponent.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-positive-integer-exponent.json deleted file mode 100644 index 90c0616f5..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-positive-integer-exponent.json +++ /dev/null @@ -1 +0,0 @@ -1e+2 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-positive-zero-integer-exponent.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-positive-zero-integer-exponent.json deleted file mode 100644 index 1d7002f9f..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-positive-zero-integer-exponent.json +++ /dev/null @@ -1 +0,0 @@ -5e+0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-zero-integer-exponent.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-zero-integer-exponent.json deleted file mode 100644 index a5e3196e3..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer-with-zero-integer-exponent.json +++ /dev/null @@ -1 +0,0 @@ -5e0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer.json deleted file mode 100644 index 60d3b2f4a..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/integer.json +++ /dev/null @@ -1 +0,0 @@ -15 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/lone-decimal-point.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/lone-decimal-point.txt deleted file mode 100644 index 9c558e357..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/lone-decimal-point.txt +++ /dev/null @@ -1 +0,0 @@ -. diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/nan.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/nan.json5 deleted file mode 100644 index 736991a13..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/nan.json5 +++ /dev/null @@ -1 +0,0 @@ -NaN diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-float-leading-decimal-point.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-float-leading-decimal-point.json5 deleted file mode 100644 index c6eaee5ce..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-float-leading-decimal-point.json5 +++ /dev/null @@ -1 +0,0 @@ --.5 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-float-leading-zero.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-float-leading-zero.json deleted file mode 100644 index e118203f3..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-float-leading-zero.json +++ /dev/null @@ -1 +0,0 @@ --0.5 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-float-trailing-decimal-point.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-float-trailing-decimal-point.json5 deleted file mode 100644 index 52e52459f..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-float-trailing-decimal-point.json5 +++ /dev/null @@ -1 +0,0 @@ --5. diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-float.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-float.json deleted file mode 100644 index 1d94c8a01..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-float.json +++ /dev/null @@ -1 +0,0 @@ --1.2 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-hexadecimal.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-hexadecimal.json5 deleted file mode 100644 index 8882fae36..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-hexadecimal.json5 +++ /dev/null @@ -1 +0,0 @@ --0xC8 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-infinity.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-infinity.json5 deleted file mode 100644 index 879e80ee3..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-infinity.json5 +++ /dev/null @@ -1 +0,0 @@ --Infinity diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-integer.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-integer.json deleted file mode 100644 index 21922364c..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-integer.json +++ /dev/null @@ -1 +0,0 @@ --15 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-noctal.js b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-noctal.js deleted file mode 100644 index 8826f4866..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-noctal.js +++ /dev/null @@ -1 +0,0 @@ --098 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-octal.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-octal.txt deleted file mode 100644 index 2e7a4b450..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-octal.txt +++ /dev/null @@ -1 +0,0 @@ --0123 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-float-leading-decimal-point.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-float-leading-decimal-point.json5 deleted file mode 100644 index 8dd8e037e..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-float-leading-decimal-point.json5 +++ /dev/null @@ -1 +0,0 @@ --.0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-float-trailing-decimal-point.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-float-trailing-decimal-point.json5 deleted file mode 100644 index 90cc048c5..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-float-trailing-decimal-point.json5 +++ /dev/null @@ -1 +0,0 @@ --0. diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-float.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-float.json deleted file mode 100644 index 1344bfd9d..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-float.json +++ /dev/null @@ -1 +0,0 @@ --0.0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-hexadecimal.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-hexadecimal.json5 deleted file mode 100644 index 8847d0524..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-hexadecimal.json5 +++ /dev/null @@ -1 +0,0 @@ --0x0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-integer.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-integer.json deleted file mode 100644 index ec064f61b..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-integer.json +++ /dev/null @@ -1 +0,0 @@ --0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-octal.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-octal.txt deleted file mode 100644 index 200a80184..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/negative-zero-octal.txt +++ /dev/null @@ -1 +0,0 @@ --00 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/noctal-with-leading-octal-digit.js b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/noctal-with-leading-octal-digit.js deleted file mode 100644 index 1fd7c08c1..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/noctal-with-leading-octal-digit.js +++ /dev/null @@ -1 +0,0 @@ -0780 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/noctal.js b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/noctal.js deleted file mode 100644 index fa5c7835b..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/noctal.js +++ /dev/null @@ -1 +0,0 @@ -080 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/octal.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/octal.txt deleted file mode 100644 index 9e8493eae..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/octal.txt +++ /dev/null @@ -1 +0,0 @@ -010 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-float-leading-decimal-point.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-float-leading-decimal-point.json5 deleted file mode 100644 index 043460803..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-float-leading-decimal-point.json5 +++ /dev/null @@ -1 +0,0 @@ -+.5 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-float-leading-zero.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-float-leading-zero.json5 deleted file mode 100644 index d89b45d16..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-float-leading-zero.json5 +++ /dev/null @@ -1 +0,0 @@ -+0.5 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-float-trailing-decimal-point.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-float-trailing-decimal-point.json5 deleted file mode 100644 index bee758a7b..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-float-trailing-decimal-point.json5 +++ /dev/null @@ -1 +0,0 @@ -+5. diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-float.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-float.json5 deleted file mode 100644 index c5732cbcf..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-float.json5 +++ /dev/null @@ -1 +0,0 @@ -+1.2 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-hexadecimal.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-hexadecimal.json5 deleted file mode 100644 index c91ede969..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-hexadecimal.json5 +++ /dev/null @@ -1 +0,0 @@ -+0xC8 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-infinity.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-infinity.json5 deleted file mode 100644 index 9bcb989f1..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-infinity.json5 +++ /dev/null @@ -1 +0,0 @@ -+Infinity diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-integer.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-integer.json5 deleted file mode 100644 index 8ed01e070..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-integer.json5 +++ /dev/null @@ -1 +0,0 @@ -+15 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-noctal.js b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-noctal.js deleted file mode 100644 index 2f450fce4..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-noctal.js +++ /dev/null @@ -1 +0,0 @@ -+098 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-octal.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-octal.txt deleted file mode 100644 index faa86009c..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-octal.txt +++ /dev/null @@ -1 +0,0 @@ -+0123 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-float-leading-decimal-point.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-float-leading-decimal-point.json5 deleted file mode 100644 index 557bcde17..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-float-leading-decimal-point.json5 +++ /dev/null @@ -1 +0,0 @@ -+.0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-float-trailing-decimal-point.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-float-trailing-decimal-point.json5 deleted file mode 100644 index d8912d161..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-float-trailing-decimal-point.json5 +++ /dev/null @@ -1 +0,0 @@ -+0. diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-float.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-float.json5 deleted file mode 100644 index 11e8402c5..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-float.json5 +++ /dev/null @@ -1 +0,0 @@ -+0.0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-hexadecimal.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-hexadecimal.json5 deleted file mode 100644 index 40a9ce637..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-hexadecimal.json5 +++ /dev/null @@ -1 +0,0 @@ -+0x0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-integer.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-integer.json5 deleted file mode 100644 index 9317bcb62..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-integer.json5 +++ /dev/null @@ -1 +0,0 @@ -+0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-octal.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-octal.txt deleted file mode 100644 index 80959e57a..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/positive-zero-octal.txt +++ /dev/null @@ -1 +0,0 @@ -+00 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-float-leading-decimal-point.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-float-leading-decimal-point.json5 deleted file mode 100644 index 7d856fdb3..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-float-leading-decimal-point.json5 +++ /dev/null @@ -1 +0,0 @@ -.0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-float-trailing-decimal-point.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-float-trailing-decimal-point.json5 deleted file mode 100644 index 17a5757b1..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-float-trailing-decimal-point.json5 +++ /dev/null @@ -1 +0,0 @@ -0. diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-float.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-float.json deleted file mode 100644 index ba66466c2..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-float.json +++ /dev/null @@ -1 +0,0 @@ -0.0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-hexadecimal.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-hexadecimal.json5 deleted file mode 100644 index 9982566dc..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-hexadecimal.json5 +++ /dev/null @@ -1 +0,0 @@ -0x0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-integer-with-integer-exponent.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-integer-with-integer-exponent.json deleted file mode 100644 index da219e3f1..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-integer-with-integer-exponent.json +++ /dev/null @@ -1 +0,0 @@ -0e23 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-integer.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-integer.json deleted file mode 100644 index 573541ac9..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-integer.json +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-octal.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-octal.txt deleted file mode 100644 index 4daddb72f..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/numbers/zero-octal.txt +++ /dev/null @@ -1 +0,0 @@ -00 diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/duplicate-keys.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/duplicate-keys.json deleted file mode 100644 index bb0e4cc3d..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/duplicate-keys.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "a": true, - "a": false -} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/empty-object.json b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/empty-object.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/empty-object.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/illegal-unquoted-key-number.errorSpec b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/illegal-unquoted-key-number.errorSpec deleted file mode 100644 index e44dc850d..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/illegal-unquoted-key-number.errorSpec +++ /dev/null @@ -1,6 +0,0 @@ -{ - at: 7, - lineNumber: 2, - columnNumber: 5, - message: "Bad identifier as unquoted key" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/illegal-unquoted-key-number.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/illegal-unquoted-key-number.txt deleted file mode 100644 index aebcac2cd..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/illegal-unquoted-key-number.txt +++ /dev/null @@ -1,3 +0,0 @@ -{ - 10twenty: "ten twenty" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/illegal-unquoted-key-symbol.errorSpec b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/illegal-unquoted-key-symbol.errorSpec deleted file mode 100644 index 95ba46831..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/illegal-unquoted-key-symbol.errorSpec +++ /dev/null @@ -1,6 +0,0 @@ -{ - at: 12, - lineNumber: 2, - columnNumber: 10, - message: "Expected ':' instead of '-'" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/illegal-unquoted-key-symbol.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/illegal-unquoted-key-symbol.txt deleted file mode 100644 index 4cb2bd5c0..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/illegal-unquoted-key-symbol.txt +++ /dev/null @@ -1,3 +0,0 @@ -{ - multi-word: "multi-word" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/leading-comma-object.errorSpec b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/leading-comma-object.errorSpec deleted file mode 100644 index e44dc850d..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/leading-comma-object.errorSpec +++ /dev/null @@ -1,6 +0,0 @@ -{ - at: 7, - lineNumber: 2, - columnNumber: 5, - message: "Bad identifier as unquoted key" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/leading-comma-object.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/leading-comma-object.txt deleted file mode 100644 index bfb3c51fa..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/leading-comma-object.txt +++ /dev/null @@ -1,3 +0,0 @@ -{ - ,"foo": "bar" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/lone-trailing-comma-object.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/lone-trailing-comma-object.txt deleted file mode 100644 index 3f3f9f796..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/lone-trailing-comma-object.txt +++ /dev/null @@ -1,3 +0,0 @@ -{ - , -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/no-comma-object.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/no-comma-object.txt deleted file mode 100644 index c0738750d..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/no-comma-object.txt +++ /dev/null @@ -1,4 +0,0 @@ -{ - "foo": "bar" - "hello": "world" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/reserved-unquoted-key.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/reserved-unquoted-key.json5 deleted file mode 100644 index 4b80a63b4..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/reserved-unquoted-key.json5 +++ /dev/null @@ -1,3 +0,0 @@ -{ - while: true -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/single-quoted-key.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/single-quoted-key.json5 deleted file mode 100644 index 842ca19c6..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/single-quoted-key.json5 +++ /dev/null @@ -1,3 +0,0 @@ -{ - 'hello': "world" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/trailing-comma-object.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/trailing-comma-object.json5 deleted file mode 100644 index ab61ba76e..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/trailing-comma-object.json5 +++ /dev/null @@ -1,3 +0,0 @@ -{ - "foo": "bar", -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/unquoted-keys.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/unquoted-keys.json5 deleted file mode 100644 index 0c06f3fc7..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/objects/unquoted-keys.json5 +++ /dev/null @@ -1,8 +0,0 @@ -{ - hello: "world", - _: "underscore", - $: "dollar sign", - one1: "numerals", - _$_: "multiple symbols", - $_$hello123world_$_: "mixed" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/escaped-single-quoted-string.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/escaped-single-quoted-string.json5 deleted file mode 100644 index 1c799101b..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/escaped-single-quoted-string.json5 +++ /dev/null @@ -1 +0,0 @@ -'I can\'t wait' \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/multi-line-string.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/multi-line-string.json5 deleted file mode 100644 index 964dc2dec..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/multi-line-string.json5 +++ /dev/null @@ -1,2 +0,0 @@ -'hello\ - world' \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/single-quoted-string.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/single-quoted-string.json5 deleted file mode 100644 index 5dadd333c..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/single-quoted-string.json5 +++ /dev/null @@ -1 +0,0 @@ -'hello world' \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/unescaped-multi-line-string.errorSpec b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/unescaped-multi-line-string.errorSpec deleted file mode 100644 index a85f1ad18..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/unescaped-multi-line-string.errorSpec +++ /dev/null @@ -1,6 +0,0 @@ -{ - at: 5, - lineNumber: 2, - columnNumber: 0, - message: "Bad string" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/unescaped-multi-line-string.txt b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/unescaped-multi-line-string.txt deleted file mode 100644 index 7325139a8..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/strings/unescaped-multi-line-string.txt +++ /dev/null @@ -1,2 +0,0 @@ -"foo -bar" diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/todo/unicode-escaped-unquoted-key.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/todo/unicode-escaped-unquoted-key.json5 deleted file mode 100644 index 56c345711..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/todo/unicode-escaped-unquoted-key.json5 +++ /dev/null @@ -1,3 +0,0 @@ -{ - sig\u03A3ma: "the sum of all things" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/todo/unicode-unquoted-key.json5 b/Tests/FoundationEssentialsTests/Resources/JSON5/spec/todo/unicode-unquoted-key.json5 deleted file mode 100644 index 98382e699..000000000 --- a/Tests/FoundationEssentialsTests/Resources/JSON5/spec/todo/unicode-unquoted-key.json5 +++ /dev/null @@ -1,3 +0,0 @@ -{ - ümlåût: "that's not really an ümlaüt, but this is" -} \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/Test_5616259.bad b/Tests/FoundationEssentialsTests/Resources/Test_5616259.bad deleted file mode 100644 index 8878c295d..000000000 --- a/Tests/FoundationEssentialsTests/Resources/Test_5616259.bad +++ /dev/null @@ -1,16 +0,0 @@ - - - - - aBoolean - - aString - foobar - anArray - - alpha - beta - gamma - - - diff --git a/Tests/FoundationEssentialsTests/Resources/Test_82142612.bad b/Tests/FoundationEssentialsTests/Resources/Test_82142612.bad deleted file mode 100644 index 94353e8d9..000000000 Binary files a/Tests/FoundationEssentialsTests/Resources/Test_82142612.bad and /dev/null differ diff --git a/Tests/FoundationEssentialsTests/Resources/bad_plist.bad b/Tests/FoundationEssentialsTests/Resources/bad_plist.bad deleted file mode 100644 index c0969a814..000000000 --- a/Tests/FoundationEssentialsTests/Resources/bad_plist.bad +++ /dev/null @@ -1 +0,0 @@ - CFBundleVersion 2.5.2 CFBundleShortVersionString2.5.2 CFBundleGetInfoString Constructor v2.5.2, a Metrowerks CodeWarriorª Component, ©1993-2001 Metrowerks Corporation CFBundleName Constructor CFBundleSignature MWC2 CFBundlePackageType APPL CFBundleIconFile 128 CFBundleIdentifier com.metrowerks.Constructor CFBundleDocumentTypes CFBundleTypeName Constructor project CFBundleTypeIconFile 129 CFBundleTypeRole Editor CFBundleTypeOSTypes rsrc CFBundleTypeExtentions ppob rsrc ctyp CFBundleTypeName Constructor preferences CFBundleTypeIconFile 130 CFBundleTypeRole None CFBundleTypeOSTypes pref CFBundleDevelopmentRegionEnglish CFBundleInfoDictionaryVersion6.0 LSPrefersCarbon \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/test_oldStylePlist_getSlashedChars_octal.plist b/Tests/FoundationEssentialsTests/Resources/test_oldStylePlist_getSlashedChars_octal.plist deleted file mode 100644 index d3e09f506..000000000 --- a/Tests/FoundationEssentialsTests/Resources/test_oldStylePlist_getSlashedChars_octal.plist +++ /dev/null @@ -1 +0,0 @@ -('\0','\00','\000','\1','\01','\001','\2','\02','\002','\3','\03','\003','\4','\04','\004','\5','\05','\005','\6','\06','\006','\7','\07','\007','\10','\010','\11','\011','\12','\012','\13','\013','\14','\014','\15','\015','\16','\016','\17','\017','\20','\020','\21','\021','\22','\022','\23','\023','\24','\024','\25','\025','\26','\026','\27','\027','\30','\030','\31','\031','\32','\032','\33','\033','\34','\034','\35','\035','\36','\036','\37','\037','\40','\040','\41','\041','\42','\042','\43','\043','\44','\044','\45','\045','\46','\046','\47','\047','\50','\050','\51','\051','\52','\052','\53','\053','\54','\054','\55','\055','\56','\056','\57','\057','\60','\060','\61','\061','\62','\062','\63','\063','\64','\064','\65','\065','\66','\066','\67','\067','\70','\070','\71','\071','\72','\072','\73','\073','\74','\074','\75','\075','\76','\076','\77','\077','\100','\101','\102','\103','\104','\105','\106','\107','\110','\111','\112','\113','\114','\115','\116','\117','\120','\121','\122','\123','\124','\125','\126','\127','\130','\131','\132','\133','\134','\135','\136','\137','\140','\141','\142','\143','\144','\145','\146','\147','\150','\151','\152','\153','\154','\155','\156','\157','\160','\161','\162','\163','\164','\165','\166','\167','\170','\171','\172','\173','\174','\175','\176','\177','\200','\201','\202','\203','\204','\205','\206','\207','\210','\211','\212','\213','\214','\215','\216','\217','\220','\221','\222','\223','\224','\225','\226','\227','\230','\231','\232','\233','\234','\235','\236','\237','\240','\241','\242','\243','\244','\245','\246','\247','\250','\251','\252','\253','\254','\255','\256','\257','\260','\261','\262','\263','\264','\265','\266','\267','\270','\271','\272','\273','\274','\275','\276','\277','\300','\301','\302','\303','\304','\305','\306','\307','\310','\311','\312','\313','\314','\315','\316','\317','\320','\321','\322','\323','\324','\325','\326','\327','\330','\331','\332','\333','\334','\335','\336','\337','\340','\341','\342','\343','\344','\345','\346','\347','\350','\351','\352','\353','\354','\355','\356','\357','\360','\361','\362','\363','\364','\365','\366','\367','\370','\371','\372','\373','\374','\375','\400','\401','\402','\403','\404','\405','\406','\407','\410','\411','\412','\413','\414','\415','\416','\417','\420','\421','\422','\423','\424','\425','\426','\427','\430','\431','\432','\433','\434','\435','\436','\437','\440','\441','\442','\443','\444','\445','\446','\447','\450','\451','\452','\453','\454','\455','\456','\457','\460','\461','\462','\463','\464','\465','\466','\467','\470','\471','\472','\473','\474','\475','\476','\477','\500','\501','\502','\503','\504','\505','\506','\507','\510','\511','\512','\513','\514','\515','\516','\517','\520','\521','\522','\523','\524','\525','\526','\527','\530','\531','\532','\533','\534','\535','\536','\537','\540','\541','\542','\543','\544','\545','\546','\547','\550','\551','\552','\553','\554','\555','\556','\557','\560','\561','\562','\563','\564','\565','\566','\567','\570','\571','\572','\573','\574','\575','\576','\577','\600','\601','\602','\603','\604','\605','\606','\607','\610','\611','\612','\613','\614','\615','\616','\617','\620','\621','\622','\623','\624','\625','\626','\627','\630','\631','\632','\633','\634','\635','\636','\637','\640','\641','\642','\643','\644','\645','\646','\647','\650','\651','\652','\653','\654','\655','\656','\657','\660','\661','\662','\663','\664','\665','\666','\667','\670','\671','\672','\673','\674','\675','\676','\677','\700','\701','\702','\703','\704','\705','\706','\707','\710','\711','\712','\713','\714','\715','\716','\717','\720','\721','\722','\723','\724','\725','\726','\727','\730','\731','\732','\733','\734','\735','\736','\737','\740','\741','\742','\743','\744','\745','\746','\747','\750','\751','\752','\753','\754','\755','\756','\757','\760','\761','\762','\763','\764','\765','\766','\767','\770','\771','\772','\773','\774','\775',) \ No newline at end of file diff --git a/Tests/FoundationEssentialsTests/Resources/test_oldStylePlist_getSlashedChars_octal_expected.plist b/Tests/FoundationEssentialsTests/Resources/test_oldStylePlist_getSlashedChars_octal_expected.plist deleted file mode 100644 index 1bf9b41f4..000000000 Binary files a/Tests/FoundationEssentialsTests/Resources/test_oldStylePlist_getSlashedChars_octal_expected.plist and /dev/null differ diff --git a/Tests/FoundationEssentialsTests/Resources/test_oldStylePlist_getSlashedChars_unicode.plist b/Tests/FoundationEssentialsTests/Resources/test_oldStylePlist_getSlashedChars_unicode.plist deleted file mode 100644 index 023076d33..000000000 --- a/Tests/FoundationEssentialsTests/Resources/test_oldStylePlist_getSlashedChars_unicode.plist +++ /dev/null @@ -1 +0,0 @@ -('\U0','\U00','\U000','\U0000','\U1','\U01','\U001','\U0001','\U2','\U02','\U002','\U0002','\U3','\U03','\U003','\U0003','\U4','\U04','\U004','\U0004','\U5','\U05','\U005','\U0005','\U6','\U06','\U006','\U0006','\U7','\U07','\U007','\U0007','\U8','\U08','\U008','\U0008','\U9','\U09','\U009','\U0009','\UA','\U0A','\U00A','\U000A','\UB','\U0B','\U00B','\U000B','\UC','\U0C','\U00C','\U000C','\UD','\U0D','\U00D','\U000D','\UE','\U0E','\U00E','\U000E','\UF','\U0F','\U00F','\U000F','\U10','\U010','\U0010','\U11','\U011','\U0011','\U12','\U012','\U0012','\U13','\U013','\U0013','\U14','\U014','\U0014','\U15','\U015','\U0015','\U16','\U016','\U0016','\U17','\U017','\U0017','\U18','\U018','\U0018','\U19','\U019','\U0019','\U1A','\U01A','\U001A','\U1B','\U01B','\U001B','\U1C','\U01C','\U001C','\U1D','\U01D','\U001D','\U1E','\U01E','\U001E','\U1F','\U01F','\U001F','\U20','\U020','\U0020','\U21','\U021','\U0021','\U22','\U022','\U0022','\U23','\U023','\U0023','\U24','\U024','\U0024','\U25','\U025','\U0025','\U26','\U026','\U0026','\U27','\U027','\U0027','\U28','\U028','\U0028','\U29','\U029','\U0029','\U2A','\U02A','\U002A','\U2B','\U02B','\U002B','\U2C','\U02C','\U002C','\U2D','\U02D','\U002D','\U2E','\U02E','\U002E','\U2F','\U02F','\U002F','\U30','\U030','\U0030','\U31','\U031','\U0031','\U32','\U032','\U0032','\U33','\U033','\U0033','\U34','\U034','\U0034','\U35','\U035','\U0035','\U36','\U036','\U0036','\U37','\U037','\U0037','\U38','\U038','\U0038','\U39','\U039','\U0039','\U3A','\U03A','\U003A','\U3B','\U03B','\U003B','\U3C','\U03C','\U003C','\U3D','\U03D','\U003D','\U3E','\U03E','\U003E','\U3F','\U03F','\U003F','\U40','\U040','\U0040','\U41','\U041','\U0041','\U42','\U042','\U0042','\U43','\U043','\U0043','\U44','\U044','\U0044','\U45','\U045','\U0045','\U46','\U046','\U0046','\U47','\U047','\U0047','\U48','\U048','\U0048','\U49','\U049','\U0049','\U4A','\U04A','\U004A','\U4B','\U04B','\U004B','\U4C','\U04C','\U004C','\U4D','\U04D','\U004D','\U4E','\U04E','\U004E','\U4F','\U04F','\U004F','\U50','\U050','\U0050','\U51','\U051','\U0051','\U52','\U052','\U0052','\U53','\U053','\U0053','\U54','\U054','\U0054','\U55','\U055','\U0055','\U56','\U056','\U0056','\U57','\U057','\U0057','\U58','\U058','\U0058','\U59','\U059','\U0059','\U5A','\U05A','\U005A','\U5B','\U05B','\U005B','\U5C','\U05C','\U005C','\U5D','\U05D','\U005D','\U5E','\U05E','\U005E','\U5F','\U05F','\U005F','\U60','\U060','\U0060','\U61','\U061','\U0061','\U62','\U062','\U0062','\U63','\U063','\U0063','\U64','\U064','\U0064','\U65','\U065','\U0065','\U66','\U066','\U0066','\U67','\U067','\U0067','\U68','\U068','\U0068','\U69','\U069','\U0069','\U6A','\U06A','\U006A','\U6B','\U06B','\U006B','\U6C','\U06C','\U006C','\U6D','\U06D','\U006D','\U6E','\U06E','\U006E','\U6F','\U06F','\U006F','\U70','\U070','\U0070','\U71','\U071','\U0071','\U72','\U072','\U0072','\U73','\U073','\U0073','\U74','\U074','\U0074','\U75','\U075','\U0075','\U76','\U076','\U0076','\U77','\U077','\U0077','\U78','\U078','\U0078','\U79','\U079','\U0079','\U7A','\U07A','\U007A','\U7B','\U07B','\U007B','\U7C','\U07C','\U007C','\U7D','\U07D','\U007D','\U7E','\U07E','\U007E','\U7F','\U07F','\U007F','\U80','\U080','\U0080','\U81','\U081','\U0081','\U82','\U082','\U0082','\U83','\U083','\U0083','\U84','\U084','\U0084','\U85','\U085','\U0085','\U86','\U086','\U0086','\U87','\U087','\U0087','\U88','\U088','\U0088','\U89','\U089','\U0089','\U8A','\U08A','\U008A','\U8B','\U08B','\U008B','\U8C','\U08C','\U008C','\U8D','\U08D','\U008D','\U8E','\U08E','\U008E','\U8F','\U08F','\U008F','\U90','\U090','\U0090','\U91','\U091','\U0091','\U92','\U092','\U0092','\U93','\U093','\U0093','\U94','\U094','\U0094','\U95','\U095','\U0095','\U96','\U096','\U0096','\U97','\U097','\U0097','\U98','\U098','\U0098','\U99','\U099','\U0099','\U9A','\U09A','\U009A','\U9B','\U09B','\U009B','\U9C','\U09C','\U009C','\U9D','\U09D','\U009D','\U9E','\U09E','\U009E','\U9F','\U09F','\U009F','\UA0','\U0A0','\U00A0','\UA1','\U0A1','\U00A1','\UA2','\U0A2','\U00A2','\UA3','\U0A3','\U00A3','\UA4','\U0A4','\U00A4','\UA5','\U0A5','\U00A5','\UA6','\U0A6','\U00A6','\UA7','\U0A7','\U00A7','\UA8','\U0A8','\U00A8','\UA9','\U0A9','\U00A9','\UAA','\U0AA','\U00AA','\UAB','\U0AB','\U00AB','\UAC','\U0AC','\U00AC','\UAD','\U0AD','\U00AD','\UAE','\U0AE','\U00AE','\UAF','\U0AF','\U00AF','\UB0','\U0B0','\U00B0','\UB1','\U0B1','\U00B1','\UB2','\U0B2','\U00B2','\UB3','\U0B3','\U00B3','\UB4','\U0B4','\U00B4','\UB5','\U0B5','\U00B5','\UB6','\U0B6','\U00B6','\UB7','\U0B7','\U00B7','\UB8','\U0B8','\U00B8','\UB9','\U0B9','\U00B9','\UBA','\U0BA','\U00BA','\UBB','\U0BB','\U00BB','\UBC','\U0BC','\U00BC','\UBD','\U0BD','\U00BD','\UBE','\U0BE','\U00BE','\UBF','\U0BF','\U00BF','\UC0','\U0C0','\U00C0','\UC1','\U0C1','\U00C1','\UC2','\U0C2','\U00C2','\UC3','\U0C3','\U00C3','\UC4','\U0C4','\U00C4','\UC5','\U0C5','\U00C5','\UC6','\U0C6','\U00C6','\UC7','\U0C7','\U00C7','\UC8','\U0C8','\U00C8','\UC9','\U0C9','\U00C9','\UCA','\U0CA','\U00CA','\UCB','\U0CB','\U00CB','\UCC','\U0CC','\U00CC','\UCD','\U0CD','\U00CD','\UCE','\U0CE','\U00CE','\UCF','\U0CF','\U00CF','\UD0','\U0D0','\U00D0','\UD1','\U0D1','\U00D1','\UD2','\U0D2','\U00D2','\UD3','\U0D3','\U00D3','\UD4','\U0D4','\U00D4','\UD5','\U0D5','\U00D5','\UD6','\U0D6','\U00D6','\UD7','\U0D7','\U00D7','\UD8','\U0D8','\U00D8','\UD9','\U0D9','\U00D9','\UDA','\U0DA','\U00DA','\UDB','\U0DB','\U00DB','\UDC','\U0DC','\U00DC','\UDD','\U0DD','\U00DD','\UDE','\U0DE','\U00DE','\UDF','\U0DF','\U00DF','\UE0','\U0E0','\U00E0','\UE1','\U0E1','\U00E1','\UE2','\U0E2','\U00E2','\UE3','\U0E3','\U00E3','\UE4','\U0E4','\U00E4','\UE5','\U0E5','\U00E5','\UE6','\U0E6','\U00E6','\UE7','\U0E7','\U00E7','\UE8','\U0E8','\U00E8','\UE9','\U0E9','\U00E9','\UEA','\U0EA','\U00EA','\UEB','\U0EB','\U00EB','\UEC','\U0EC','\U00EC','\UED','\U0ED','\U00ED','\UEE','\U0EE','\U00EE','\UEF','\U0EF','\U00EF','\UF0','\U0F0','\U00F0','\UF1','\U0F1','\U00F1','\UF2','\U0F2','\U00F2','\UF3','\U0F3','\U00F3','\UF4','\U0F4','\U00F4','\UF5','\U0F5','\U00F5','\UF6','\U0F6','\U00F6','\UF7','\U0F7','\U00F7','\UF8','\U0F8','\U00F8','\UF9','\U0F9','\U00F9','\UFA','\U0FA','\U00FA','\UFB','\U0FB','\U00FB','\UFC','\U0FC','\U00FC','\UFD','\U0FD','\U00FD','\UFE','\U0FE','\U00FE','\UFF','\U0FF','\U00FF','\U100','\U0100','\U101','\U0101','\U102','\U0102','\U103','\U0103','\U104','\U0104','\U105','\U0105','\U106','\U0106','\U107','\U0107','\U108','\U0108','\U109','\U0109','\U10A','\U010A','\U10B','\U010B','\U10C','\U010C','\U10D','\U010D','\U10E','\U010E','\U10F','\U010F','\U110','\U0110','\U111','\U0111','\U112','\U0112','\U113','\U0113','\U114','\U0114','\U115','\U0115','\U116','\U0116','\U117','\U0117','\U118','\U0118','\U119','\U0119','\U11A','\U011A','\U11B','\U011B','\U11C','\U011C','\U11D','\U011D','\U11E','\U011E','\U11F','\U011F','\U120','\U0120','\U121','\U0121','\U122','\U0122','\U123','\U0123','\U124','\U0124','\U125','\U0125','\U126','\U0126','\U127','\U0127','\U128','\U0128','\U129','\U0129','\U12A','\U012A','\U12B','\U012B','\U12C','\U012C','\U12D','\U012D','\U12E','\U012E','\U12F','\U012F','\U130','\U0130','\U131','\U0131','\U132','\U0132','\U133','\U0133','\U134','\U0134','\U135','\U0135','\U136','\U0136','\U137','\U0137','\U138','\U0138','\U139','\U0139','\U13A','\U013A','\U13B','\U013B','\U13C','\U013C','\U13D','\U013D','\U13E','\U013E','\U13F','\U013F','\U140','\U0140','\U141','\U0141','\U142','\U0142','\U143','\U0143','\U144','\U0144','\U145','\U0145','\U146','\U0146','\U147','\U0147','\U148','\U0148','\U149','\U0149','\U14A','\U014A','\U14B','\U014B','\U14C','\U014C','\U14D','\U014D','\U14E','\U014E','\U14F','\U014F','\U150','\U0150','\U151','\U0151','\U152','\U0152','\U153','\U0153','\U154','\U0154','\U155','\U0155','\U156','\U0156','\U157','\U0157','\U158','\U0158','\U159','\U0159','\U15A','\U015A','\U15B','\U015B','\U15C','\U015C','\U15D','\U015D','\U15E','\U015E','\U15F','\U015F','\U160','\U0160','\U161','\U0161','\U162','\U0162','\U163','\U0163','\U164','\U0164','\U165','\U0165','\U166','\U0166','\U167','\U0167','\U168','\U0168','\U169','\U0169','\U16A','\U016A','\U16B','\U016B','\U16C','\U016C','\U16D','\U016D','\U16E','\U016E','\U16F','\U016F','\U170','\U0170','\U171','\U0171','\U172','\U0172','\U173','\U0173','\U174','\U0174','\U175','\U0175','\U176','\U0176','\U177','\U0177','\U178','\U0178','\U179','\U0179','\U17A','\U017A','\U17B','\U017B','\U17C','\U017C','\U17D','\U017D','\U17E','\U017E','\U17F','\U017F','\U180','\U0180','\U181','\U0181','\U182','\U0182','\U183','\U0183','\U184','\U0184','\U185','\U0185','\U186','\U0186','\U187','\U0187','\U188','\U0188','\U189','\U0189','\U18A','\U018A','\U18B','\U018B','\U18C','\U018C','\U18D','\U018D','\U18E','\U018E','\U18F','\U018F','\U190','\U0190','\U191','\U0191','\U192','\U0192','\U193','\U0193','\U194','\U0194','\U195','\U0195','\U196','\U0196','\U197','\U0197','\U198','\U0198','\U199','\U0199','\U19A','\U019A','\U19B','\U019B','\U19C','\U019C','\U19D','\U019D','\U19E','\U019E','\U19F','\U019F','\U1A0','\U01A0','\U1A1','\U01A1','\U1A2','\U01A2','\U1A3','\U01A3','\U1A4','\U01A4','\U1A5','\U01A5','\U1A6','\U01A6','\U1A7','\U01A7','\U1A8','\U01A8','\U1A9','\U01A9','\U1AA','\U01AA','\U1AB','\U01AB','\U1AC','\U01AC','\U1AD','\U01AD','\U1AE','\U01AE','\U1AF','\U01AF','\U1B0','\U01B0','\U1B1','\U01B1','\U1B2','\U01B2','\U1B3','\U01B3','\U1B4','\U01B4','\U1B5','\U01B5','\U1B6','\U01B6','\U1B7','\U01B7','\U1B8','\U01B8','\U1B9','\U01B9','\U1BA','\U01BA','\U1BB','\U01BB','\U1BC','\U01BC','\U1BD','\U01BD','\U1BE','\U01BE','\U1BF','\U01BF','\U1C0','\U01C0','\U1C1','\U01C1','\U1C2','\U01C2','\U1C3','\U01C3','\U1C4','\U01C4','\U1C5','\U01C5','\U1C6','\U01C6','\U1C7','\U01C7','\U1C8','\U01C8','\U1C9','\U01C9','\U1CA','\U01CA','\U1CB','\U01CB','\U1CC','\U01CC','\U1CD','\U01CD','\U1CE','\U01CE','\U1CF','\U01CF','\U1D0','\U01D0','\U1D1','\U01D1','\U1D2','\U01D2','\U1D3','\U01D3','\U1D4','\U01D4','\U1D5','\U01D5','\U1D6','\U01D6','\U1D7','\U01D7','\U1D8','\U01D8','\U1D9','\U01D9','\U1DA','\U01DA','\U1DB','\U01DB','\U1DC','\U01DC','\U1DD','\U01DD','\U1DE','\U01DE','\U1DF','\U01DF','\U1E0','\U01E0','\U1E1','\U01E1','\U1E2','\U01E2','\U1E3','\U01E3','\U1E4','\U01E4','\U1E5','\U01E5','\U1E6','\U01E6','\U1E7','\U01E7','\U1E8','\U01E8','\U1E9','\U01E9','\U1EA','\U01EA','\U1EB','\U01EB','\U1EC','\U01EC','\U1ED','\U01ED','\U1EE','\U01EE','\U1EF','\U01EF','\U1F0','\U01F0','\U1F1','\U01F1','\U1F2','\U01F2','\U1F3','\U01F3','\U1F4','\U01F4','\U1F5','\U01F5','\U1F6','\U01F6','\U1F7','\U01F7','\U1F8','\U01F8','\U1F9','\U01F9','\U1FA','\U01FA','\U1FB','\U01FB','\U1FC','\U01FC','\U1FD','\U01FD','\U1FE','\U01FE','\U1FF','\U01FF','\U200','\U0200','\U201','\U0201','\U202','\U0202','\U203','\U0203','\U204','\U0204','\U205','\U0205','\U206','\U0206','\U207','\U0207','\U208','\U0208','\U209','\U0209','\U20A','\U020A','\U20B','\U020B','\U20C','\U020C','\U20D','\U020D','\U20E','\U020E','\U20F','\U020F','\U210','\U0210','\U211','\U0211','\U212','\U0212','\U213','\U0213','\U214','\U0214','\U215','\U0215','\U216','\U0216','\U217','\U0217','\U218','\U0218','\U219','\U0219','\U21A','\U021A','\U21B','\U021B','\U21C','\U021C','\U21D','\U021D','\U21E','\U021E','\U21F','\U021F','\U220','\U0220','\U221','\U0221','\U222','\U0222','\U223','\U0223','\U224','\U0224','\U225','\U0225','\U226','\U0226','\U227','\U0227','\U228','\U0228','\U229','\U0229','\U22A','\U022A','\U22B','\U022B','\U22C','\U022C','\U22D','\U022D','\U22E','\U022E','\U22F','\U022F','\U230','\U0230','\U231','\U0231','\U232','\U0232','\U233','\U0233','\U234','\U0234','\U235','\U0235','\U236','\U0236','\U237','\U0237','\U238','\U0238','\U239','\U0239','\U23A','\U023A','\U23B','\U023B','\U23C','\U023C','\U23D','\U023D','\U23E','\U023E','\U23F','\U023F','\U240','\U0240','\U241','\U0241','\U242','\U0242','\U243','\U0243','\U244','\U0244','\U245','\U0245','\U246','\U0246','\U247','\U0247','\U248','\U0248','\U249','\U0249','\U24A','\U024A','\U24B','\U024B','\U24C','\U024C','\U24D','\U024D','\U24E','\U024E','\U24F','\U024F','\U250','\U0250','\U251','\U0251','\U252','\U0252','\U253','\U0253','\U254','\U0254','\U255','\U0255','\U256','\U0256','\U257','\U0257','\U258','\U0258','\U259','\U0259','\U25A','\U025A','\U25B','\U025B','\U25C','\U025C','\U25D','\U025D','\U25E','\U025E','\U25F','\U025F','\U260','\U0260','\U261','\U0261','\U262','\U0262','\U263','\U0263','\U264','\U0264','\U265','\U0265','\U266','\U0266','\U267','\U0267','\U268','\U0268','\U269','\U0269','\U26A','\U026A','\U26B','\U026B','\U26C','\U026C','\U26D','\U026D','\U26E','\U026E','\U26F','\U026F','\U270','\U0270','\U271','\U0271','\U272','\U0272','\U273','\U0273','\U274','\U0274','\U275','\U0275','\U276','\U0276','\U277','\U0277','\U278','\U0278','\U279','\U0279','\U27A','\U027A','\U27B','\U027B','\U27C','\U027C','\U27D','\U027D','\U27E','\U027E','\U27F','\U027F','\U280','\U0280','\U281','\U0281','\U282','\U0282','\U283','\U0283','\U284','\U0284','\U285','\U0285','\U286','\U0286','\U287','\U0287','\U288','\U0288','\U289','\U0289','\U28A','\U028A','\U28B','\U028B','\U28C','\U028C','\U28D','\U028D','\U28E','\U028E','\U28F','\U028F','\U290','\U0290','\U291','\U0291','\U292','\U0292','\U293','\U0293','\U294','\U0294','\U295','\U0295','\U296','\U0296','\U297','\U0297','\U298','\U0298','\U299','\U0299','\U29A','\U029A','\U29B','\U029B','\U29C','\U029C','\U29D','\U029D','\U29E','\U029E','\U29F','\U029F','\U2A0','\U02A0','\U2A1','\U02A1','\U2A2','\U02A2','\U2A3','\U02A3','\U2A4','\U02A4','\U2A5','\U02A5','\U2A6','\U02A6','\U2A7','\U02A7','\U2A8','\U02A8','\U2A9','\U02A9','\U2AA','\U02AA','\U2AB','\U02AB','\U2AC','\U02AC','\U2AD','\U02AD','\U2AE','\U02AE','\U2AF','\U02AF','\U2B0','\U02B0','\U2B1','\U02B1','\U2B2','\U02B2','\U2B3','\U02B3','\U2B4','\U02B4','\U2B5','\U02B5','\U2B6','\U02B6','\U2B7','\U02B7','\U2B8','\U02B8','\U2B9','\U02B9','\U2BA','\U02BA','\U2BB','\U02BB','\U2BC','\U02BC','\U2BD','\U02BD','\U2BE','\U02BE','\U2BF','\U02BF','\U2C0','\U02C0','\U2C1','\U02C1','\U2C2','\U02C2','\U2C3','\U02C3','\U2C4','\U02C4','\U2C5','\U02C5','\U2C6','\U02C6','\U2C7','\U02C7','\U2C8','\U02C8','\U2C9','\U02C9','\U2CA','\U02CA','\U2CB','\U02CB','\U2CC','\U02CC','\U2CD','\U02CD','\U2CE','\U02CE','\U2CF','\U02CF','\U2D0','\U02D0','\U2D1','\U02D1','\U2D2','\U02D2','\U2D3','\U02D3','\U2D4','\U02D4','\U2D5','\U02D5','\U2D6','\U02D6','\U2D7','\U02D7','\U2D8','\U02D8','\U2D9','\U02D9','\U2DA','\U02DA','\U2DB','\U02DB','\U2DC','\U02DC','\U2DD','\U02DD','\U2DE','\U02DE','\U2DF','\U02DF','\U2E0','\U02E0','\U2E1','\U02E1','\U2E2','\U02E2','\U2E3','\U02E3','\U2E4','\U02E4','\U2E5','\U02E5','\U2E6','\U02E6','\U2E7','\U02E7','\U2E8','\U02E8','\U2E9','\U02E9','\U2EA','\U02EA','\U2EB','\U02EB','\U2EC','\U02EC','\U2ED','\U02ED','\U2EE','\U02EE','\U2EF','\U02EF','\U2F0','\U02F0','\U2F1','\U02F1','\U2F2','\U02F2','\U2F3','\U02F3','\U2F4','\U02F4','\U2F5','\U02F5','\U2F6','\U02F6','\U2F7','\U02F7','\U2F8','\U02F8','\U2F9','\U02F9','\U2FA','\U02FA','\U2FB','\U02FB','\U2FC','\U02FC','\U2FD','\U02FD','\U2FE','\U02FE','\U2FF','\U02FF','\U300','\U0300','\U301','\U0301','\U302','\U0302','\U303','\U0303','\U304','\U0304','\U305','\U0305','\U306','\U0306','\U307','\U0307','\U308','\U0308','\U309','\U0309','\U30A','\U030A','\U30B','\U030B','\U30C','\U030C','\U30D','\U030D','\U30E','\U030E','\U30F','\U030F','\U310','\U0310','\U311','\U0311','\U312','\U0312','\U313','\U0313','\U314','\U0314','\U315','\U0315','\U316','\U0316','\U317','\U0317','\U318','\U0318','\U319','\U0319','\U31A','\U031A','\U31B','\U031B','\U31C','\U031C','\U31D','\U031D','\U31E','\U031E','\U31F','\U031F','\U320','\U0320','\U321','\U0321','\U322','\U0322','\U323','\U0323','\U324','\U0324','\U325','\U0325','\U326','\U0326','\U327','\U0327','\U328','\U0328','\U329','\U0329','\U32A','\U032A','\U32B','\U032B','\U32C','\U032C','\U32D','\U032D','\U32E','\U032E','\U32F','\U032F','\U330','\U0330','\U331','\U0331','\U332','\U0332','\U333','\U0333','\U334','\U0334','\U335','\U0335','\U336','\U0336','\U337','\U0337','\U338','\U0338','\U339','\U0339','\U33A','\U033A','\U33B','\U033B','\U33C','\U033C','\U33D','\U033D','\U33E','\U033E','\U33F','\U033F','\U340','\U0340','\U341','\U0341','\U342','\U0342','\U343','\U0343','\U344','\U0344','\U345','\U0345','\U346','\U0346','\U347','\U0347','\U348','\U0348','\U349','\U0349','\U34A','\U034A','\U34B','\U034B','\U34C','\U034C','\U34D','\U034D','\U34E','\U034E','\U34F','\U034F','\U350','\U0350','\U351','\U0351','\U352','\U0352','\U353','\U0353','\U354','\U0354','\U355','\U0355','\U356','\U0356','\U357','\U0357','\U358','\U0358','\U359','\U0359','\U35A','\U035A','\U35B','\U035B','\U35C','\U035C','\U35D','\U035D','\U35E','\U035E','\U35F','\U035F','\U360','\U0360','\U361','\U0361','\U362','\U0362','\U363','\U0363','\U364','\U0364','\U365','\U0365','\U366','\U0366','\U367','\U0367','\U368','\U0368','\U369','\U0369','\U36A','\U036A','\U36B','\U036B','\U36C','\U036C','\U36D','\U036D','\U36E','\U036E','\U36F','\U036F','\U370','\U0370','\U371','\U0371','\U372','\U0372','\U373','\U0373','\U374','\U0374','\U375','\U0375','\U376','\U0376','\U377','\U0377','\U378','\U0378','\U379','\U0379','\U37A','\U037A','\U37B','\U037B','\U37C','\U037C','\U37D','\U037D','\U37E','\U037E','\U37F','\U037F','\U380','\U0380','\U381','\U0381','\U382','\U0382','\U383','\U0383','\U384','\U0384','\U385','\U0385','\U386','\U0386','\U387','\U0387','\U388','\U0388','\U389','\U0389','\U38A','\U038A','\U38B','\U038B','\U38C','\U038C','\U38D','\U038D','\U38E','\U038E','\U38F','\U038F','\U390','\U0390','\U391','\U0391','\U392','\U0392','\U393','\U0393','\U394','\U0394','\U395','\U0395','\U396','\U0396','\U397','\U0397','\U398','\U0398','\U399','\U0399','\U39A','\U039A','\U39B','\U039B','\U39C','\U039C','\U39D','\U039D','\U39E','\U039E','\U39F','\U039F','\U3A0','\U03A0','\U3A1','\U03A1','\U3A2','\U03A2','\U3A3','\U03A3','\U3A4','\U03A4','\U3A5','\U03A5','\U3A6','\U03A6','\U3A7','\U03A7','\U3A8','\U03A8','\U3A9','\U03A9','\U3AA','\U03AA','\U3AB','\U03AB','\U3AC','\U03AC','\U3AD','\U03AD','\U3AE','\U03AE','\U3AF','\U03AF','\U3B0','\U03B0','\U3B1','\U03B1','\U3B2','\U03B2','\U3B3','\U03B3','\U3B4','\U03B4','\U3B5','\U03B5','\U3B6','\U03B6','\U3B7','\U03B7','\U3B8','\U03B8','\U3B9','\U03B9','\U3BA','\U03BA','\U3BB','\U03BB','\U3BC','\U03BC','\U3BD','\U03BD','\U3BE','\U03BE','\U3BF','\U03BF','\U3C0','\U03C0','\U3C1','\U03C1','\U3C2','\U03C2','\U3C3','\U03C3','\U3C4','\U03C4','\U3C5','\U03C5','\U3C6','\U03C6','\U3C7','\U03C7','\U3C8','\U03C8','\U3C9','\U03C9','\U3CA','\U03CA','\U3CB','\U03CB','\U3CC','\U03CC','\U3CD','\U03CD','\U3CE','\U03CE','\U3CF','\U03CF','\U3D0','\U03D0','\U3D1','\U03D1','\U3D2','\U03D2','\U3D3','\U03D3','\U3D4','\U03D4','\U3D5','\U03D5','\U3D6','\U03D6','\U3D7','\U03D7','\U3D8','\U03D8','\U3D9','\U03D9','\U3DA','\U03DA','\U3DB','\U03DB','\U3DC','\U03DC','\U3DD','\U03DD','\U3DE','\U03DE','\U3DF','\U03DF','\U3E0','\U03E0','\U3E1','\U03E1','\U3E2','\U03E2','\U3E3','\U03E3','\U3E4','\U03E4','\U3E5','\U03E5','\U3E6','\U03E6','\U3E7','\U03E7','\U3E8','\U03E8','\U3E9','\U03E9','\U3EA','\U03EA','\U3EB','\U03EB','\U3EC','\U03EC','\U3ED','\U03ED','\U3EE','\U03EE','\U3EF','\U03EF','\U3F0','\U03F0','\U3F1','\U03F1','\U3F2','\U03F2','\U3F3','\U03F3','\U3F4','\U03F4','\U3F5','\U03F5','\U3F6','\U03F6','\U3F7','\U03F7','\U3F8','\U03F8','\U3F9','\U03F9','\U3FA','\U03FA','\U3FB','\U03FB','\U3FC','\U03FC','\U3FD','\U03FD','\U3FE','\U03FE','\U3FF','\U03FF','\U400','\U0400','\U401','\U0401','\U402','\U0402','\U403','\U0403','\U404','\U0404','\U405','\U0405','\U406','\U0406','\U407','\U0407','\U408','\U0408','\U409','\U0409','\U40A','\U040A','\U40B','\U040B','\U40C','\U040C','\U40D','\U040D','\U40E','\U040E','\U40F','\U040F','\U410','\U0410','\U411','\U0411','\U412','\U0412','\U413','\U0413','\U414','\U0414','\U415','\U0415','\U416','\U0416','\U417','\U0417','\U418','\U0418','\U419','\U0419','\U41A','\U041A','\U41B','\U041B','\U41C','\U041C','\U41D','\U041D','\U41E','\U041E','\U41F','\U041F','\U420','\U0420','\U421','\U0421','\U422','\U0422','\U423','\U0423','\U424','\U0424','\U425','\U0425','\U426','\U0426','\U427','\U0427','\U428','\U0428','\U429','\U0429','\U42A','\U042A','\U42B','\U042B','\U42C','\U042C','\U42D','\U042D','\U42E','\U042E','\U42F','\U042F','\U430','\U0430','\U431','\U0431','\U432','\U0432','\U433','\U0433','\U434','\U0434','\U435','\U0435','\U436','\U0436','\U437','\U0437','\U438','\U0438','\U439','\U0439','\U43A','\U043A','\U43B','\U043B','\U43C','\U043C','\U43D','\U043D','\U43E','\U043E','\U43F','\U043F','\U440','\U0440','\U441','\U0441','\U442','\U0442','\U443','\U0443','\U444','\U0444','\U445','\U0445','\U446','\U0446','\U447','\U0447','\U448','\U0448','\U449','\U0449','\U44A','\U044A','\U44B','\U044B','\U44C','\U044C','\U44D','\U044D','\U44E','\U044E','\U44F','\U044F','\U450','\U0450','\U451','\U0451','\U452','\U0452','\U453','\U0453','\U454','\U0454','\U455','\U0455','\U456','\U0456','\U457','\U0457','\U458','\U0458','\U459','\U0459','\U45A','\U045A','\U45B','\U045B','\U45C','\U045C','\U45D','\U045D','\U45E','\U045E','\U45F','\U045F','\U460','\U0460','\U461','\U0461','\U462','\U0462','\U463','\U0463','\U464','\U0464','\U465','\U0465','\U466','\U0466','\U467','\U0467','\U468','\U0468','\U469','\U0469','\U46A','\U046A','\U46B','\U046B','\U46C','\U046C','\U46D','\U046D','\U46E','\U046E','\U46F','\U046F','\U470','\U0470','\U471','\U0471','\U472','\U0472','\U473','\U0473','\U474','\U0474','\U475','\U0475','\U476','\U0476','\U477','\U0477','\U478','\U0478','\U479','\U0479','\U47A','\U047A','\U47B','\U047B','\U47C','\U047C','\U47D','\U047D','\U47E','\U047E','\U47F','\U047F','\U480','\U0480','\U481','\U0481','\U482','\U0482','\U483','\U0483','\U484','\U0484','\U485','\U0485','\U486','\U0486','\U487','\U0487','\U488','\U0488','\U489','\U0489','\U48A','\U048A','\U48B','\U048B','\U48C','\U048C','\U48D','\U048D','\U48E','\U048E','\U48F','\U048F','\U490','\U0490','\U491','\U0491','\U492','\U0492','\U493','\U0493','\U494','\U0494','\U495','\U0495','\U496','\U0496','\U497','\U0497','\U498','\U0498','\U499','\U0499','\U49A','\U049A','\U49B','\U049B','\U49C','\U049C','\U49D','\U049D','\U49E','\U049E','\U49F','\U049F','\U4A0','\U04A0','\U4A1','\U04A1','\U4A2','\U04A2','\U4A3','\U04A3','\U4A4','\U04A4','\U4A5','\U04A5','\U4A6','\U04A6','\U4A7','\U04A7','\U4A8','\U04A8','\U4A9','\U04A9','\U4AA','\U04AA','\U4AB','\U04AB','\U4AC','\U04AC','\U4AD','\U04AD','\U4AE','\U04AE','\U4AF','\U04AF','\U4B0','\U04B0','\U4B1','\U04B1','\U4B2','\U04B2','\U4B3','\U04B3','\U4B4','\U04B4','\U4B5','\U04B5','\U4B6','\U04B6','\U4B7','\U04B7','\U4B8','\U04B8','\U4B9','\U04B9','\U4BA','\U04BA','\U4BB','\U04BB','\U4BC','\U04BC','\U4BD','\U04BD','\U4BE','\U04BE','\U4BF','\U04BF','\U4C0','\U04C0','\U4C1','\U04C1','\U4C2','\U04C2','\U4C3','\U04C3','\U4C4','\U04C4','\U4C5','\U04C5','\U4C6','\U04C6','\U4C7','\U04C7','\U4C8','\U04C8','\U4C9','\U04C9','\U4CA','\U04CA','\U4CB','\U04CB','\U4CC','\U04CC','\U4CD','\U04CD','\U4CE','\U04CE','\U4CF','\U04CF','\U4D0','\U04D0','\U4D1','\U04D1','\U4D2','\U04D2','\U4D3','\U04D3','\U4D4','\U04D4','\U4D5','\U04D5','\U4D6','\U04D6','\U4D7','\U04D7','\U4D8','\U04D8','\U4D9','\U04D9','\U4DA','\U04DA','\U4DB','\U04DB','\U4DC','\U04DC','\U4DD','\U04DD','\U4DE','\U04DE','\U4DF','\U04DF','\U4E0','\U04E0','\U4E1','\U04E1','\U4E2','\U04E2','\U4E3','\U04E3','\U4E4','\U04E4','\U4E5','\U04E5','\U4E6','\U04E6','\U4E7','\U04E7','\U4E8','\U04E8','\U4E9','\U04E9','\U4EA','\U04EA','\U4EB','\U04EB','\U4EC','\U04EC','\U4ED','\U04ED','\U4EE','\U04EE','\U4EF','\U04EF','\U4F0','\U04F0','\U4F1','\U04F1','\U4F2','\U04F2','\U4F3','\U04F3','\U4F4','\U04F4','\U4F5','\U04F5','\U4F6','\U04F6','\U4F7','\U04F7','\U4F8','\U04F8','\U4F9','\U04F9','\U4FA','\U04FA','\U4FB','\U04FB','\U4FC','\U04FC','\U4FD','\U04FD','\U4FE','\U04FE','\U4FF','\U04FF','\U500','\U0500','\U501','\U0501','\U502','\U0502','\U503','\U0503','\U504','\U0504','\U505','\U0505','\U506','\U0506','\U507','\U0507','\U508','\U0508','\U509','\U0509','\U50A','\U050A','\U50B','\U050B','\U50C','\U050C','\U50D','\U050D','\U50E','\U050E','\U50F','\U050F','\U510','\U0510','\U511','\U0511','\U512','\U0512','\U513','\U0513','\U514','\U0514','\U515','\U0515','\U516','\U0516','\U517','\U0517','\U518','\U0518','\U519','\U0519','\U51A','\U051A','\U51B','\U051B','\U51C','\U051C','\U51D','\U051D','\U51E','\U051E','\U51F','\U051F','\U520','\U0520','\U521','\U0521','\U522','\U0522','\U523','\U0523','\U524','\U0524','\U525','\U0525','\U526','\U0526','\U527','\U0527','\U528','\U0528','\U529','\U0529','\U52A','\U052A','\U52B','\U052B','\U52C','\U052C','\U52D','\U052D','\U52E','\U052E','\U52F','\U052F','\U530','\U0530','\U531','\U0531','\U532','\U0532','\U533','\U0533','\U534','\U0534','\U535','\U0535','\U536','\U0536','\U537','\U0537','\U538','\U0538','\U539','\U0539','\U53A','\U053A','\U53B','\U053B','\U53C','\U053C','\U53D','\U053D','\U53E','\U053E','\U53F','\U053F','\U540','\U0540','\U541','\U0541','\U542','\U0542','\U543','\U0543','\U544','\U0544','\U545','\U0545','\U546','\U0546','\U547','\U0547','\U548','\U0548','\U549','\U0549','\U54A','\U054A','\U54B','\U054B','\U54C','\U054C','\U54D','\U054D','\U54E','\U054E','\U54F','\U054F','\U550','\U0550','\U551','\U0551','\U552','\U0552','\U553','\U0553','\U554','\U0554','\U555','\U0555','\U556','\U0556','\U557','\U0557','\U558','\U0558','\U559','\U0559','\U55A','\U055A','\U55B','\U055B','\U55C','\U055C','\U55D','\U055D','\U55E','\U055E','\U55F','\U055F','\U560','\U0560','\U561','\U0561','\U562','\U0562','\U563','\U0563','\U564','\U0564','\U565','\U0565','\U566','\U0566','\U567','\U0567','\U568','\U0568','\U569','\U0569','\U56A','\U056A','\U56B','\U056B','\U56C','\U056C','\U56D','\U056D','\U56E','\U056E','\U56F','\U056F','\U570','\U0570','\U571','\U0571','\U572','\U0572','\U573','\U0573','\U574','\U0574','\U575','\U0575','\U576','\U0576','\U577','\U0577','\U578','\U0578','\U579','\U0579','\U57A','\U057A','\U57B','\U057B','\U57C','\U057C','\U57D','\U057D','\U57E','\U057E','\U57F','\U057F','\U580','\U0580','\U581','\U0581','\U582','\U0582','\U583','\U0583','\U584','\U0584','\U585','\U0585','\U586','\U0586','\U587','\U0587','\U588','\U0588','\U589','\U0589','\U58A','\U058A','\U58B','\U058B','\U58C','\U058C','\U58D','\U058D','\U58E','\U058E','\U58F','\U058F','\U590','\U0590','\U591','\U0591','\U592','\U0592','\U593','\U0593','\U594','\U0594','\U595','\U0595','\U596','\U0596','\U597','\U0597','\U598','\U0598','\U599','\U0599','\U59A','\U059A','\U59B','\U059B','\U59C','\U059C','\U59D','\U059D','\U59E','\U059E','\U59F','\U059F','\U5A0','\U05A0','\U5A1','\U05A1','\U5A2','\U05A2','\U5A3','\U05A3','\U5A4','\U05A4','\U5A5','\U05A5','\U5A6','\U05A6','\U5A7','\U05A7','\U5A8','\U05A8','\U5A9','\U05A9','\U5AA','\U05AA','\U5AB','\U05AB','\U5AC','\U05AC','\U5AD','\U05AD','\U5AE','\U05AE','\U5AF','\U05AF','\U5B0','\U05B0','\U5B1','\U05B1','\U5B2','\U05B2','\U5B3','\U05B3','\U5B4','\U05B4','\U5B5','\U05B5','\U5B6','\U05B6','\U5B7','\U05B7','\U5B8','\U05B8','\U5B9','\U05B9','\U5BA','\U05BA','\U5BB','\U05BB','\U5BC','\U05BC','\U5BD','\U05BD','\U5BE','\U05BE','\U5BF','\U05BF','\U5C0','\U05C0','\U5C1','\U05C1','\U5C2','\U05C2','\U5C3','\U05C3','\U5C4','\U05C4','\U5C5','\U05C5','\U5C6','\U05C6','\U5C7','\U05C7','\U5C8','\U05C8','\U5C9','\U05C9','\U5CA','\U05CA','\U5CB','\U05CB','\U5CC','\U05CC','\U5CD','\U05CD','\U5CE','\U05CE','\U5CF','\U05CF','\U5D0','\U05D0','\U5D1','\U05D1','\U5D2','\U05D2','\U5D3','\U05D3','\U5D4','\U05D4','\U5D5','\U05D5','\U5D6','\U05D6','\U5D7','\U05D7','\U5D8','\U05D8','\U5D9','\U05D9','\U5DA','\U05DA','\U5DB','\U05DB','\U5DC','\U05DC','\U5DD','\U05DD','\U5DE','\U05DE','\U5DF','\U05DF','\U5E0','\U05E0','\U5E1','\U05E1','\U5E2','\U05E2','\U5E3','\U05E3','\U5E4','\U05E4','\U5E5','\U05E5','\U5E6','\U05E6','\U5E7','\U05E7','\U5E8','\U05E8','\U5E9','\U05E9','\U5EA','\U05EA','\U5EB','\U05EB','\U5EC','\U05EC','\U5ED','\U05ED','\U5EE','\U05EE','\U5EF','\U05EF','\U5F0','\U05F0','\U5F1','\U05F1','\U5F2','\U05F2','\U5F3','\U05F3','\U5F4','\U05F4','\U5F5','\U05F5','\U5F6','\U05F6','\U5F7','\U05F7','\U5F8','\U05F8','\U5F9','\U05F9','\U5FA','\U05FA','\U5FB','\U05FB','\U5FC','\U05FC','\U5FD','\U05FD','\U5FE','\U05FE','\U5FF','\U05FF','\U600','\U0600','\U601','\U0601','\U602','\U0602','\U603','\U0603','\U604','\U0604','\U605','\U0605','\U606','\U0606','\U607','\U0607','\U608','\U0608','\U609','\U0609','\U60A','\U060A','\U60B','\U060B','\U60C','\U060C','\U60D','\U060D','\U60E','\U060E','\U60F','\U060F','\U610','\U0610','\U611','\U0611','\U612','\U0612','\U613','\U0613','\U614','\U0614','\U615','\U0615','\U616','\U0616','\U617','\U0617','\U618','\U0618','\U619','\U0619','\U61A','\U061A','\U61B','\U061B','\U61C','\U061C','\U61D','\U061D','\U61E','\U061E','\U61F','\U061F','\U620','\U0620','\U621','\U0621','\U622','\U0622','\U623','\U0623','\U624','\U0624','\U625','\U0625','\U626','\U0626','\U627','\U0627','\U628','\U0628','\U629','\U0629','\U62A','\U062A','\U62B','\U062B','\U62C','\U062C','\U62D','\U062D','\U62E','\U062E','\U62F','\U062F','\U630','\U0630','\U631','\U0631','\U632','\U0632','\U633','\U0633','\U634','\U0634','\U635','\U0635','\U636','\U0636','\U637','\U0637','\U638','\U0638','\U639','\U0639','\U63A','\U063A','\U63B','\U063B','\U63C','\U063C','\U63D','\U063D','\U63E','\U063E','\U63F','\U063F','\U640','\U0640','\U641','\U0641','\U642','\U0642','\U643','\U0643','\U644','\U0644','\U645','\U0645','\U646','\U0646','\U647','\U0647','\U648','\U0648','\U649','\U0649','\U64A','\U064A','\U64B','\U064B','\U64C','\U064C','\U64D','\U064D','\U64E','\U064E','\U64F','\U064F','\U650','\U0650','\U651','\U0651','\U652','\U0652','\U653','\U0653','\U654','\U0654','\U655','\U0655','\U656','\U0656','\U657','\U0657','\U658','\U0658','\U659','\U0659','\U65A','\U065A','\U65B','\U065B','\U65C','\U065C','\U65D','\U065D','\U65E','\U065E','\U65F','\U065F','\U660','\U0660','\U661','\U0661','\U662','\U0662','\U663','\U0663','\U664','\U0664','\U665','\U0665','\U666','\U0666','\U667','\U0667','\U668','\U0668','\U669','\U0669','\U66A','\U066A','\U66B','\U066B','\U66C','\U066C','\U66D','\U066D','\U66E','\U066E','\U66F','\U066F','\U670','\U0670','\U671','\U0671','\U672','\U0672','\U673','\U0673','\U674','\U0674','\U675','\U0675','\U676','\U0676','\U677','\U0677','\U678','\U0678','\U679','\U0679','\U67A','\U067A','\U67B','\U067B','\U67C','\U067C','\U67D','\U067D','\U67E','\U067E','\U67F','\U067F','\U680','\U0680','\U681','\U0681','\U682','\U0682','\U683','\U0683','\U684','\U0684','\U685','\U0685','\U686','\U0686','\U687','\U0687','\U688','\U0688','\U689','\U0689','\U68A','\U068A','\U68B','\U068B','\U68C','\U068C','\U68D','\U068D','\U68E','\U068E','\U68F','\U068F','\U690','\U0690','\U691','\U0691','\U692','\U0692','\U693','\U0693','\U694','\U0694','\U695','\U0695','\U696','\U0696','\U697','\U0697','\U698','\U0698','\U699','\U0699','\U69A','\U069A','\U69B','\U069B','\U69C','\U069C','\U69D','\U069D','\U69E','\U069E','\U69F','\U069F','\U6A0','\U06A0','\U6A1','\U06A1','\U6A2','\U06A2','\U6A3','\U06A3','\U6A4','\U06A4','\U6A5','\U06A5','\U6A6','\U06A6','\U6A7','\U06A7','\U6A8','\U06A8','\U6A9','\U06A9','\U6AA','\U06AA','\U6AB','\U06AB','\U6AC','\U06AC','\U6AD','\U06AD','\U6AE','\U06AE','\U6AF','\U06AF','\U6B0','\U06B0','\U6B1','\U06B1','\U6B2','\U06B2','\U6B3','\U06B3','\U6B4','\U06B4','\U6B5','\U06B5','\U6B6','\U06B6','\U6B7','\U06B7','\U6B8','\U06B8','\U6B9','\U06B9','\U6BA','\U06BA','\U6BB','\U06BB','\U6BC','\U06BC','\U6BD','\U06BD','\U6BE','\U06BE','\U6BF','\U06BF','\U6C0','\U06C0','\U6C1','\U06C1','\U6C2','\U06C2','\U6C3','\U06C3','\U6C4','\U06C4','\U6C5','\U06C5','\U6C6','\U06C6','\U6C7','\U06C7','\U6C8','\U06C8','\U6C9','\U06C9','\U6CA','\U06CA','\U6CB','\U06CB','\U6CC','\U06CC','\U6CD','\U06CD','\U6CE','\U06CE','\U6CF','\U06CF','\U6D0','\U06D0','\U6D1','\U06D1','\U6D2','\U06D2','\U6D3','\U06D3','\U6D4','\U06D4','\U6D5','\U06D5','\U6D6','\U06D6','\U6D7','\U06D7','\U6D8','\U06D8','\U6D9','\U06D9','\U6DA','\U06DA','\U6DB','\U06DB','\U6DC','\U06DC','\U6DD','\U06DD','\U6DE','\U06DE','\U6DF','\U06DF','\U6E0','\U06E0','\U6E1','\U06E1','\U6E2','\U06E2','\U6E3','\U06E3','\U6E4','\U06E4','\U6E5','\U06E5','\U6E6','\U06E6','\U6E7','\U06E7','\U6E8','\U06E8','\U6E9','\U06E9','\U6EA','\U06EA','\U6EB','\U06EB','\U6EC','\U06EC','\U6ED','\U06ED','\U6EE','\U06EE','\U6EF','\U06EF','\U6F0','\U06F0','\U6F1','\U06F1','\U6F2','\U06F2','\U6F3','\U06F3','\U6F4','\U06F4','\U6F5','\U06F5','\U6F6','\U06F6','\U6F7','\U06F7','\U6F8','\U06F8','\U6F9','\U06F9','\U6FA','\U06FA','\U6FB','\U06FB','\U6FC','\U06FC','\U6FD','\U06FD','\U6FE','\U06FE','\U6FF','\U06FF','\U700','\U0700','\U701','\U0701','\U702','\U0702','\U703','\U0703','\U704','\U0704','\U705','\U0705','\U706','\U0706','\U707','\U0707','\U708','\U0708','\U709','\U0709','\U70A','\U070A','\U70B','\U070B','\U70C','\U070C','\U70D','\U070D','\U70E','\U070E','\U70F','\U070F','\U710','\U0710','\U711','\U0711','\U712','\U0712','\U713','\U0713','\U714','\U0714','\U715','\U0715','\U716','\U0716','\U717','\U0717','\U718','\U0718','\U719','\U0719','\U71A','\U071A','\U71B','\U071B','\U71C','\U071C','\U71D','\U071D','\U71E','\U071E','\U71F','\U071F','\U720','\U0720','\U721','\U0721','\U722','\U0722','\U723','\U0723','\U724','\U0724','\U725','\U0725','\U726','\U0726','\U727','\U0727','\U728','\U0728','\U729','\U0729','\U72A','\U072A','\U72B','\U072B','\U72C','\U072C','\U72D','\U072D','\U72E','\U072E','\U72F','\U072F','\U730','\U0730','\U731','\U0731','\U732','\U0732','\U733','\U0733','\U734','\U0734','\U735','\U0735','\U736','\U0736','\U737','\U0737','\U738','\U0738','\U739','\U0739','\U73A','\U073A','\U73B','\U073B','\U73C','\U073C','\U73D','\U073D','\U73E','\U073E','\U73F','\U073F','\U740','\U0740','\U741','\U0741','\U742','\U0742','\U743','\U0743','\U744','\U0744','\U745','\U0745','\U746','\U0746','\U747','\U0747','\U748','\U0748','\U749','\U0749','\U74A','\U074A','\U74B','\U074B','\U74C','\U074C','\U74D','\U074D','\U74E','\U074E','\U74F','\U074F','\U750','\U0750','\U751','\U0751','\U752','\U0752','\U753','\U0753','\U754','\U0754','\U755','\U0755','\U756','\U0756','\U757','\U0757','\U758','\U0758','\U759','\U0759','\U75A','\U075A','\U75B','\U075B','\U75C','\U075C','\U75D','\U075D','\U75E','\U075E','\U75F','\U075F','\U760','\U0760','\U761','\U0761','\U762','\U0762','\U763','\U0763','\U764','\U0764','\U765','\U0765','\U766','\U0766','\U767','\U0767','\U768','\U0768','\U769','\U0769','\U76A','\U076A','\U76B','\U076B','\U76C','\U076C','\U76D','\U076D','\U76E','\U076E','\U76F','\U076F','\U770','\U0770','\U771','\U0771','\U772','\U0772','\U773','\U0773','\U774','\U0774','\U775','\U0775','\U776','\U0776','\U777','\U0777','\U778','\U0778','\U779','\U0779','\U77A','\U077A','\U77B','\U077B','\U77C','\U077C','\U77D','\U077D','\U77E','\U077E','\U77F','\U077F','\U780','\U0780','\U781','\U0781','\U782','\U0782','\U783','\U0783','\U784','\U0784','\U785','\U0785','\U786','\U0786','\U787','\U0787','\U788','\U0788','\U789','\U0789','\U78A','\U078A','\U78B','\U078B','\U78C','\U078C','\U78D','\U078D','\U78E','\U078E','\U78F','\U078F','\U790','\U0790','\U791','\U0791','\U792','\U0792','\U793','\U0793','\U794','\U0794','\U795','\U0795','\U796','\U0796','\U797','\U0797','\U798','\U0798','\U799','\U0799','\U79A','\U079A','\U79B','\U079B','\U79C','\U079C','\U79D','\U079D','\U79E','\U079E','\U79F','\U079F','\U7A0','\U07A0','\U7A1','\U07A1','\U7A2','\U07A2','\U7A3','\U07A3','\U7A4','\U07A4','\U7A5','\U07A5','\U7A6','\U07A6','\U7A7','\U07A7','\U7A8','\U07A8','\U7A9','\U07A9','\U7AA','\U07AA','\U7AB','\U07AB','\U7AC','\U07AC','\U7AD','\U07AD','\U7AE','\U07AE','\U7AF','\U07AF','\U7B0','\U07B0','\U7B1','\U07B1','\U7B2','\U07B2','\U7B3','\U07B3','\U7B4','\U07B4','\U7B5','\U07B5','\U7B6','\U07B6','\U7B7','\U07B7','\U7B8','\U07B8','\U7B9','\U07B9','\U7BA','\U07BA','\U7BB','\U07BB','\U7BC','\U07BC','\U7BD','\U07BD','\U7BE','\U07BE','\U7BF','\U07BF','\U7C0','\U07C0','\U7C1','\U07C1','\U7C2','\U07C2','\U7C3','\U07C3','\U7C4','\U07C4','\U7C5','\U07C5','\U7C6','\U07C6','\U7C7','\U07C7','\U7C8','\U07C8','\U7C9','\U07C9','\U7CA','\U07CA','\U7CB','\U07CB','\U7CC','\U07CC','\U7CD','\U07CD','\U7CE','\U07CE','\U7CF','\U07CF','\U7D0','\U07D0','\U7D1','\U07D1','\U7D2','\U07D2','\U7D3','\U07D3','\U7D4','\U07D4','\U7D5','\U07D5','\U7D6','\U07D6','\U7D7','\U07D7','\U7D8','\U07D8','\U7D9','\U07D9','\U7DA','\U07DA','\U7DB','\U07DB','\U7DC','\U07DC','\U7DD','\U07DD','\U7DE','\U07DE','\U7DF','\U07DF','\U7E0','\U07E0','\U7E1','\U07E1','\U7E2','\U07E2','\U7E3','\U07E3','\U7E4','\U07E4','\U7E5','\U07E5','\U7E6','\U07E6','\U7E7','\U07E7','\U7E8','\U07E8','\U7E9','\U07E9','\U7EA','\U07EA','\U7EB','\U07EB','\U7EC','\U07EC','\U7ED','\U07ED','\U7EE','\U07EE','\U7EF','\U07EF','\U7F0','\U07F0','\U7F1','\U07F1','\U7F2','\U07F2','\U7F3','\U07F3','\U7F4','\U07F4','\U7F5','\U07F5','\U7F6','\U07F6','\U7F7','\U07F7','\U7F8','\U07F8','\U7F9','\U07F9','\U7FA','\U07FA','\U7FB','\U07FB','\U7FC','\U07FC','\U7FD','\U07FD','\U7FE','\U07FE','\U7FF','\U07FF','\U800','\U0800','\U801','\U0801','\U802','\U0802','\U803','\U0803','\U804','\U0804','\U805','\U0805','\U806','\U0806','\U807','\U0807','\U808','\U0808','\U809','\U0809','\U80A','\U080A','\U80B','\U080B','\U80C','\U080C','\U80D','\U080D','\U80E','\U080E','\U80F','\U080F','\U810','\U0810','\U811','\U0811','\U812','\U0812','\U813','\U0813','\U814','\U0814','\U815','\U0815','\U816','\U0816','\U817','\U0817','\U818','\U0818','\U819','\U0819','\U81A','\U081A','\U81B','\U081B','\U81C','\U081C','\U81D','\U081D','\U81E','\U081E','\U81F','\U081F','\U820','\U0820','\U821','\U0821','\U822','\U0822','\U823','\U0823','\U824','\U0824','\U825','\U0825','\U826','\U0826','\U827','\U0827','\U828','\U0828','\U829','\U0829','\U82A','\U082A','\U82B','\U082B','\U82C','\U082C','\U82D','\U082D','\U82E','\U082E','\U82F','\U082F','\U830','\U0830','\U831','\U0831','\U832','\U0832','\U833','\U0833','\U834','\U0834','\U835','\U0835','\U836','\U0836','\U837','\U0837','\U838','\U0838','\U839','\U0839','\U83A','\U083A','\U83B','\U083B','\U83C','\U083C','\U83D','\U083D','\U83E','\U083E','\U83F','\U083F','\U840','\U0840','\U841','\U0841','\U842','\U0842','\U843','\U0843','\U844','\U0844','\U845','\U0845','\U846','\U0846','\U847','\U0847','\U848','\U0848','\U849','\U0849','\U84A','\U084A','\U84B','\U084B','\U84C','\U084C','\U84D','\U084D','\U84E','\U084E','\U84F','\U084F','\U850','\U0850','\U851','\U0851','\U852','\U0852','\U853','\U0853','\U854','\U0854','\U855','\U0855','\U856','\U0856','\U857','\U0857','\U858','\U0858','\U859','\U0859','\U85A','\U085A','\U85B','\U085B','\U85C','\U085C','\U85D','\U085D','\U85E','\U085E','\U85F','\U085F','\U860','\U0860','\U861','\U0861','\U862','\U0862','\U863','\U0863','\U864','\U0864','\U865','\U0865','\U866','\U0866','\U867','\U0867','\U868','\U0868','\U869','\U0869','\U86A','\U086A','\U86B','\U086B','\U86C','\U086C','\U86D','\U086D','\U86E','\U086E','\U86F','\U086F','\U870','\U0870','\U871','\U0871','\U872','\U0872','\U873','\U0873','\U874','\U0874','\U875','\U0875','\U876','\U0876','\U877','\U0877','\U878','\U0878','\U879','\U0879','\U87A','\U087A','\U87B','\U087B','\U87C','\U087C','\U87D','\U087D','\U87E','\U087E','\U87F','\U087F','\U880','\U0880','\U881','\U0881','\U882','\U0882','\U883','\U0883','\U884','\U0884','\U885','\U0885','\U886','\U0886','\U887','\U0887','\U888','\U0888','\U889','\U0889','\U88A','\U088A','\U88B','\U088B','\U88C','\U088C','\U88D','\U088D','\U88E','\U088E','\U88F','\U088F','\U890','\U0890','\U891','\U0891','\U892','\U0892','\U893','\U0893','\U894','\U0894','\U895','\U0895','\U896','\U0896','\U897','\U0897','\U898','\U0898','\U899','\U0899','\U89A','\U089A','\U89B','\U089B','\U89C','\U089C','\U89D','\U089D','\U89E','\U089E','\U89F','\U089F','\U8A0','\U08A0','\U8A1','\U08A1','\U8A2','\U08A2','\U8A3','\U08A3','\U8A4','\U08A4','\U8A5','\U08A5','\U8A6','\U08A6','\U8A7','\U08A7','\U8A8','\U08A8','\U8A9','\U08A9','\U8AA','\U08AA','\U8AB','\U08AB','\U8AC','\U08AC','\U8AD','\U08AD','\U8AE','\U08AE','\U8AF','\U08AF','\U8B0','\U08B0','\U8B1','\U08B1','\U8B2','\U08B2','\U8B3','\U08B3','\U8B4','\U08B4','\U8B5','\U08B5','\U8B6','\U08B6','\U8B7','\U08B7','\U8B8','\U08B8','\U8B9','\U08B9','\U8BA','\U08BA','\U8BB','\U08BB','\U8BC','\U08BC','\U8BD','\U08BD','\U8BE','\U08BE','\U8BF','\U08BF','\U8C0','\U08C0','\U8C1','\U08C1','\U8C2','\U08C2','\U8C3','\U08C3','\U8C4','\U08C4','\U8C5','\U08C5','\U8C6','\U08C6','\U8C7','\U08C7','\U8C8','\U08C8','\U8C9','\U08C9','\U8CA','\U08CA','\U8CB','\U08CB','\U8CC','\U08CC','\U8CD','\U08CD','\U8CE','\U08CE','\U8CF','\U08CF','\U8D0','\U08D0','\U8D1','\U08D1','\U8D2','\U08D2','\U8D3','\U08D3','\U8D4','\U08D4','\U8D5','\U08D5','\U8D6','\U08D6','\U8D7','\U08D7','\U8D8','\U08D8','\U8D9','\U08D9','\U8DA','\U08DA','\U8DB','\U08DB','\U8DC','\U08DC','\U8DD','\U08DD','\U8DE','\U08DE','\U8DF','\U08DF','\U8E0','\U08E0','\U8E1','\U08E1','\U8E2','\U08E2','\U8E3','\U08E3','\U8E4','\U08E4','\U8E5','\U08E5','\U8E6','\U08E6','\U8E7','\U08E7','\U8E8','\U08E8','\U8E9','\U08E9','\U8EA','\U08EA','\U8EB','\U08EB','\U8EC','\U08EC','\U8ED','\U08ED','\U8EE','\U08EE','\U8EF','\U08EF','\U8F0','\U08F0','\U8F1','\U08F1','\U8F2','\U08F2','\U8F3','\U08F3','\U8F4','\U08F4','\U8F5','\U08F5','\U8F6','\U08F6','\U8F7','\U08F7','\U8F8','\U08F8','\U8F9','\U08F9','\U8FA','\U08FA','\U8FB','\U08FB','\U8FC','\U08FC','\U8FD','\U08FD','\U8FE','\U08FE','\U8FF','\U08FF','\U900','\U0900','\U901','\U0901','\U902','\U0902','\U903','\U0903','\U904','\U0904','\U905','\U0905','\U906','\U0906','\U907','\U0907','\U908','\U0908','\U909','\U0909','\U90A','\U090A','\U90B','\U090B','\U90C','\U090C','\U90D','\U090D','\U90E','\U090E','\U90F','\U090F','\U910','\U0910','\U911','\U0911','\U912','\U0912','\U913','\U0913','\U914','\U0914','\U915','\U0915','\U916','\U0916','\U917','\U0917','\U918','\U0918','\U919','\U0919','\U91A','\U091A','\U91B','\U091B','\U91C','\U091C','\U91D','\U091D','\U91E','\U091E','\U91F','\U091F','\U920','\U0920','\U921','\U0921','\U922','\U0922','\U923','\U0923','\U924','\U0924','\U925','\U0925','\U926','\U0926','\U927','\U0927','\U928','\U0928','\U929','\U0929','\U92A','\U092A','\U92B','\U092B','\U92C','\U092C','\U92D','\U092D','\U92E','\U092E','\U92F','\U092F','\U930','\U0930','\U931','\U0931','\U932','\U0932','\U933','\U0933','\U934','\U0934','\U935','\U0935','\U936','\U0936','\U937','\U0937','\U938','\U0938','\U939','\U0939','\U93A','\U093A','\U93B','\U093B','\U93C','\U093C','\U93D','\U093D','\U93E','\U093E','\U93F','\U093F','\U940','\U0940','\U941','\U0941','\U942','\U0942','\U943','\U0943','\U944','\U0944','\U945','\U0945','\U946','\U0946','\U947','\U0947','\U948','\U0948','\U949','\U0949','\U94A','\U094A','\U94B','\U094B','\U94C','\U094C','\U94D','\U094D','\U94E','\U094E','\U94F','\U094F','\U950','\U0950','\U951','\U0951','\U952','\U0952','\U953','\U0953','\U954','\U0954','\U955','\U0955','\U956','\U0956','\U957','\U0957','\U958','\U0958','\U959','\U0959','\U95A','\U095A','\U95B','\U095B','\U95C','\U095C','\U95D','\U095D','\U95E','\U095E','\U95F','\U095F','\U960','\U0960','\U961','\U0961','\U962','\U0962','\U963','\U0963','\U964','\U0964','\U965','\U0965','\U966','\U0966','\U967','\U0967','\U968','\U0968','\U969','\U0969','\U96A','\U096A','\U96B','\U096B','\U96C','\U096C','\U96D','\U096D','\U96E','\U096E','\U96F','\U096F','\U970','\U0970','\U971','\U0971','\U972','\U0972','\U973','\U0973','\U974','\U0974','\U975','\U0975','\U976','\U0976','\U977','\U0977','\U978','\U0978','\U979','\U0979','\U97A','\U097A','\U97B','\U097B','\U97C','\U097C','\U97D','\U097D','\U97E','\U097E','\U97F','\U097F','\U980','\U0980','\U981','\U0981','\U982','\U0982','\U983','\U0983','\U984','\U0984','\U985','\U0985','\U986','\U0986','\U987','\U0987','\U988','\U0988','\U989','\U0989','\U98A','\U098A','\U98B','\U098B','\U98C','\U098C','\U98D','\U098D','\U98E','\U098E','\U98F','\U098F','\U990','\U0990','\U991','\U0991','\U992','\U0992','\U993','\U0993','\U994','\U0994','\U995','\U0995','\U996','\U0996','\U997','\U0997','\U998','\U0998','\U999','\U0999','\U99A','\U099A','\U99B','\U099B','\U99C','\U099C','\U99D','\U099D','\U99E','\U099E','\U99F','\U099F','\U9A0','\U09A0','\U9A1','\U09A1','\U9A2','\U09A2','\U9A3','\U09A3','\U9A4','\U09A4','\U9A5','\U09A5','\U9A6','\U09A6','\U9A7','\U09A7','\U9A8','\U09A8','\U9A9','\U09A9','\U9AA','\U09AA','\U9AB','\U09AB','\U9AC','\U09AC','\U9AD','\U09AD','\U9AE','\U09AE','\U9AF','\U09AF','\U9B0','\U09B0','\U9B1','\U09B1','\U9B2','\U09B2','\U9B3','\U09B3','\U9B4','\U09B4','\U9B5','\U09B5','\U9B6','\U09B6','\U9B7','\U09B7','\U9B8','\U09B8','\U9B9','\U09B9','\U9BA','\U09BA','\U9BB','\U09BB','\U9BC','\U09BC','\U9BD','\U09BD','\U9BE','\U09BE','\U9BF','\U09BF','\U9C0','\U09C0','\U9C1','\U09C1','\U9C2','\U09C2','\U9C3','\U09C3','\U9C4','\U09C4','\U9C5','\U09C5','\U9C6','\U09C6','\U9C7','\U09C7','\U9C8','\U09C8','\U9C9','\U09C9','\U9CA','\U09CA','\U9CB','\U09CB','\U9CC','\U09CC','\U9CD','\U09CD','\U9CE','\U09CE','\U9CF','\U09CF','\U9D0','\U09D0','\U9D1','\U09D1','\U9D2','\U09D2','\U9D3','\U09D3','\U9D4','\U09D4','\U9D5','\U09D5','\U9D6','\U09D6','\U9D7','\U09D7','\U9D8','\U09D8','\U9D9','\U09D9','\U9DA','\U09DA','\U9DB','\U09DB','\U9DC','\U09DC','\U9DD','\U09DD','\U9DE','\U09DE','\U9DF','\U09DF','\U9E0','\U09E0','\U9E1','\U09E1','\U9E2','\U09E2','\U9E3','\U09E3','\U9E4','\U09E4','\U9E5','\U09E5','\U9E6','\U09E6','\U9E7','\U09E7','\U9E8','\U09E8','\U9E9','\U09E9','\U9EA','\U09EA','\U9EB','\U09EB','\U9EC','\U09EC','\U9ED','\U09ED','\U9EE','\U09EE','\U9EF','\U09EF','\U9F0','\U09F0','\U9F1','\U09F1','\U9F2','\U09F2','\U9F3','\U09F3','\U9F4','\U09F4','\U9F5','\U09F5','\U9F6','\U09F6','\U9F7','\U09F7','\U9F8','\U09F8','\U9F9','\U09F9','\U9FA','\U09FA','\U9FB','\U09FB','\U9FC','\U09FC','\U9FD','\U09FD','\U9FE','\U09FE','\U9FF','\U09FF','\UA00','\U0A00','\UA01','\U0A01','\UA02','\U0A02','\UA03','\U0A03','\UA04','\U0A04','\UA05','\U0A05','\UA06','\U0A06','\UA07','\U0A07','\UA08','\U0A08','\UA09','\U0A09','\UA0A','\U0A0A','\UA0B','\U0A0B','\UA0C','\U0A0C','\UA0D','\U0A0D','\UA0E','\U0A0E','\UA0F','\U0A0F','\UA10','\U0A10','\UA11','\U0A11','\UA12','\U0A12','\UA13','\U0A13','\UA14','\U0A14','\UA15','\U0A15','\UA16','\U0A16','\UA17','\U0A17','\UA18','\U0A18','\UA19','\U0A19','\UA1A','\U0A1A','\UA1B','\U0A1B','\UA1C','\U0A1C','\UA1D','\U0A1D','\UA1E','\U0A1E','\UA1F','\U0A1F','\UA20','\U0A20','\UA21','\U0A21','\UA22','\U0A22','\UA23','\U0A23','\UA24','\U0A24','\UA25','\U0A25','\UA26','\U0A26','\UA27','\U0A27','\UA28','\U0A28','\UA29','\U0A29','\UA2A','\U0A2A','\UA2B','\U0A2B','\UA2C','\U0A2C','\UA2D','\U0A2D','\UA2E','\U0A2E','\UA2F','\U0A2F','\UA30','\U0A30','\UA31','\U0A31','\UA32','\U0A32','\UA33','\U0A33','\UA34','\U0A34','\UA35','\U0A35','\UA36','\U0A36','\UA37','\U0A37','\UA38','\U0A38','\UA39','\U0A39','\UA3A','\U0A3A','\UA3B','\U0A3B','\UA3C','\U0A3C','\UA3D','\U0A3D','\UA3E','\U0A3E','\UA3F','\U0A3F','\UA40','\U0A40','\UA41','\U0A41','\UA42','\U0A42','\UA43','\U0A43','\UA44','\U0A44','\UA45','\U0A45','\UA46','\U0A46','\UA47','\U0A47','\UA48','\U0A48','\UA49','\U0A49','\UA4A','\U0A4A','\UA4B','\U0A4B','\UA4C','\U0A4C','\UA4D','\U0A4D','\UA4E','\U0A4E','\UA4F','\U0A4F','\UA50','\U0A50','\UA51','\U0A51','\UA52','\U0A52','\UA53','\U0A53','\UA54','\U0A54','\UA55','\U0A55','\UA56','\U0A56','\UA57','\U0A57','\UA58','\U0A58','\UA59','\U0A59','\UA5A','\U0A5A','\UA5B','\U0A5B','\UA5C','\U0A5C','\UA5D','\U0A5D','\UA5E','\U0A5E','\UA5F','\U0A5F','\UA60','\U0A60','\UA61','\U0A61','\UA62','\U0A62','\UA63','\U0A63','\UA64','\U0A64','\UA65','\U0A65','\UA66','\U0A66','\UA67','\U0A67','\UA68','\U0A68','\UA69','\U0A69','\UA6A','\U0A6A','\UA6B','\U0A6B','\UA6C','\U0A6C','\UA6D','\U0A6D','\UA6E','\U0A6E','\UA6F','\U0A6F','\UA70','\U0A70','\UA71','\U0A71','\UA72','\U0A72','\UA73','\U0A73','\UA74','\U0A74','\UA75','\U0A75','\UA76','\U0A76','\UA77','\U0A77','\UA78','\U0A78','\UA79','\U0A79','\UA7A','\U0A7A','\UA7B','\U0A7B','\UA7C','\U0A7C','\UA7D','\U0A7D','\UA7E','\U0A7E','\UA7F','\U0A7F','\UA80','\U0A80','\UA81','\U0A81','\UA82','\U0A82','\UA83','\U0A83','\UA84','\U0A84','\UA85','\U0A85','\UA86','\U0A86','\UA87','\U0A87','\UA88','\U0A88','\UA89','\U0A89','\UA8A','\U0A8A','\UA8B','\U0A8B','\UA8C','\U0A8C','\UA8D','\U0A8D','\UA8E','\U0A8E','\UA8F','\U0A8F','\UA90','\U0A90','\UA91','\U0A91','\UA92','\U0A92','\UA93','\U0A93','\UA94','\U0A94','\UA95','\U0A95','\UA96','\U0A96','\UA97','\U0A97','\UA98','\U0A98','\UA99','\U0A99','\UA9A','\U0A9A','\UA9B','\U0A9B','\UA9C','\U0A9C','\UA9D','\U0A9D','\UA9E','\U0A9E','\UA9F','\U0A9F','\UAA0','\U0AA0','\UAA1','\U0AA1','\UAA2','\U0AA2','\UAA3','\U0AA3','\UAA4','\U0AA4','\UAA5','\U0AA5','\UAA6','\U0AA6','\UAA7','\U0AA7','\UAA8','\U0AA8','\UAA9','\U0AA9','\UAAA','\U0AAA','\UAAB','\U0AAB','\UAAC','\U0AAC','\UAAD','\U0AAD','\UAAE','\U0AAE','\UAAF','\U0AAF','\UAB0','\U0AB0','\UAB1','\U0AB1','\UAB2','\U0AB2','\UAB3','\U0AB3','\UAB4','\U0AB4','\UAB5','\U0AB5','\UAB6','\U0AB6','\UAB7','\U0AB7','\UAB8','\U0AB8','\UAB9','\U0AB9','\UABA','\U0ABA','\UABB','\U0ABB','\UABC','\U0ABC','\UABD','\U0ABD','\UABE','\U0ABE','\UABF','\U0ABF','\UAC0','\U0AC0','\UAC1','\U0AC1','\UAC2','\U0AC2','\UAC3','\U0AC3','\UAC4','\U0AC4','\UAC5','\U0AC5','\UAC6','\U0AC6','\UAC7','\U0AC7','\UAC8','\U0AC8','\UAC9','\U0AC9','\UACA','\U0ACA','\UACB','\U0ACB','\UACC','\U0ACC','\UACD','\U0ACD','\UACE','\U0ACE','\UACF','\U0ACF','\UAD0','\U0AD0','\UAD1','\U0AD1','\UAD2','\U0AD2','\UAD3','\U0AD3','\UAD4','\U0AD4','\UAD5','\U0AD5','\UAD6','\U0AD6','\UAD7','\U0AD7','\UAD8','\U0AD8','\UAD9','\U0AD9','\UADA','\U0ADA','\UADB','\U0ADB','\UADC','\U0ADC','\UADD','\U0ADD','\UADE','\U0ADE','\UADF','\U0ADF','\UAE0','\U0AE0','\UAE1','\U0AE1','\UAE2','\U0AE2','\UAE3','\U0AE3','\UAE4','\U0AE4','\UAE5','\U0AE5','\UAE6','\U0AE6','\UAE7','\U0AE7','\UAE8','\U0AE8','\UAE9','\U0AE9','\UAEA','\U0AEA','\UAEB','\U0AEB','\UAEC','\U0AEC','\UAED','\U0AED','\UAEE','\U0AEE','\UAEF','\U0AEF','\UAF0','\U0AF0','\UAF1','\U0AF1','\UAF2','\U0AF2','\UAF3','\U0AF3','\UAF4','\U0AF4','\UAF5','\U0AF5','\UAF6','\U0AF6','\UAF7','\U0AF7','\UAF8','\U0AF8','\UAF9','\U0AF9','\UAFA','\U0AFA','\UAFB','\U0AFB','\UAFC','\U0AFC','\UAFD','\U0AFD','\UAFE','\U0AFE','\UAFF','\U0AFF','\UB00','\U0B00','\UB01','\U0B01','\UB02','\U0B02','\UB03','\U0B03','\UB04','\U0B04','\UB05','\U0B05','\UB06','\U0B06','\UB07','\U0B07','\UB08','\U0B08','\UB09','\U0B09','\UB0A','\U0B0A','\UB0B','\U0B0B','\UB0C','\U0B0C','\UB0D','\U0B0D','\UB0E','\U0B0E','\UB0F','\U0B0F','\UB10','\U0B10','\UB11','\U0B11','\UB12','\U0B12','\UB13','\U0B13','\UB14','\U0B14','\UB15','\U0B15','\UB16','\U0B16','\UB17','\U0B17','\UB18','\U0B18','\UB19','\U0B19','\UB1A','\U0B1A','\UB1B','\U0B1B','\UB1C','\U0B1C','\UB1D','\U0B1D','\UB1E','\U0B1E','\UB1F','\U0B1F','\UB20','\U0B20','\UB21','\U0B21','\UB22','\U0B22','\UB23','\U0B23','\UB24','\U0B24','\UB25','\U0B25','\UB26','\U0B26','\UB27','\U0B27','\UB28','\U0B28','\UB29','\U0B29','\UB2A','\U0B2A','\UB2B','\U0B2B','\UB2C','\U0B2C','\UB2D','\U0B2D','\UB2E','\U0B2E','\UB2F','\U0B2F','\UB30','\U0B30','\UB31','\U0B31','\UB32','\U0B32','\UB33','\U0B33','\UB34','\U0B34','\UB35','\U0B35','\UB36','\U0B36','\UB37','\U0B37','\UB38','\U0B38','\UB39','\U0B39','\UB3A','\U0B3A','\UB3B','\U0B3B','\UB3C','\U0B3C','\UB3D','\U0B3D','\UB3E','\U0B3E','\UB3F','\U0B3F','\UB40','\U0B40','\UB41','\U0B41','\UB42','\U0B42','\UB43','\U0B43','\UB44','\U0B44','\UB45','\U0B45','\UB46','\U0B46','\UB47','\U0B47','\UB48','\U0B48','\UB49','\U0B49','\UB4A','\U0B4A','\UB4B','\U0B4B','\UB4C','\U0B4C','\UB4D','\U0B4D','\UB4E','\U0B4E','\UB4F','\U0B4F','\UB50','\U0B50','\UB51','\U0B51','\UB52','\U0B52','\UB53','\U0B53','\UB54','\U0B54','\UB55','\U0B55','\UB56','\U0B56','\UB57','\U0B57','\UB58','\U0B58','\UB59','\U0B59','\UB5A','\U0B5A','\UB5B','\U0B5B','\UB5C','\U0B5C','\UB5D','\U0B5D','\UB5E','\U0B5E','\UB5F','\U0B5F','\UB60','\U0B60','\UB61','\U0B61','\UB62','\U0B62','\UB63','\U0B63','\UB64','\U0B64','\UB65','\U0B65','\UB66','\U0B66','\UB67','\U0B67','\UB68','\U0B68','\UB69','\U0B69','\UB6A','\U0B6A','\UB6B','\U0B6B','\UB6C','\U0B6C','\UB6D','\U0B6D','\UB6E','\U0B6E','\UB6F','\U0B6F','\UB70','\U0B70','\UB71','\U0B71','\UB72','\U0B72','\UB73','\U0B73','\UB74','\U0B74','\UB75','\U0B75','\UB76','\U0B76','\UB77','\U0B77','\UB78','\U0B78','\UB79','\U0B79','\UB7A','\U0B7A','\UB7B','\U0B7B','\UB7C','\U0B7C','\UB7D','\U0B7D','\UB7E','\U0B7E','\UB7F','\U0B7F','\UB80','\U0B80','\UB81','\U0B81','\UB82','\U0B82','\UB83','\U0B83','\UB84','\U0B84','\UB85','\U0B85','\UB86','\U0B86','\UB87','\U0B87','\UB88','\U0B88','\UB89','\U0B89','\UB8A','\U0B8A','\UB8B','\U0B8B','\UB8C','\U0B8C','\UB8D','\U0B8D','\UB8E','\U0B8E','\UB8F','\U0B8F','\UB90','\U0B90','\UB91','\U0B91','\UB92','\U0B92','\UB93','\U0B93','\UB94','\U0B94','\UB95','\U0B95','\UB96','\U0B96','\UB97','\U0B97','\UB98','\U0B98','\UB99','\U0B99','\UB9A','\U0B9A','\UB9B','\U0B9B','\UB9C','\U0B9C','\UB9D','\U0B9D','\UB9E','\U0B9E','\UB9F','\U0B9F','\UBA0','\U0BA0','\UBA1','\U0BA1','\UBA2','\U0BA2','\UBA3','\U0BA3','\UBA4','\U0BA4','\UBA5','\U0BA5','\UBA6','\U0BA6','\UBA7','\U0BA7','\UBA8','\U0BA8','\UBA9','\U0BA9','\UBAA','\U0BAA','\UBAB','\U0BAB','\UBAC','\U0BAC','\UBAD','\U0BAD','\UBAE','\U0BAE','\UBAF','\U0BAF','\UBB0','\U0BB0','\UBB1','\U0BB1','\UBB2','\U0BB2','\UBB3','\U0BB3','\UBB4','\U0BB4','\UBB5','\U0BB5','\UBB6','\U0BB6','\UBB7','\U0BB7','\UBB8','\U0BB8','\UBB9','\U0BB9','\UBBA','\U0BBA','\UBBB','\U0BBB','\UBBC','\U0BBC','\UBBD','\U0BBD','\UBBE','\U0BBE','\UBBF','\U0BBF','\UBC0','\U0BC0','\UBC1','\U0BC1','\UBC2','\U0BC2','\UBC3','\U0BC3','\UBC4','\U0BC4','\UBC5','\U0BC5','\UBC6','\U0BC6','\UBC7','\U0BC7','\UBC8','\U0BC8','\UBC9','\U0BC9','\UBCA','\U0BCA','\UBCB','\U0BCB','\UBCC','\U0BCC','\UBCD','\U0BCD','\UBCE','\U0BCE','\UBCF','\U0BCF','\UBD0','\U0BD0','\UBD1','\U0BD1','\UBD2','\U0BD2','\UBD3','\U0BD3','\UBD4','\U0BD4','\UBD5','\U0BD5','\UBD6','\U0BD6','\UBD7','\U0BD7','\UBD8','\U0BD8','\UBD9','\U0BD9','\UBDA','\U0BDA','\UBDB','\U0BDB','\UBDC','\U0BDC','\UBDD','\U0BDD','\UBDE','\U0BDE','\UBDF','\U0BDF','\UBE0','\U0BE0','\UBE1','\U0BE1','\UBE2','\U0BE2','\UBE3','\U0BE3','\UBE4','\U0BE4','\UBE5','\U0BE5','\UBE6','\U0BE6','\UBE7','\U0BE7','\UBE8','\U0BE8','\UBE9','\U0BE9','\UBEA','\U0BEA','\UBEB','\U0BEB','\UBEC','\U0BEC','\UBED','\U0BED','\UBEE','\U0BEE','\UBEF','\U0BEF','\UBF0','\U0BF0','\UBF1','\U0BF1','\UBF2','\U0BF2','\UBF3','\U0BF3','\UBF4','\U0BF4','\UBF5','\U0BF5','\UBF6','\U0BF6','\UBF7','\U0BF7','\UBF8','\U0BF8','\UBF9','\U0BF9','\UBFA','\U0BFA','\UBFB','\U0BFB','\UBFC','\U0BFC','\UBFD','\U0BFD','\UBFE','\U0BFE','\UBFF','\U0BFF','\UC00','\U0C00','\UC01','\U0C01','\UC02','\U0C02','\UC03','\U0C03','\UC04','\U0C04','\UC05','\U0C05','\UC06','\U0C06','\UC07','\U0C07','\UC08','\U0C08','\UC09','\U0C09','\UC0A','\U0C0A','\UC0B','\U0C0B','\UC0C','\U0C0C','\UC0D','\U0C0D','\UC0E','\U0C0E','\UC0F','\U0C0F','\UC10','\U0C10','\UC11','\U0C11','\UC12','\U0C12','\UC13','\U0C13','\UC14','\U0C14','\UC15','\U0C15','\UC16','\U0C16','\UC17','\U0C17','\UC18','\U0C18','\UC19','\U0C19','\UC1A','\U0C1A','\UC1B','\U0C1B','\UC1C','\U0C1C','\UC1D','\U0C1D','\UC1E','\U0C1E','\UC1F','\U0C1F','\UC20','\U0C20','\UC21','\U0C21','\UC22','\U0C22','\UC23','\U0C23','\UC24','\U0C24','\UC25','\U0C25','\UC26','\U0C26','\UC27','\U0C27','\UC28','\U0C28','\UC29','\U0C29','\UC2A','\U0C2A','\UC2B','\U0C2B','\UC2C','\U0C2C','\UC2D','\U0C2D','\UC2E','\U0C2E','\UC2F','\U0C2F','\UC30','\U0C30','\UC31','\U0C31','\UC32','\U0C32','\UC33','\U0C33','\UC34','\U0C34','\UC35','\U0C35','\UC36','\U0C36','\UC37','\U0C37','\UC38','\U0C38','\UC39','\U0C39','\UC3A','\U0C3A','\UC3B','\U0C3B','\UC3C','\U0C3C','\UC3D','\U0C3D','\UC3E','\U0C3E','\UC3F','\U0C3F','\UC40','\U0C40','\UC41','\U0C41','\UC42','\U0C42','\UC43','\U0C43','\UC44','\U0C44','\UC45','\U0C45','\UC46','\U0C46','\UC47','\U0C47','\UC48','\U0C48','\UC49','\U0C49','\UC4A','\U0C4A','\UC4B','\U0C4B','\UC4C','\U0C4C','\UC4D','\U0C4D','\UC4E','\U0C4E','\UC4F','\U0C4F','\UC50','\U0C50','\UC51','\U0C51','\UC52','\U0C52','\UC53','\U0C53','\UC54','\U0C54','\UC55','\U0C55','\UC56','\U0C56','\UC57','\U0C57','\UC58','\U0C58','\UC59','\U0C59','\UC5A','\U0C5A','\UC5B','\U0C5B','\UC5C','\U0C5C','\UC5D','\U0C5D','\UC5E','\U0C5E','\UC5F','\U0C5F','\UC60','\U0C60','\UC61','\U0C61','\UC62','\U0C62','\UC63','\U0C63','\UC64','\U0C64','\UC65','\U0C65','\UC66','\U0C66','\UC67','\U0C67','\UC68','\U0C68','\UC69','\U0C69','\UC6A','\U0C6A','\UC6B','\U0C6B','\UC6C','\U0C6C','\UC6D','\U0C6D','\UC6E','\U0C6E','\UC6F','\U0C6F','\UC70','\U0C70','\UC71','\U0C71','\UC72','\U0C72','\UC73','\U0C73','\UC74','\U0C74','\UC75','\U0C75','\UC76','\U0C76','\UC77','\U0C77','\UC78','\U0C78','\UC79','\U0C79','\UC7A','\U0C7A','\UC7B','\U0C7B','\UC7C','\U0C7C','\UC7D','\U0C7D','\UC7E','\U0C7E','\UC7F','\U0C7F','\UC80','\U0C80','\UC81','\U0C81','\UC82','\U0C82','\UC83','\U0C83','\UC84','\U0C84','\UC85','\U0C85','\UC86','\U0C86','\UC87','\U0C87','\UC88','\U0C88','\UC89','\U0C89','\UC8A','\U0C8A','\UC8B','\U0C8B','\UC8C','\U0C8C','\UC8D','\U0C8D','\UC8E','\U0C8E','\UC8F','\U0C8F','\UC90','\U0C90','\UC91','\U0C91','\UC92','\U0C92','\UC93','\U0C93','\UC94','\U0C94','\UC95','\U0C95','\UC96','\U0C96','\UC97','\U0C97','\UC98','\U0C98','\UC99','\U0C99','\UC9A','\U0C9A','\UC9B','\U0C9B','\UC9C','\U0C9C','\UC9D','\U0C9D','\UC9E','\U0C9E','\UC9F','\U0C9F','\UCA0','\U0CA0','\UCA1','\U0CA1','\UCA2','\U0CA2','\UCA3','\U0CA3','\UCA4','\U0CA4','\UCA5','\U0CA5','\UCA6','\U0CA6','\UCA7','\U0CA7','\UCA8','\U0CA8','\UCA9','\U0CA9','\UCAA','\U0CAA','\UCAB','\U0CAB','\UCAC','\U0CAC','\UCAD','\U0CAD','\UCAE','\U0CAE','\UCAF','\U0CAF','\UCB0','\U0CB0','\UCB1','\U0CB1','\UCB2','\U0CB2','\UCB3','\U0CB3','\UCB4','\U0CB4','\UCB5','\U0CB5','\UCB6','\U0CB6','\UCB7','\U0CB7','\UCB8','\U0CB8','\UCB9','\U0CB9','\UCBA','\U0CBA','\UCBB','\U0CBB','\UCBC','\U0CBC','\UCBD','\U0CBD','\UCBE','\U0CBE','\UCBF','\U0CBF','\UCC0','\U0CC0','\UCC1','\U0CC1','\UCC2','\U0CC2','\UCC3','\U0CC3','\UCC4','\U0CC4','\UCC5','\U0CC5','\UCC6','\U0CC6','\UCC7','\U0CC7','\UCC8','\U0CC8','\UCC9','\U0CC9','\UCCA','\U0CCA','\UCCB','\U0CCB','\UCCC','\U0CCC','\UCCD','\U0CCD','\UCCE','\U0CCE','\UCCF','\U0CCF','\UCD0','\U0CD0','\UCD1','\U0CD1','\UCD2','\U0CD2','\UCD3','\U0CD3','\UCD4','\U0CD4','\UCD5','\U0CD5','\UCD6','\U0CD6','\UCD7','\U0CD7','\UCD8','\U0CD8','\UCD9','\U0CD9','\UCDA','\U0CDA','\UCDB','\U0CDB','\UCDC','\U0CDC','\UCDD','\U0CDD','\UCDE','\U0CDE','\UCDF','\U0CDF','\UCE0','\U0CE0','\UCE1','\U0CE1','\UCE2','\U0CE2','\UCE3','\U0CE3','\UCE4','\U0CE4','\UCE5','\U0CE5','\UCE6','\U0CE6','\UCE7','\U0CE7','\UCE8','\U0CE8','\UCE9','\U0CE9','\UCEA','\U0CEA','\UCEB','\U0CEB','\UCEC','\U0CEC','\UCED','\U0CED','\UCEE','\U0CEE','\UCEF','\U0CEF','\UCF0','\U0CF0','\UCF1','\U0CF1','\UCF2','\U0CF2','\UCF3','\U0CF3','\UCF4','\U0CF4','\UCF5','\U0CF5','\UCF6','\U0CF6','\UCF7','\U0CF7','\UCF8','\U0CF8','\UCF9','\U0CF9','\UCFA','\U0CFA','\UCFB','\U0CFB','\UCFC','\U0CFC','\UCFD','\U0CFD','\UCFE','\U0CFE','\UCFF','\U0CFF','\UD00','\U0D00','\UD01','\U0D01','\UD02','\U0D02','\UD03','\U0D03','\UD04','\U0D04','\UD05','\U0D05','\UD06','\U0D06','\UD07','\U0D07','\UD08','\U0D08','\UD09','\U0D09','\UD0A','\U0D0A','\UD0B','\U0D0B','\UD0C','\U0D0C','\UD0D','\U0D0D','\UD0E','\U0D0E','\UD0F','\U0D0F','\UD10','\U0D10','\UD11','\U0D11','\UD12','\U0D12','\UD13','\U0D13','\UD14','\U0D14','\UD15','\U0D15','\UD16','\U0D16','\UD17','\U0D17','\UD18','\U0D18','\UD19','\U0D19','\UD1A','\U0D1A','\UD1B','\U0D1B','\UD1C','\U0D1C','\UD1D','\U0D1D','\UD1E','\U0D1E','\UD1F','\U0D1F','\UD20','\U0D20','\UD21','\U0D21','\UD22','\U0D22','\UD23','\U0D23','\UD24','\U0D24','\UD25','\U0D25','\UD26','\U0D26','\UD27','\U0D27','\UD28','\U0D28','\UD29','\U0D29','\UD2A','\U0D2A','\UD2B','\U0D2B','\UD2C','\U0D2C','\UD2D','\U0D2D','\UD2E','\U0D2E','\UD2F','\U0D2F','\UD30','\U0D30','\UD31','\U0D31','\UD32','\U0D32','\UD33','\U0D33','\UD34','\U0D34','\UD35','\U0D35','\UD36','\U0D36','\UD37','\U0D37','\UD38','\U0D38','\UD39','\U0D39','\UD3A','\U0D3A','\UD3B','\U0D3B','\UD3C','\U0D3C','\UD3D','\U0D3D','\UD3E','\U0D3E','\UD3F','\U0D3F','\UD40','\U0D40','\UD41','\U0D41','\UD42','\U0D42','\UD43','\U0D43','\UD44','\U0D44','\UD45','\U0D45','\UD46','\U0D46','\UD47','\U0D47','\UD48','\U0D48','\UD49','\U0D49','\UD4A','\U0D4A','\UD4B','\U0D4B','\UD4C','\U0D4C','\UD4D','\U0D4D','\UD4E','\U0D4E','\UD4F','\U0D4F','\UD50','\U0D50','\UD51','\U0D51','\UD52','\U0D52','\UD53','\U0D53','\UD54','\U0D54','\UD55','\U0D55','\UD56','\U0D56','\UD57','\U0D57','\UD58','\U0D58','\UD59','\U0D59','\UD5A','\U0D5A','\UD5B','\U0D5B','\UD5C','\U0D5C','\UD5D','\U0D5D','\UD5E','\U0D5E','\UD5F','\U0D5F','\UD60','\U0D60','\UD61','\U0D61','\UD62','\U0D62','\UD63','\U0D63','\UD64','\U0D64','\UD65','\U0D65','\UD66','\U0D66','\UD67','\U0D67','\UD68','\U0D68','\UD69','\U0D69','\UD6A','\U0D6A','\UD6B','\U0D6B','\UD6C','\U0D6C','\UD6D','\U0D6D','\UD6E','\U0D6E','\UD6F','\U0D6F','\UD70','\U0D70','\UD71','\U0D71','\UD72','\U0D72','\UD73','\U0D73','\UD74','\U0D74','\UD75','\U0D75','\UD76','\U0D76','\UD77','\U0D77','\UD78','\U0D78','\UD79','\U0D79','\UD7A','\U0D7A','\UD7B','\U0D7B','\UD7C','\U0D7C','\UD7D','\U0D7D','\UD7E','\U0D7E','\UD7F','\U0D7F','\UD80','\U0D80','\UD81','\U0D81','\UD82','\U0D82','\UD83','\U0D83','\UD84','\U0D84','\UD85','\U0D85','\UD86','\U0D86','\UD87','\U0D87','\UD88','\U0D88','\UD89','\U0D89','\UD8A','\U0D8A','\UD8B','\U0D8B','\UD8C','\U0D8C','\UD8D','\U0D8D','\UD8E','\U0D8E','\UD8F','\U0D8F','\UD90','\U0D90','\UD91','\U0D91','\UD92','\U0D92','\UD93','\U0D93','\UD94','\U0D94','\UD95','\U0D95','\UD96','\U0D96','\UD97','\U0D97','\UD98','\U0D98','\UD99','\U0D99','\UD9A','\U0D9A','\UD9B','\U0D9B','\UD9C','\U0D9C','\UD9D','\U0D9D','\UD9E','\U0D9E','\UD9F','\U0D9F','\UDA0','\U0DA0','\UDA1','\U0DA1','\UDA2','\U0DA2','\UDA3','\U0DA3','\UDA4','\U0DA4','\UDA5','\U0DA5','\UDA6','\U0DA6','\UDA7','\U0DA7','\UDA8','\U0DA8','\UDA9','\U0DA9','\UDAA','\U0DAA','\UDAB','\U0DAB','\UDAC','\U0DAC','\UDAD','\U0DAD','\UDAE','\U0DAE','\UDAF','\U0DAF','\UDB0','\U0DB0','\UDB1','\U0DB1','\UDB2','\U0DB2','\UDB3','\U0DB3','\UDB4','\U0DB4','\UDB5','\U0DB5','\UDB6','\U0DB6','\UDB7','\U0DB7','\UDB8','\U0DB8','\UDB9','\U0DB9','\UDBA','\U0DBA','\UDBB','\U0DBB','\UDBC','\U0DBC','\UDBD','\U0DBD','\UDBE','\U0DBE','\UDBF','\U0DBF','\UDC0','\U0DC0','\UDC1','\U0DC1','\UDC2','\U0DC2','\UDC3','\U0DC3','\UDC4','\U0DC4','\UDC5','\U0DC5','\UDC6','\U0DC6','\UDC7','\U0DC7','\UDC8','\U0DC8','\UDC9','\U0DC9','\UDCA','\U0DCA','\UDCB','\U0DCB','\UDCC','\U0DCC','\UDCD','\U0DCD','\UDCE','\U0DCE','\UDCF','\U0DCF','\UDD0','\U0DD0','\UDD1','\U0DD1','\UDD2','\U0DD2','\UDD3','\U0DD3','\UDD4','\U0DD4','\UDD5','\U0DD5','\UDD6','\U0DD6','\UDD7','\U0DD7','\UDD8','\U0DD8','\UDD9','\U0DD9','\UDDA','\U0DDA','\UDDB','\U0DDB','\UDDC','\U0DDC','\UDDD','\U0DDD','\UDDE','\U0DDE','\UDDF','\U0DDF','\UDE0','\U0DE0','\UDE1','\U0DE1','\UDE2','\U0DE2','\UDE3','\U0DE3','\UDE4','\U0DE4','\UDE5','\U0DE5','\UDE6','\U0DE6','\UDE7','\U0DE7','\UDE8','\U0DE8','\UDE9','\U0DE9','\UDEA','\U0DEA','\UDEB','\U0DEB','\UDEC','\U0DEC','\UDED','\U0DED','\UDEE','\U0DEE','\UDEF','\U0DEF','\UDF0','\U0DF0','\UDF1','\U0DF1','\UDF2','\U0DF2','\UDF3','\U0DF3','\UDF4','\U0DF4','\UDF5','\U0DF5','\UDF6','\U0DF6','\UDF7','\U0DF7','\UDF8','\U0DF8','\UDF9','\U0DF9','\UDFA','\U0DFA','\UDFB','\U0DFB','\UDFC','\U0DFC','\UDFD','\U0DFD','\UDFE','\U0DFE','\UDFF','\U0DFF','\UE00','\U0E00','\UE01','\U0E01','\UE02','\U0E02','\UE03','\U0E03','\UE04','\U0E04','\UE05','\U0E05','\UE06','\U0E06','\UE07','\U0E07','\UE08','\U0E08','\UE09','\U0E09','\UE0A','\U0E0A','\UE0B','\U0E0B','\UE0C','\U0E0C','\UE0D','\U0E0D','\UE0E','\U0E0E','\UE0F','\U0E0F','\UE10','\U0E10','\UE11','\U0E11','\UE12','\U0E12','\UE13','\U0E13','\UE14','\U0E14','\UE15','\U0E15','\UE16','\U0E16','\UE17','\U0E17','\UE18','\U0E18','\UE19','\U0E19','\UE1A','\U0E1A','\UE1B','\U0E1B','\UE1C','\U0E1C','\UE1D','\U0E1D','\UE1E','\U0E1E','\UE1F','\U0E1F','\UE20','\U0E20','\UE21','\U0E21','\UE22','\U0E22','\UE23','\U0E23','\UE24','\U0E24','\UE25','\U0E25','\UE26','\U0E26','\UE27','\U0E27','\UE28','\U0E28','\UE29','\U0E29','\UE2A','\U0E2A','\UE2B','\U0E2B','\UE2C','\U0E2C','\UE2D','\U0E2D','\UE2E','\U0E2E','\UE2F','\U0E2F','\UE30','\U0E30','\UE31','\U0E31','\UE32','\U0E32','\UE33','\U0E33','\UE34','\U0E34','\UE35','\U0E35','\UE36','\U0E36','\UE37','\U0E37','\UE38','\U0E38','\UE39','\U0E39','\UE3A','\U0E3A','\UE3B','\U0E3B','\UE3C','\U0E3C','\UE3D','\U0E3D','\UE3E','\U0E3E','\UE3F','\U0E3F','\UE40','\U0E40','\UE41','\U0E41','\UE42','\U0E42','\UE43','\U0E43','\UE44','\U0E44','\UE45','\U0E45','\UE46','\U0E46','\UE47','\U0E47','\UE48','\U0E48','\UE49','\U0E49','\UE4A','\U0E4A','\UE4B','\U0E4B','\UE4C','\U0E4C','\UE4D','\U0E4D','\UE4E','\U0E4E','\UE4F','\U0E4F','\UE50','\U0E50','\UE51','\U0E51','\UE52','\U0E52','\UE53','\U0E53','\UE54','\U0E54','\UE55','\U0E55','\UE56','\U0E56','\UE57','\U0E57','\UE58','\U0E58','\UE59','\U0E59','\UE5A','\U0E5A','\UE5B','\U0E5B','\UE5C','\U0E5C','\UE5D','\U0E5D','\UE5E','\U0E5E','\UE5F','\U0E5F','\UE60','\U0E60','\UE61','\U0E61','\UE62','\U0E62','\UE63','\U0E63','\UE64','\U0E64','\UE65','\U0E65','\UE66','\U0E66','\UE67','\U0E67','\UE68','\U0E68','\UE69','\U0E69','\UE6A','\U0E6A','\UE6B','\U0E6B','\UE6C','\U0E6C','\UE6D','\U0E6D','\UE6E','\U0E6E','\UE6F','\U0E6F','\UE70','\U0E70','\UE71','\U0E71','\UE72','\U0E72','\UE73','\U0E73','\UE74','\U0E74','\UE75','\U0E75','\UE76','\U0E76','\UE77','\U0E77','\UE78','\U0E78','\UE79','\U0E79','\UE7A','\U0E7A','\UE7B','\U0E7B','\UE7C','\U0E7C','\UE7D','\U0E7D','\UE7E','\U0E7E','\UE7F','\U0E7F','\UE80','\U0E80','\UE81','\U0E81','\UE82','\U0E82','\UE83','\U0E83','\UE84','\U0E84','\UE85','\U0E85','\UE86','\U0E86','\UE87','\U0E87','\UE88','\U0E88','\UE89','\U0E89','\UE8A','\U0E8A','\UE8B','\U0E8B','\UE8C','\U0E8C','\UE8D','\U0E8D','\UE8E','\U0E8E','\UE8F','\U0E8F','\UE90','\U0E90','\UE91','\U0E91','\UE92','\U0E92','\UE93','\U0E93','\UE94','\U0E94','\UE95','\U0E95','\UE96','\U0E96','\UE97','\U0E97','\UE98','\U0E98','\UE99','\U0E99','\UE9A','\U0E9A','\UE9B','\U0E9B','\UE9C','\U0E9C','\UE9D','\U0E9D','\UE9E','\U0E9E','\UE9F','\U0E9F','\UEA0','\U0EA0','\UEA1','\U0EA1','\UEA2','\U0EA2','\UEA3','\U0EA3','\UEA4','\U0EA4','\UEA5','\U0EA5','\UEA6','\U0EA6','\UEA7','\U0EA7','\UEA8','\U0EA8','\UEA9','\U0EA9','\UEAA','\U0EAA','\UEAB','\U0EAB','\UEAC','\U0EAC','\UEAD','\U0EAD','\UEAE','\U0EAE','\UEAF','\U0EAF','\UEB0','\U0EB0','\UEB1','\U0EB1','\UEB2','\U0EB2','\UEB3','\U0EB3','\UEB4','\U0EB4','\UEB5','\U0EB5','\UEB6','\U0EB6','\UEB7','\U0EB7','\UEB8','\U0EB8','\UEB9','\U0EB9','\UEBA','\U0EBA','\UEBB','\U0EBB','\UEBC','\U0EBC','\UEBD','\U0EBD','\UEBE','\U0EBE','\UEBF','\U0EBF','\UEC0','\U0EC0','\UEC1','\U0EC1','\UEC2','\U0EC2','\UEC3','\U0EC3','\UEC4','\U0EC4','\UEC5','\U0EC5','\UEC6','\U0EC6','\UEC7','\U0EC7','\UEC8','\U0EC8','\UEC9','\U0EC9','\UECA','\U0ECA','\UECB','\U0ECB','\UECC','\U0ECC','\UECD','\U0ECD','\UECE','\U0ECE','\UECF','\U0ECF','\UED0','\U0ED0','\UED1','\U0ED1','\UED2','\U0ED2','\UED3','\U0ED3','\UED4','\U0ED4','\UED5','\U0ED5','\UED6','\U0ED6','\UED7','\U0ED7','\UED8','\U0ED8','\UED9','\U0ED9','\UEDA','\U0EDA','\UEDB','\U0EDB','\UEDC','\U0EDC','\UEDD','\U0EDD','\UEDE','\U0EDE','\UEDF','\U0EDF','\UEE0','\U0EE0','\UEE1','\U0EE1','\UEE2','\U0EE2','\UEE3','\U0EE3','\UEE4','\U0EE4','\UEE5','\U0EE5','\UEE6','\U0EE6','\UEE7','\U0EE7','\UEE8','\U0EE8','\UEE9','\U0EE9','\UEEA','\U0EEA','\UEEB','\U0EEB','\UEEC','\U0EEC','\UEED','\U0EED','\UEEE','\U0EEE','\UEEF','\U0EEF','\UEF0','\U0EF0','\UEF1','\U0EF1','\UEF2','\U0EF2','\UEF3','\U0EF3','\UEF4','\U0EF4','\UEF5','\U0EF5','\UEF6','\U0EF6','\UEF7','\U0EF7','\UEF8','\U0EF8','\UEF9','\U0EF9','\UEFA','\U0EFA','\UEFB','\U0EFB','\UEFC','\U0EFC','\UEFD','\U0EFD','\UEFE','\U0EFE','\UEFF','\U0EFF','\UF00','\U0F00','\UF01','\U0F01','\UF02','\U0F02','\UF03','\U0F03','\UF04','\U0F04','\UF05','\U0F05','\UF06','\U0F06','\UF07','\U0F07','\UF08','\U0F08','\UF09','\U0F09','\UF0A','\U0F0A','\UF0B','\U0F0B','\UF0C','\U0F0C','\UF0D','\U0F0D','\UF0E','\U0F0E','\UF0F','\U0F0F','\UF10','\U0F10','\UF11','\U0F11','\UF12','\U0F12','\UF13','\U0F13','\UF14','\U0F14','\UF15','\U0F15','\UF16','\U0F16','\UF17','\U0F17','\UF18','\U0F18','\UF19','\U0F19','\UF1A','\U0F1A','\UF1B','\U0F1B','\UF1C','\U0F1C','\UF1D','\U0F1D','\UF1E','\U0F1E','\UF1F','\U0F1F','\UF20','\U0F20','\UF21','\U0F21','\UF22','\U0F22','\UF23','\U0F23','\UF24','\U0F24','\UF25','\U0F25','\UF26','\U0F26','\UF27','\U0F27','\UF28','\U0F28','\UF29','\U0F29','\UF2A','\U0F2A','\UF2B','\U0F2B','\UF2C','\U0F2C','\UF2D','\U0F2D','\UF2E','\U0F2E','\UF2F','\U0F2F','\UF30','\U0F30','\UF31','\U0F31','\UF32','\U0F32','\UF33','\U0F33','\UF34','\U0F34','\UF35','\U0F35','\UF36','\U0F36','\UF37','\U0F37','\UF38','\U0F38','\UF39','\U0F39','\UF3A','\U0F3A','\UF3B','\U0F3B','\UF3C','\U0F3C','\UF3D','\U0F3D','\UF3E','\U0F3E','\UF3F','\U0F3F','\UF40','\U0F40','\UF41','\U0F41','\UF42','\U0F42','\UF43','\U0F43','\UF44','\U0F44','\UF45','\U0F45','\UF46','\U0F46','\UF47','\U0F47','\UF48','\U0F48','\UF49','\U0F49','\UF4A','\U0F4A','\UF4B','\U0F4B','\UF4C','\U0F4C','\UF4D','\U0F4D','\UF4E','\U0F4E','\UF4F','\U0F4F','\UF50','\U0F50','\UF51','\U0F51','\UF52','\U0F52','\UF53','\U0F53','\UF54','\U0F54','\UF55','\U0F55','\UF56','\U0F56','\UF57','\U0F57','\UF58','\U0F58','\UF59','\U0F59','\UF5A','\U0F5A','\UF5B','\U0F5B','\UF5C','\U0F5C','\UF5D','\U0F5D','\UF5E','\U0F5E','\UF5F','\U0F5F','\UF60','\U0F60','\UF61','\U0F61','\UF62','\U0F62','\UF63','\U0F63','\UF64','\U0F64','\UF65','\U0F65','\UF66','\U0F66','\UF67','\U0F67','\UF68','\U0F68','\UF69','\U0F69','\UF6A','\U0F6A','\UF6B','\U0F6B','\UF6C','\U0F6C','\UF6D','\U0F6D','\UF6E','\U0F6E','\UF6F','\U0F6F','\UF70','\U0F70','\UF71','\U0F71','\UF72','\U0F72','\UF73','\U0F73','\UF74','\U0F74','\UF75','\U0F75','\UF76','\U0F76','\UF77','\U0F77','\UF78','\U0F78','\UF79','\U0F79','\UF7A','\U0F7A','\UF7B','\U0F7B','\UF7C','\U0F7C','\UF7D','\U0F7D','\UF7E','\U0F7E','\UF7F','\U0F7F','\UF80','\U0F80','\UF81','\U0F81','\UF82','\U0F82','\UF83','\U0F83','\UF84','\U0F84','\UF85','\U0F85','\UF86','\U0F86','\UF87','\U0F87','\UF88','\U0F88','\UF89','\U0F89','\UF8A','\U0F8A','\UF8B','\U0F8B','\UF8C','\U0F8C','\UF8D','\U0F8D','\UF8E','\U0F8E','\UF8F','\U0F8F','\UF90','\U0F90','\UF91','\U0F91','\UF92','\U0F92','\UF93','\U0F93','\UF94','\U0F94','\UF95','\U0F95','\UF96','\U0F96','\UF97','\U0F97','\UF98','\U0F98','\UF99','\U0F99','\UF9A','\U0F9A','\UF9B','\U0F9B','\UF9C','\U0F9C','\UF9D','\U0F9D','\UF9E','\U0F9E','\UF9F','\U0F9F','\UFA0','\U0FA0','\UFA1','\U0FA1','\UFA2','\U0FA2','\UFA3','\U0FA3','\UFA4','\U0FA4','\UFA5','\U0FA5','\UFA6','\U0FA6','\UFA7','\U0FA7','\UFA8','\U0FA8','\UFA9','\U0FA9','\UFAA','\U0FAA','\UFAB','\U0FAB','\UFAC','\U0FAC','\UFAD','\U0FAD','\UFAE','\U0FAE','\UFAF','\U0FAF','\UFB0','\U0FB0','\UFB1','\U0FB1','\UFB2','\U0FB2','\UFB3','\U0FB3','\UFB4','\U0FB4','\UFB5','\U0FB5','\UFB6','\U0FB6','\UFB7','\U0FB7','\UFB8','\U0FB8','\UFB9','\U0FB9','\UFBA','\U0FBA','\UFBB','\U0FBB','\UFBC','\U0FBC','\UFBD','\U0FBD','\UFBE','\U0FBE','\UFBF','\U0FBF','\UFC0','\U0FC0','\UFC1','\U0FC1','\UFC2','\U0FC2','\UFC3','\U0FC3','\UFC4','\U0FC4','\UFC5','\U0FC5','\UFC6','\U0FC6','\UFC7','\U0FC7','\UFC8','\U0FC8','\UFC9','\U0FC9','\UFCA','\U0FCA','\UFCB','\U0FCB','\UFCC','\U0FCC','\UFCD','\U0FCD','\UFCE','\U0FCE','\UFCF','\U0FCF','\UFD0','\U0FD0','\UFD1','\U0FD1','\UFD2','\U0FD2','\UFD3','\U0FD3','\UFD4','\U0FD4','\UFD5','\U0FD5','\UFD6','\U0FD6','\UFD7','\U0FD7','\UFD8','\U0FD8','\UFD9','\U0FD9','\UFDA','\U0FDA','\UFDB','\U0FDB','\UFDC','\U0FDC','\UFDD','\U0FDD','\UFDE','\U0FDE','\UFDF','\U0FDF','\UFE0','\U0FE0','\UFE1','\U0FE1','\UFE2','\U0FE2','\UFE3','\U0FE3','\UFE4','\U0FE4','\UFE5','\U0FE5','\UFE6','\U0FE6','\UFE7','\U0FE7','\UFE8','\U0FE8','\UFE9','\U0FE9','\UFEA','\U0FEA','\UFEB','\U0FEB','\UFEC','\U0FEC','\UFED','\U0FED','\UFEE','\U0FEE','\UFEF','\U0FEF','\UFF0','\U0FF0','\UFF1','\U0FF1','\UFF2','\U0FF2','\UFF3','\U0FF3','\UFF4','\U0FF4','\UFF5','\U0FF5','\UFF6','\U0FF6','\UFF7','\U0FF7','\UFF8','\U0FF8','\UFF9','\U0FF9','\UFFA','\U0FFA','\UFFB','\U0FFB','\UFFC','\U0FFC','\UFFD','\U0FFD','\UFFE','\U0FFE','\UFFF','\U0FFF','\U1000','\U1001','\U1002','\U1003','\U1004','\U1005','\U1006','\U1007','\U1008','\U1009','\U100A','\U100B','\U100C','\U100D','\U100E','\U100F','\U1010','\U1011','\U1012','\U1013','\U1014','\U1015','\U1016','\U1017','\U1018','\U1019','\U101A','\U101B','\U101C','\U101D','\U101E','\U101F','\U1020','\U1021','\U1022','\U1023','\U1024','\U1025','\U1026','\U1027','\U1028','\U1029','\U102A','\U102B','\U102C','\U102D','\U102E','\U102F','\U1030','\U1031','\U1032','\U1033','\U1034','\U1035','\U1036','\U1037','\U1038','\U1039','\U103A','\U103B','\U103C','\U103D','\U103E','\U103F','\U1040','\U1041','\U1042','\U1043','\U1044','\U1045','\U1046','\U1047','\U1048','\U1049','\U104A','\U104B','\U104C','\U104D','\U104E','\U104F','\U1050','\U1051','\U1052','\U1053','\U1054','\U1055','\U1056','\U1057','\U1058','\U1059','\U105A','\U105B','\U105C','\U105D','\U105E','\U105F','\U1060','\U1061','\U1062','\U1063','\U1064','\U1065','\U1066','\U1067','\U1068','\U1069','\U106A','\U106B','\U106C','\U106D','\U106E','\U106F','\U1070','\U1071','\U1072','\U1073','\U1074','\U1075','\U1076','\U1077','\U1078','\U1079','\U107A','\U107B','\U107C','\U107D','\U107E','\U107F','\U1080','\U1081','\U1082','\U1083','\U1084','\U1085','\U1086','\U1087','\U1088','\U1089','\U108A','\U108B','\U108C','\U108D','\U108E','\U108F','\U1090','\U1091','\U1092','\U1093','\U1094','\U1095','\U1096','\U1097','\U1098','\U1099','\U109A','\U109B','\U109C','\U109D','\U109E','\U109F','\U10A0','\U10A1','\U10A2','\U10A3','\U10A4','\U10A5','\U10A6','\U10A7','\U10A8','\U10A9','\U10AA','\U10AB','\U10AC','\U10AD','\U10AE','\U10AF','\U10B0','\U10B1','\U10B2','\U10B3','\U10B4','\U10B5','\U10B6','\U10B7','\U10B8','\U10B9','\U10BA','\U10BB','\U10BC','\U10BD','\U10BE','\U10BF','\U10C0','\U10C1','\U10C2','\U10C3','\U10C4','\U10C5','\U10C6','\U10C7','\U10C8','\U10C9','\U10CA','\U10CB','\U10CC','\U10CD','\U10CE','\U10CF','\U10D0','\U10D1','\U10D2','\U10D3','\U10D4','\U10D5','\U10D6','\U10D7','\U10D8','\U10D9','\U10DA','\U10DB','\U10DC','\U10DD','\U10DE','\U10DF','\U10E0','\U10E1','\U10E2','\U10E3','\U10E4','\U10E5','\U10E6','\U10E7','\U10E8','\U10E9','\U10EA','\U10EB','\U10EC','\U10ED','\U10EE','\U10EF','\U10F0','\U10F1','\U10F2','\U10F3','\U10F4','\U10F5','\U10F6','\U10F7','\U10F8','\U10F9','\U10FA','\U10FB','\U10FC','\U10FD','\U10FE','\U10FF','\U1100','\U1101','\U1102','\U1103','\U1104','\U1105','\U1106','\U1107','\U1108','\U1109','\U110A','\U110B','\U110C','\U110D','\U110E','\U110F','\U1110','\U1111','\U1112','\U1113','\U1114','\U1115','\U1116','\U1117','\U1118','\U1119','\U111A','\U111B','\U111C','\U111D','\U111E','\U111F','\U1120','\U1121','\U1122','\U1123','\U1124','\U1125','\U1126','\U1127','\U1128','\U1129','\U112A','\U112B','\U112C','\U112D','\U112E','\U112F','\U1130','\U1131','\U1132','\U1133','\U1134','\U1135','\U1136','\U1137','\U1138','\U1139','\U113A','\U113B','\U113C','\U113D','\U113E','\U113F','\U1140','\U1141','\U1142','\U1143','\U1144','\U1145','\U1146','\U1147','\U1148','\U1149','\U114A','\U114B','\U114C','\U114D','\U114E','\U114F','\U1150','\U1151','\U1152','\U1153','\U1154','\U1155','\U1156','\U1157','\U1158','\U1159','\U115A','\U115B','\U115C','\U115D','\U115E','\U115F','\U1160','\U1161','\U1162','\U1163','\U1164','\U1165','\U1166','\U1167','\U1168','\U1169','\U116A','\U116B','\U116C','\U116D','\U116E','\U116F','\U1170','\U1171','\U1172','\U1173','\U1174','\U1175','\U1176','\U1177','\U1178','\U1179','\U117A','\U117B','\U117C','\U117D','\U117E','\U117F','\U1180','\U1181','\U1182','\U1183','\U1184','\U1185','\U1186','\U1187','\U1188','\U1189','\U118A','\U118B','\U118C','\U118D','\U118E','\U118F','\U1190','\U1191','\U1192','\U1193','\U1194','\U1195','\U1196','\U1197','\U1198','\U1199','\U119A','\U119B','\U119C','\U119D','\U119E','\U119F','\U11A0','\U11A1','\U11A2','\U11A3','\U11A4','\U11A5','\U11A6','\U11A7','\U11A8','\U11A9','\U11AA','\U11AB','\U11AC','\U11AD','\U11AE','\U11AF','\U11B0','\U11B1','\U11B2','\U11B3','\U11B4','\U11B5','\U11B6','\U11B7','\U11B8','\U11B9','\U11BA','\U11BB','\U11BC','\U11BD','\U11BE','\U11BF','\U11C0','\U11C1','\U11C2','\U11C3','\U11C4','\U11C5','\U11C6','\U11C7','\U11C8','\U11C9','\U11CA','\U11CB','\U11CC','\U11CD','\U11CE','\U11CF','\U11D0','\U11D1','\U11D2','\U11D3','\U11D4','\U11D5','\U11D6','\U11D7','\U11D8','\U11D9','\U11DA','\U11DB','\U11DC','\U11DD','\U11DE','\U11DF','\U11E0','\U11E1','\U11E2','\U11E3','\U11E4','\U11E5','\U11E6','\U11E7','\U11E8','\U11E9','\U11EA','\U11EB','\U11EC','\U11ED','\U11EE','\U11EF','\U11F0','\U11F1','\U11F2','\U11F3','\U11F4','\U11F5','\U11F6','\U11F7','\U11F8','\U11F9','\U11FA','\U11FB','\U11FC','\U11FD','\U11FE','\U11FF','\U1200','\U1201','\U1202','\U1203','\U1204','\U1205','\U1206','\U1207','\U1208','\U1209','\U120A','\U120B','\U120C','\U120D','\U120E','\U120F','\U1210','\U1211','\U1212','\U1213','\U1214','\U1215','\U1216','\U1217','\U1218','\U1219','\U121A','\U121B','\U121C','\U121D','\U121E','\U121F','\U1220','\U1221','\U1222','\U1223','\U1224','\U1225','\U1226','\U1227','\U1228','\U1229','\U122A','\U122B','\U122C','\U122D','\U122E','\U122F','\U1230','\U1231','\U1232','\U1233','\U1234','\U1235','\U1236','\U1237','\U1238','\U1239','\U123A','\U123B','\U123C','\U123D','\U123E','\U123F','\U1240','\U1241','\U1242','\U1243','\U1244','\U1245','\U1246','\U1247','\U1248','\U1249','\U124A','\U124B','\U124C','\U124D','\U124E','\U124F','\U1250','\U1251','\U1252','\U1253','\U1254','\U1255','\U1256','\U1257','\U1258','\U1259','\U125A','\U125B','\U125C','\U125D','\U125E','\U125F','\U1260','\U1261','\U1262','\U1263','\U1264','\U1265','\U1266','\U1267','\U1268','\U1269','\U126A','\U126B','\U126C','\U126D','\U126E','\U126F','\U1270','\U1271','\U1272','\U1273','\U1274','\U1275','\U1276','\U1277','\U1278','\U1279','\U127A','\U127B','\U127C','\U127D','\U127E','\U127F','\U1280','\U1281','\U1282','\U1283','\U1284','\U1285','\U1286','\U1287','\U1288','\U1289','\U128A','\U128B','\U128C','\U128D','\U128E','\U128F','\U1290','\U1291','\U1292','\U1293','\U1294','\U1295','\U1296','\U1297','\U1298','\U1299','\U129A','\U129B','\U129C','\U129D','\U129E','\U129F','\U12A0','\U12A1','\U12A2','\U12A3','\U12A4','\U12A5','\U12A6','\U12A7','\U12A8','\U12A9','\U12AA','\U12AB','\U12AC','\U12AD','\U12AE','\U12AF','\U12B0','\U12B1','\U12B2','\U12B3','\U12B4','\U12B5','\U12B6','\U12B7','\U12B8','\U12B9','\U12BA','\U12BB','\U12BC','\U12BD','\U12BE','\U12BF','\U12C0','\U12C1','\U12C2','\U12C3','\U12C4','\U12C5','\U12C6','\U12C7','\U12C8','\U12C9','\U12CA','\U12CB','\U12CC','\U12CD','\U12CE','\U12CF','\U12D0','\U12D1','\U12D2','\U12D3','\U12D4','\U12D5','\U12D6','\U12D7','\U12D8','\U12D9','\U12DA','\U12DB','\U12DC','\U12DD','\U12DE','\U12DF','\U12E0','\U12E1','\U12E2','\U12E3','\U12E4','\U12E5','\U12E6','\U12E7','\U12E8','\U12E9','\U12EA','\U12EB','\U12EC','\U12ED','\U12EE','\U12EF','\U12F0','\U12F1','\U12F2','\U12F3','\U12F4','\U12F5','\U12F6','\U12F7','\U12F8','\U12F9','\U12FA','\U12FB','\U12FC','\U12FD','\U12FE','\U12FF','\U1300','\U1301','\U1302','\U1303','\U1304','\U1305','\U1306','\U1307','\U1308','\U1309','\U130A','\U130B','\U130C','\U130D','\U130E','\U130F','\U1310','\U1311','\U1312','\U1313','\U1314','\U1315','\U1316','\U1317','\U1318','\U1319','\U131A','\U131B','\U131C','\U131D','\U131E','\U131F','\U1320','\U1321','\U1322','\U1323','\U1324','\U1325','\U1326','\U1327','\U1328','\U1329','\U132A','\U132B','\U132C','\U132D','\U132E','\U132F','\U1330','\U1331','\U1332','\U1333','\U1334','\U1335','\U1336','\U1337','\U1338','\U1339','\U133A','\U133B','\U133C','\U133D','\U133E','\U133F','\U1340','\U1341','\U1342','\U1343','\U1344','\U1345','\U1346','\U1347','\U1348','\U1349','\U134A','\U134B','\U134C','\U134D','\U134E','\U134F','\U1350','\U1351','\U1352','\U1353','\U1354','\U1355','\U1356','\U1357','\U1358','\U1359','\U135A','\U135B','\U135C','\U135D','\U135E','\U135F','\U1360','\U1361','\U1362','\U1363','\U1364','\U1365','\U1366','\U1367','\U1368','\U1369','\U136A','\U136B','\U136C','\U136D','\U136E','\U136F','\U1370','\U1371','\U1372','\U1373','\U1374','\U1375','\U1376','\U1377','\U1378','\U1379','\U137A','\U137B','\U137C','\U137D','\U137E','\U137F','\U1380','\U1381','\U1382','\U1383','\U1384','\U1385','\U1386','\U1387','\U1388','\U1389','\U138A','\U138B','\U138C','\U138D','\U138E','\U138F','\U1390','\U1391','\U1392','\U1393','\U1394','\U1395','\U1396','\U1397','\U1398','\U1399','\U139A','\U139B','\U139C','\U139D','\U139E','\U139F','\U13A0','\U13A1','\U13A2','\U13A3','\U13A4','\U13A5','\U13A6','\U13A7','\U13A8','\U13A9','\U13AA','\U13AB','\U13AC','\U13AD','\U13AE','\U13AF','\U13B0','\U13B1','\U13B2','\U13B3','\U13B4','\U13B5','\U13B6','\U13B7','\U13B8','\U13B9','\U13BA','\U13BB','\U13BC','\U13BD','\U13BE','\U13BF','\U13C0','\U13C1','\U13C2','\U13C3','\U13C4','\U13C5','\U13C6','\U13C7','\U13C8','\U13C9','\U13CA','\U13CB','\U13CC','\U13CD','\U13CE','\U13CF','\U13D0','\U13D1','\U13D2','\U13D3','\U13D4','\U13D5','\U13D6','\U13D7','\U13D8','\U13D9','\U13DA','\U13DB','\U13DC','\U13DD','\U13DE','\U13DF','\U13E0','\U13E1','\U13E2','\U13E3','\U13E4','\U13E5','\U13E6','\U13E7','\U13E8','\U13E9','\U13EA','\U13EB','\U13EC','\U13ED','\U13EE','\U13EF','\U13F0','\U13F1','\U13F2','\U13F3','\U13F4','\U13F5','\U13F6','\U13F7','\U13F8','\U13F9','\U13FA','\U13FB','\U13FC','\U13FD','\U13FE','\U13FF','\U1400','\U1401','\U1402','\U1403','\U1404','\U1405','\U1406','\U1407','\U1408','\U1409','\U140A','\U140B','\U140C','\U140D','\U140E','\U140F','\U1410','\U1411','\U1412','\U1413','\U1414','\U1415','\U1416','\U1417','\U1418','\U1419','\U141A','\U141B','\U141C','\U141D','\U141E','\U141F','\U1420','\U1421','\U1422','\U1423','\U1424','\U1425','\U1426','\U1427','\U1428','\U1429','\U142A','\U142B','\U142C','\U142D','\U142E','\U142F','\U1430','\U1431','\U1432','\U1433','\U1434','\U1435','\U1436','\U1437','\U1438','\U1439','\U143A','\U143B','\U143C','\U143D','\U143E','\U143F','\U1440','\U1441','\U1442','\U1443','\U1444','\U1445','\U1446','\U1447','\U1448','\U1449','\U144A','\U144B','\U144C','\U144D','\U144E','\U144F','\U1450','\U1451','\U1452','\U1453','\U1454','\U1455','\U1456','\U1457','\U1458','\U1459','\U145A','\U145B','\U145C','\U145D','\U145E','\U145F','\U1460','\U1461','\U1462','\U1463','\U1464','\U1465','\U1466','\U1467','\U1468','\U1469','\U146A','\U146B','\U146C','\U146D','\U146E','\U146F','\U1470','\U1471','\U1472','\U1473','\U1474','\U1475','\U1476','\U1477','\U1478','\U1479','\U147A','\U147B','\U147C','\U147D','\U147E','\U147F','\U1480','\U1481','\U1482','\U1483','\U1484','\U1485','\U1486','\U1487','\U1488','\U1489','\U148A','\U148B','\U148C','\U148D','\U148E','\U148F','\U1490','\U1491','\U1492','\U1493','\U1494','\U1495','\U1496','\U1497','\U1498','\U1499','\U149A','\U149B','\U149C','\U149D','\U149E','\U149F','\U14A0','\U14A1','\U14A2','\U14A3','\U14A4','\U14A5','\U14A6','\U14A7','\U14A8','\U14A9','\U14AA','\U14AB','\U14AC','\U14AD','\U14AE','\U14AF','\U14B0','\U14B1','\U14B2','\U14B3','\U14B4','\U14B5','\U14B6','\U14B7','\U14B8','\U14B9','\U14BA','\U14BB','\U14BC','\U14BD','\U14BE','\U14BF','\U14C0','\U14C1','\U14C2','\U14C3','\U14C4','\U14C5','\U14C6','\U14C7','\U14C8','\U14C9','\U14CA','\U14CB','\U14CC','\U14CD','\U14CE','\U14CF','\U14D0','\U14D1','\U14D2','\U14D3','\U14D4','\U14D5','\U14D6','\U14D7','\U14D8','\U14D9','\U14DA','\U14DB','\U14DC','\U14DD','\U14DE','\U14DF','\U14E0','\U14E1','\U14E2','\U14E3','\U14E4','\U14E5','\U14E6','\U14E7','\U14E8','\U14E9','\U14EA','\U14EB','\U14EC','\U14ED','\U14EE','\U14EF','\U14F0','\U14F1','\U14F2','\U14F3','\U14F4','\U14F5','\U14F6','\U14F7','\U14F8','\U14F9','\U14FA','\U14FB','\U14FC','\U14FD','\U14FE','\U14FF','\U1500','\U1501','\U1502','\U1503','\U1504','\U1505','\U1506','\U1507','\U1508','\U1509','\U150A','\U150B','\U150C','\U150D','\U150E','\U150F','\U1510','\U1511','\U1512','\U1513','\U1514','\U1515','\U1516','\U1517','\U1518','\U1519','\U151A','\U151B','\U151C','\U151D','\U151E','\U151F','\U1520','\U1521','\U1522','\U1523','\U1524','\U1525','\U1526','\U1527','\U1528','\U1529','\U152A','\U152B','\U152C','\U152D','\U152E','\U152F','\U1530','\U1531','\U1532','\U1533','\U1534','\U1535','\U1536','\U1537','\U1538','\U1539','\U153A','\U153B','\U153C','\U153D','\U153E','\U153F','\U1540','\U1541','\U1542','\U1543','\U1544','\U1545','\U1546','\U1547','\U1548','\U1549','\U154A','\U154B','\U154C','\U154D','\U154E','\U154F','\U1550','\U1551','\U1552','\U1553','\U1554','\U1555','\U1556','\U1557','\U1558','\U1559','\U155A','\U155B','\U155C','\U155D','\U155E','\U155F','\U1560','\U1561','\U1562','\U1563','\U1564','\U1565','\U1566','\U1567','\U1568','\U1569','\U156A','\U156B','\U156C','\U156D','\U156E','\U156F','\U1570','\U1571','\U1572','\U1573','\U1574','\U1575','\U1576','\U1577','\U1578','\U1579','\U157A','\U157B','\U157C','\U157D','\U157E','\U157F','\U1580','\U1581','\U1582','\U1583','\U1584','\U1585','\U1586','\U1587','\U1588','\U1589','\U158A','\U158B','\U158C','\U158D','\U158E','\U158F','\U1590','\U1591','\U1592','\U1593','\U1594','\U1595','\U1596','\U1597','\U1598','\U1599','\U159A','\U159B','\U159C','\U159D','\U159E','\U159F','\U15A0','\U15A1','\U15A2','\U15A3','\U15A4','\U15A5','\U15A6','\U15A7','\U15A8','\U15A9','\U15AA','\U15AB','\U15AC','\U15AD','\U15AE','\U15AF','\U15B0','\U15B1','\U15B2','\U15B3','\U15B4','\U15B5','\U15B6','\U15B7','\U15B8','\U15B9','\U15BA','\U15BB','\U15BC','\U15BD','\U15BE','\U15BF','\U15C0','\U15C1','\U15C2','\U15C3','\U15C4','\U15C5','\U15C6','\U15C7','\U15C8','\U15C9','\U15CA','\U15CB','\U15CC','\U15CD','\U15CE','\U15CF','\U15D0','\U15D1','\U15D2','\U15D3','\U15D4','\U15D5','\U15D6','\U15D7','\U15D8','\U15D9','\U15DA','\U15DB','\U15DC','\U15DD','\U15DE','\U15DF','\U15E0','\U15E1','\U15E2','\U15E3','\U15E4','\U15E5','\U15E6','\U15E7','\U15E8','\U15E9','\U15EA','\U15EB','\U15EC','\U15ED','\U15EE','\U15EF','\U15F0','\U15F1','\U15F2','\U15F3','\U15F4','\U15F5','\U15F6','\U15F7','\U15F8','\U15F9','\U15FA','\U15FB','\U15FC','\U15FD','\U15FE','\U15FF','\U1600','\U1601','\U1602','\U1603','\U1604','\U1605','\U1606','\U1607','\U1608','\U1609','\U160A','\U160B','\U160C','\U160D','\U160E','\U160F','\U1610','\U1611','\U1612','\U1613','\U1614','\U1615','\U1616','\U1617','\U1618','\U1619','\U161A','\U161B','\U161C','\U161D','\U161E','\U161F','\U1620','\U1621','\U1622','\U1623','\U1624','\U1625','\U1626','\U1627','\U1628','\U1629','\U162A','\U162B','\U162C','\U162D','\U162E','\U162F','\U1630','\U1631','\U1632','\U1633','\U1634','\U1635','\U1636','\U1637','\U1638','\U1639','\U163A','\U163B','\U163C','\U163D','\U163E','\U163F','\U1640','\U1641','\U1642','\U1643','\U1644','\U1645','\U1646','\U1647','\U1648','\U1649','\U164A','\U164B','\U164C','\U164D','\U164E','\U164F','\U1650','\U1651','\U1652','\U1653','\U1654','\U1655','\U1656','\U1657','\U1658','\U1659','\U165A','\U165B','\U165C','\U165D','\U165E','\U165F','\U1660','\U1661','\U1662','\U1663','\U1664','\U1665','\U1666','\U1667','\U1668','\U1669','\U166A','\U166B','\U166C','\U166D','\U166E','\U166F','\U1670','\U1671','\U1672','\U1673','\U1674','\U1675','\U1676','\U1677','\U1678','\U1679','\U167A','\U167B','\U167C','\U167D','\U167E','\U167F','\U1680','\U1681','\U1682','\U1683','\U1684','\U1685','\U1686','\U1687','\U1688','\U1689','\U168A','\U168B','\U168C','\U168D','\U168E','\U168F','\U1690','\U1691','\U1692','\U1693','\U1694','\U1695','\U1696','\U1697','\U1698','\U1699','\U169A','\U169B','\U169C','\U169D','\U169E','\U169F','\U16A0','\U16A1','\U16A2','\U16A3','\U16A4','\U16A5','\U16A6','\U16A7','\U16A8','\U16A9','\U16AA','\U16AB','\U16AC','\U16AD','\U16AE','\U16AF','\U16B0','\U16B1','\U16B2','\U16B3','\U16B4','\U16B5','\U16B6','\U16B7','\U16B8','\U16B9','\U16BA','\U16BB','\U16BC','\U16BD','\U16BE','\U16BF','\U16C0','\U16C1','\U16C2','\U16C3','\U16C4','\U16C5','\U16C6','\U16C7','\U16C8','\U16C9','\U16CA','\U16CB','\U16CC','\U16CD','\U16CE','\U16CF','\U16D0','\U16D1','\U16D2','\U16D3','\U16D4','\U16D5','\U16D6','\U16D7','\U16D8','\U16D9','\U16DA','\U16DB','\U16DC','\U16DD','\U16DE','\U16DF','\U16E0','\U16E1','\U16E2','\U16E3','\U16E4','\U16E5','\U16E6','\U16E7','\U16E8','\U16E9','\U16EA','\U16EB','\U16EC','\U16ED','\U16EE','\U16EF','\U16F0','\U16F1','\U16F2','\U16F3','\U16F4','\U16F5','\U16F6','\U16F7','\U16F8','\U16F9','\U16FA','\U16FB','\U16FC','\U16FD','\U16FE','\U16FF','\U1700','\U1701','\U1702','\U1703','\U1704','\U1705','\U1706','\U1707','\U1708','\U1709','\U170A','\U170B','\U170C','\U170D','\U170E','\U170F','\U1710','\U1711','\U1712','\U1713','\U1714','\U1715','\U1716','\U1717','\U1718','\U1719','\U171A','\U171B','\U171C','\U171D','\U171E','\U171F','\U1720','\U1721','\U1722','\U1723','\U1724','\U1725','\U1726','\U1727','\U1728','\U1729','\U172A','\U172B','\U172C','\U172D','\U172E','\U172F','\U1730','\U1731','\U1732','\U1733','\U1734','\U1735','\U1736','\U1737','\U1738','\U1739','\U173A','\U173B','\U173C','\U173D','\U173E','\U173F','\U1740','\U1741','\U1742','\U1743','\U1744','\U1745','\U1746','\U1747','\U1748','\U1749','\U174A','\U174B','\U174C','\U174D','\U174E','\U174F','\U1750','\U1751','\U1752','\U1753','\U1754','\U1755','\U1756','\U1757','\U1758','\U1759','\U175A','\U175B','\U175C','\U175D','\U175E','\U175F','\U1760','\U1761','\U1762','\U1763','\U1764','\U1765','\U1766','\U1767','\U1768','\U1769','\U176A','\U176B','\U176C','\U176D','\U176E','\U176F','\U1770','\U1771','\U1772','\U1773','\U1774','\U1775','\U1776','\U1777','\U1778','\U1779','\U177A','\U177B','\U177C','\U177D','\U177E','\U177F','\U1780','\U1781','\U1782','\U1783','\U1784','\U1785','\U1786','\U1787','\U1788','\U1789','\U178A','\U178B','\U178C','\U178D','\U178E','\U178F','\U1790','\U1791','\U1792','\U1793','\U1794','\U1795','\U1796','\U1797','\U1798','\U1799','\U179A','\U179B','\U179C','\U179D','\U179E','\U179F','\U17A0','\U17A1','\U17A2','\U17A3','\U17A4','\U17A5','\U17A6','\U17A7','\U17A8','\U17A9','\U17AA','\U17AB','\U17AC','\U17AD','\U17AE','\U17AF','\U17B0','\U17B1','\U17B2','\U17B3','\U17B4','\U17B5','\U17B6','\U17B7','\U17B8','\U17B9','\U17BA','\U17BB','\U17BC','\U17BD','\U17BE','\U17BF','\U17C0','\U17C1','\U17C2','\U17C3','\U17C4','\U17C5','\U17C6','\U17C7','\U17C8','\U17C9','\U17CA','\U17CB','\U17CC','\U17CD','\U17CE','\U17CF','\U17D0','\U17D1','\U17D2','\U17D3','\U17D4','\U17D5','\U17D6','\U17D7','\U17D8','\U17D9','\U17DA','\U17DB','\U17DC','\U17DD','\U17DE','\U17DF','\U17E0','\U17E1','\U17E2','\U17E3','\U17E4','\U17E5','\U17E6','\U17E7','\U17E8','\U17E9','\U17EA','\U17EB','\U17EC','\U17ED','\U17EE','\U17EF','\U17F0','\U17F1','\U17F2','\U17F3','\U17F4','\U17F5','\U17F6','\U17F7','\U17F8','\U17F9','\U17FA','\U17FB','\U17FC','\U17FD','\U17FE','\U17FF','\U1800','\U1801','\U1802','\U1803','\U1804','\U1805','\U1806','\U1807','\U1808','\U1809','\U180A','\U180B','\U180C','\U180D','\U180E','\U180F','\U1810','\U1811','\U1812','\U1813','\U1814','\U1815','\U1816','\U1817','\U1818','\U1819','\U181A','\U181B','\U181C','\U181D','\U181E','\U181F','\U1820','\U1821','\U1822','\U1823','\U1824','\U1825','\U1826','\U1827','\U1828','\U1829','\U182A','\U182B','\U182C','\U182D','\U182E','\U182F','\U1830','\U1831','\U1832','\U1833','\U1834','\U1835','\U1836','\U1837','\U1838','\U1839','\U183A','\U183B','\U183C','\U183D','\U183E','\U183F','\U1840','\U1841','\U1842','\U1843','\U1844','\U1845','\U1846','\U1847','\U1848','\U1849','\U184A','\U184B','\U184C','\U184D','\U184E','\U184F','\U1850','\U1851','\U1852','\U1853','\U1854','\U1855','\U1856','\U1857','\U1858','\U1859','\U185A','\U185B','\U185C','\U185D','\U185E','\U185F','\U1860','\U1861','\U1862','\U1863','\U1864','\U1865','\U1866','\U1867','\U1868','\U1869','\U186A','\U186B','\U186C','\U186D','\U186E','\U186F','\U1870','\U1871','\U1872','\U1873','\U1874','\U1875','\U1876','\U1877','\U1878','\U1879','\U187A','\U187B','\U187C','\U187D','\U187E','\U187F','\U1880','\U1881','\U1882','\U1883','\U1884','\U1885','\U1886','\U1887','\U1888','\U1889','\U188A','\U188B','\U188C','\U188D','\U188E','\U188F','\U1890','\U1891','\U1892','\U1893','\U1894','\U1895','\U1896','\U1897','\U1898','\U1899','\U189A','\U189B','\U189C','\U189D','\U189E','\U189F','\U18A0','\U18A1','\U18A2','\U18A3','\U18A4','\U18A5','\U18A6','\U18A7','\U18A8','\U18A9','\U18AA','\U18AB','\U18AC','\U18AD','\U18AE','\U18AF','\U18B0','\U18B1','\U18B2','\U18B3','\U18B4','\U18B5','\U18B6','\U18B7','\U18B8','\U18B9','\U18BA','\U18BB','\U18BC','\U18BD','\U18BE','\U18BF','\U18C0','\U18C1','\U18C2','\U18C3','\U18C4','\U18C5','\U18C6','\U18C7','\U18C8','\U18C9','\U18CA','\U18CB','\U18CC','\U18CD','\U18CE','\U18CF','\U18D0','\U18D1','\U18D2','\U18D3','\U18D4','\U18D5','\U18D6','\U18D7','\U18D8','\U18D9','\U18DA','\U18DB','\U18DC','\U18DD','\U18DE','\U18DF','\U18E0','\U18E1','\U18E2','\U18E3','\U18E4','\U18E5','\U18E6','\U18E7','\U18E8','\U18E9','\U18EA','\U18EB','\U18EC','\U18ED','\U18EE','\U18EF','\U18F0','\U18F1','\U18F2','\U18F3','\U18F4','\U18F5','\U18F6','\U18F7','\U18F8','\U18F9','\U18FA','\U18FB','\U18FC','\U18FD','\U18FE','\U18FF','\U1900','\U1901','\U1902','\U1903','\U1904','\U1905','\U1906','\U1907','\U1908','\U1909','\U190A','\U190B','\U190C','\U190D','\U190E','\U190F','\U1910','\U1911','\U1912','\U1913','\U1914','\U1915','\U1916','\U1917','\U1918','\U1919','\U191A','\U191B','\U191C','\U191D','\U191E','\U191F','\U1920','\U1921','\U1922','\U1923','\U1924','\U1925','\U1926','\U1927','\U1928','\U1929','\U192A','\U192B','\U192C','\U192D','\U192E','\U192F','\U1930','\U1931','\U1932','\U1933','\U1934','\U1935','\U1936','\U1937','\U1938','\U1939','\U193A','\U193B','\U193C','\U193D','\U193E','\U193F','\U1940','\U1941','\U1942','\U1943','\U1944','\U1945','\U1946','\U1947','\U1948','\U1949','\U194A','\U194B','\U194C','\U194D','\U194E','\U194F','\U1950','\U1951','\U1952','\U1953','\U1954','\U1955','\U1956','\U1957','\U1958','\U1959','\U195A','\U195B','\U195C','\U195D','\U195E','\U195F','\U1960','\U1961','\U1962','\U1963','\U1964','\U1965','\U1966','\U1967','\U1968','\U1969','\U196A','\U196B','\U196C','\U196D','\U196E','\U196F','\U1970','\U1971','\U1972','\U1973','\U1974','\U1975','\U1976','\U1977','\U1978','\U1979','\U197A','\U197B','\U197C','\U197D','\U197E','\U197F','\U1980','\U1981','\U1982','\U1983','\U1984','\U1985','\U1986','\U1987','\U1988','\U1989','\U198A','\U198B','\U198C','\U198D','\U198E','\U198F','\U1990','\U1991','\U1992','\U1993','\U1994','\U1995','\U1996','\U1997','\U1998','\U1999','\U199A','\U199B','\U199C','\U199D','\U199E','\U199F','\U19A0','\U19A1','\U19A2','\U19A3','\U19A4','\U19A5','\U19A6','\U19A7','\U19A8','\U19A9','\U19AA','\U19AB','\U19AC','\U19AD','\U19AE','\U19AF','\U19B0','\U19B1','\U19B2','\U19B3','\U19B4','\U19B5','\U19B6','\U19B7','\U19B8','\U19B9','\U19BA','\U19BB','\U19BC','\U19BD','\U19BE','\U19BF','\U19C0','\U19C1','\U19C2','\U19C3','\U19C4','\U19C5','\U19C6','\U19C7','\U19C8','\U19C9','\U19CA','\U19CB','\U19CC','\U19CD','\U19CE','\U19CF','\U19D0','\U19D1','\U19D2','\U19D3','\U19D4','\U19D5','\U19D6','\U19D7','\U19D8','\U19D9','\U19DA','\U19DB','\U19DC','\U19DD','\U19DE','\U19DF','\U19E0','\U19E1','\U19E2','\U19E3','\U19E4','\U19E5','\U19E6','\U19E7','\U19E8','\U19E9','\U19EA','\U19EB','\U19EC','\U19ED','\U19EE','\U19EF','\U19F0','\U19F1','\U19F2','\U19F3','\U19F4','\U19F5','\U19F6','\U19F7','\U19F8','\U19F9','\U19FA','\U19FB','\U19FC','\U19FD','\U19FE','\U19FF','\U1A00','\U1A01','\U1A02','\U1A03','\U1A04','\U1A05','\U1A06','\U1A07','\U1A08','\U1A09','\U1A0A','\U1A0B','\U1A0C','\U1A0D','\U1A0E','\U1A0F','\U1A10','\U1A11','\U1A12','\U1A13','\U1A14','\U1A15','\U1A16','\U1A17','\U1A18','\U1A19','\U1A1A','\U1A1B','\U1A1C','\U1A1D','\U1A1E','\U1A1F','\U1A20','\U1A21','\U1A22','\U1A23','\U1A24','\U1A25','\U1A26','\U1A27','\U1A28','\U1A29','\U1A2A','\U1A2B','\U1A2C','\U1A2D','\U1A2E','\U1A2F','\U1A30','\U1A31','\U1A32','\U1A33','\U1A34','\U1A35','\U1A36','\U1A37','\U1A38','\U1A39','\U1A3A','\U1A3B','\U1A3C','\U1A3D','\U1A3E','\U1A3F','\U1A40','\U1A41','\U1A42','\U1A43','\U1A44','\U1A45','\U1A46','\U1A47','\U1A48','\U1A49','\U1A4A','\U1A4B','\U1A4C','\U1A4D','\U1A4E','\U1A4F','\U1A50','\U1A51','\U1A52','\U1A53','\U1A54','\U1A55','\U1A56','\U1A57','\U1A58','\U1A59','\U1A5A','\U1A5B','\U1A5C','\U1A5D','\U1A5E','\U1A5F','\U1A60','\U1A61','\U1A62','\U1A63','\U1A64','\U1A65','\U1A66','\U1A67','\U1A68','\U1A69','\U1A6A','\U1A6B','\U1A6C','\U1A6D','\U1A6E','\U1A6F','\U1A70','\U1A71','\U1A72','\U1A73','\U1A74','\U1A75','\U1A76','\U1A77','\U1A78','\U1A79','\U1A7A','\U1A7B','\U1A7C','\U1A7D','\U1A7E','\U1A7F','\U1A80','\U1A81','\U1A82','\U1A83','\U1A84','\U1A85','\U1A86','\U1A87','\U1A88','\U1A89','\U1A8A','\U1A8B','\U1A8C','\U1A8D','\U1A8E','\U1A8F','\U1A90','\U1A91','\U1A92','\U1A93','\U1A94','\U1A95','\U1A96','\U1A97','\U1A98','\U1A99','\U1A9A','\U1A9B','\U1A9C','\U1A9D','\U1A9E','\U1A9F','\U1AA0','\U1AA1','\U1AA2','\U1AA3','\U1AA4','\U1AA5','\U1AA6','\U1AA7','\U1AA8','\U1AA9','\U1AAA','\U1AAB','\U1AAC','\U1AAD','\U1AAE','\U1AAF','\U1AB0','\U1AB1','\U1AB2','\U1AB3','\U1AB4','\U1AB5','\U1AB6','\U1AB7','\U1AB8','\U1AB9','\U1ABA','\U1ABB','\U1ABC','\U1ABD','\U1ABE','\U1ABF','\U1AC0','\U1AC1','\U1AC2','\U1AC3','\U1AC4','\U1AC5','\U1AC6','\U1AC7','\U1AC8','\U1AC9','\U1ACA','\U1ACB','\U1ACC','\U1ACD','\U1ACE','\U1ACF','\U1AD0','\U1AD1','\U1AD2','\U1AD3','\U1AD4','\U1AD5','\U1AD6','\U1AD7','\U1AD8','\U1AD9','\U1ADA','\U1ADB','\U1ADC','\U1ADD','\U1ADE','\U1ADF','\U1AE0','\U1AE1','\U1AE2','\U1AE3','\U1AE4','\U1AE5','\U1AE6','\U1AE7','\U1AE8','\U1AE9','\U1AEA','\U1AEB','\U1AEC','\U1AED','\U1AEE','\U1AEF','\U1AF0','\U1AF1','\U1AF2','\U1AF3','\U1AF4','\U1AF5','\U1AF6','\U1AF7','\U1AF8','\U1AF9','\U1AFA','\U1AFB','\U1AFC','\U1AFD','\U1AFE','\U1AFF','\U1B00','\U1B01','\U1B02','\U1B03','\U1B04','\U1B05','\U1B06','\U1B07','\U1B08','\U1B09','\U1B0A','\U1B0B','\U1B0C','\U1B0D','\U1B0E','\U1B0F','\U1B10','\U1B11','\U1B12','\U1B13','\U1B14','\U1B15','\U1B16','\U1B17','\U1B18','\U1B19','\U1B1A','\U1B1B','\U1B1C','\U1B1D','\U1B1E','\U1B1F','\U1B20','\U1B21','\U1B22','\U1B23','\U1B24','\U1B25','\U1B26','\U1B27','\U1B28','\U1B29','\U1B2A','\U1B2B','\U1B2C','\U1B2D','\U1B2E','\U1B2F','\U1B30','\U1B31','\U1B32','\U1B33','\U1B34','\U1B35','\U1B36','\U1B37','\U1B38','\U1B39','\U1B3A','\U1B3B','\U1B3C','\U1B3D','\U1B3E','\U1B3F','\U1B40','\U1B41','\U1B42','\U1B43','\U1B44','\U1B45','\U1B46','\U1B47','\U1B48','\U1B49','\U1B4A','\U1B4B','\U1B4C','\U1B4D','\U1B4E','\U1B4F','\U1B50','\U1B51','\U1B52','\U1B53','\U1B54','\U1B55','\U1B56','\U1B57','\U1B58','\U1B59','\U1B5A','\U1B5B','\U1B5C','\U1B5D','\U1B5E','\U1B5F','\U1B60','\U1B61','\U1B62','\U1B63','\U1B64','\U1B65','\U1B66','\U1B67','\U1B68','\U1B69','\U1B6A','\U1B6B','\U1B6C','\U1B6D','\U1B6E','\U1B6F','\U1B70','\U1B71','\U1B72','\U1B73','\U1B74','\U1B75','\U1B76','\U1B77','\U1B78','\U1B79','\U1B7A','\U1B7B','\U1B7C','\U1B7D','\U1B7E','\U1B7F','\U1B80','\U1B81','\U1B82','\U1B83','\U1B84','\U1B85','\U1B86','\U1B87','\U1B88','\U1B89','\U1B8A','\U1B8B','\U1B8C','\U1B8D','\U1B8E','\U1B8F','\U1B90','\U1B91','\U1B92','\U1B93','\U1B94','\U1B95','\U1B96','\U1B97','\U1B98','\U1B99','\U1B9A','\U1B9B','\U1B9C','\U1B9D','\U1B9E','\U1B9F','\U1BA0','\U1BA1','\U1BA2','\U1BA3','\U1BA4','\U1BA5','\U1BA6','\U1BA7','\U1BA8','\U1BA9','\U1BAA','\U1BAB','\U1BAC','\U1BAD','\U1BAE','\U1BAF','\U1BB0','\U1BB1','\U1BB2','\U1BB3','\U1BB4','\U1BB5','\U1BB6','\U1BB7','\U1BB8','\U1BB9','\U1BBA','\U1BBB','\U1BBC','\U1BBD','\U1BBE','\U1BBF','\U1BC0','\U1BC1','\U1BC2','\U1BC3','\U1BC4','\U1BC5','\U1BC6','\U1BC7','\U1BC8','\U1BC9','\U1BCA','\U1BCB','\U1BCC','\U1BCD','\U1BCE','\U1BCF','\U1BD0','\U1BD1','\U1BD2','\U1BD3','\U1BD4','\U1BD5','\U1BD6','\U1BD7','\U1BD8','\U1BD9','\U1BDA','\U1BDB','\U1BDC','\U1BDD','\U1BDE','\U1BDF','\U1BE0','\U1BE1','\U1BE2','\U1BE3','\U1BE4','\U1BE5','\U1BE6','\U1BE7','\U1BE8','\U1BE9','\U1BEA','\U1BEB','\U1BEC','\U1BED','\U1BEE','\U1BEF','\U1BF0','\U1BF1','\U1BF2','\U1BF3','\U1BF4','\U1BF5','\U1BF6','\U1BF7','\U1BF8','\U1BF9','\U1BFA','\U1BFB','\U1BFC','\U1BFD','\U1BFE','\U1BFF','\U1C00','\U1C01','\U1C02','\U1C03','\U1C04','\U1C05','\U1C06','\U1C07','\U1C08','\U1C09','\U1C0A','\U1C0B','\U1C0C','\U1C0D','\U1C0E','\U1C0F','\U1C10','\U1C11','\U1C12','\U1C13','\U1C14','\U1C15','\U1C16','\U1C17','\U1C18','\U1C19','\U1C1A','\U1C1B','\U1C1C','\U1C1D','\U1C1E','\U1C1F','\U1C20','\U1C21','\U1C22','\U1C23','\U1C24','\U1C25','\U1C26','\U1C27','\U1C28','\U1C29','\U1C2A','\U1C2B','\U1C2C','\U1C2D','\U1C2E','\U1C2F','\U1C30','\U1C31','\U1C32','\U1C33','\U1C34','\U1C35','\U1C36','\U1C37','\U1C38','\U1C39','\U1C3A','\U1C3B','\U1C3C','\U1C3D','\U1C3E','\U1C3F','\U1C40','\U1C41','\U1C42','\U1C43','\U1C44','\U1C45','\U1C46','\U1C47','\U1C48','\U1C49','\U1C4A','\U1C4B','\U1C4C','\U1C4D','\U1C4E','\U1C4F','\U1C50','\U1C51','\U1C52','\U1C53','\U1C54','\U1C55','\U1C56','\U1C57','\U1C58','\U1C59','\U1C5A','\U1C5B','\U1C5C','\U1C5D','\U1C5E','\U1C5F','\U1C60','\U1C61','\U1C62','\U1C63','\U1C64','\U1C65','\U1C66','\U1C67','\U1C68','\U1C69','\U1C6A','\U1C6B','\U1C6C','\U1C6D','\U1C6E','\U1C6F','\U1C70','\U1C71','\U1C72','\U1C73','\U1C74','\U1C75','\U1C76','\U1C77','\U1C78','\U1C79','\U1C7A','\U1C7B','\U1C7C','\U1C7D','\U1C7E','\U1C7F','\U1C80','\U1C81','\U1C82','\U1C83','\U1C84','\U1C85','\U1C86','\U1C87','\U1C88','\U1C89','\U1C8A','\U1C8B','\U1C8C','\U1C8D','\U1C8E','\U1C8F','\U1C90','\U1C91','\U1C92','\U1C93','\U1C94','\U1C95','\U1C96','\U1C97','\U1C98','\U1C99','\U1C9A','\U1C9B','\U1C9C','\U1C9D','\U1C9E','\U1C9F','\U1CA0','\U1CA1','\U1CA2','\U1CA3','\U1CA4','\U1CA5','\U1CA6','\U1CA7','\U1CA8','\U1CA9','\U1CAA','\U1CAB','\U1CAC','\U1CAD','\U1CAE','\U1CAF','\U1CB0','\U1CB1','\U1CB2','\U1CB3','\U1CB4','\U1CB5','\U1CB6','\U1CB7','\U1CB8','\U1CB9','\U1CBA','\U1CBB','\U1CBC','\U1CBD','\U1CBE','\U1CBF','\U1CC0','\U1CC1','\U1CC2','\U1CC3','\U1CC4','\U1CC5','\U1CC6','\U1CC7','\U1CC8','\U1CC9','\U1CCA','\U1CCB','\U1CCC','\U1CCD','\U1CCE','\U1CCF','\U1CD0','\U1CD1','\U1CD2','\U1CD3','\U1CD4','\U1CD5','\U1CD6','\U1CD7','\U1CD8','\U1CD9','\U1CDA','\U1CDB','\U1CDC','\U1CDD','\U1CDE','\U1CDF','\U1CE0','\U1CE1','\U1CE2','\U1CE3','\U1CE4','\U1CE5','\U1CE6','\U1CE7','\U1CE8','\U1CE9','\U1CEA','\U1CEB','\U1CEC','\U1CED','\U1CEE','\U1CEF','\U1CF0','\U1CF1','\U1CF2','\U1CF3','\U1CF4','\U1CF5','\U1CF6','\U1CF7','\U1CF8','\U1CF9','\U1CFA','\U1CFB','\U1CFC','\U1CFD','\U1CFE','\U1CFF','\U1D00','\U1D01','\U1D02','\U1D03','\U1D04','\U1D05','\U1D06','\U1D07','\U1D08','\U1D09','\U1D0A','\U1D0B','\U1D0C','\U1D0D','\U1D0E','\U1D0F','\U1D10','\U1D11','\U1D12','\U1D13','\U1D14','\U1D15','\U1D16','\U1D17','\U1D18','\U1D19','\U1D1A','\U1D1B','\U1D1C','\U1D1D','\U1D1E','\U1D1F','\U1D20','\U1D21','\U1D22','\U1D23','\U1D24','\U1D25','\U1D26','\U1D27','\U1D28','\U1D29','\U1D2A','\U1D2B','\U1D2C','\U1D2D','\U1D2E','\U1D2F','\U1D30','\U1D31','\U1D32','\U1D33','\U1D34','\U1D35','\U1D36','\U1D37','\U1D38','\U1D39','\U1D3A','\U1D3B','\U1D3C','\U1D3D','\U1D3E','\U1D3F','\U1D40','\U1D41','\U1D42','\U1D43','\U1D44','\U1D45','\U1D46','\U1D47','\U1D48','\U1D49','\U1D4A','\U1D4B','\U1D4C','\U1D4D','\U1D4E','\U1D4F','\U1D50','\U1D51','\U1D52','\U1D53','\U1D54','\U1D55','\U1D56','\U1D57','\U1D58','\U1D59','\U1D5A','\U1D5B','\U1D5C','\U1D5D','\U1D5E','\U1D5F','\U1D60','\U1D61','\U1D62','\U1D63','\U1D64','\U1D65','\U1D66','\U1D67','\U1D68','\U1D69','\U1D6A','\U1D6B','\U1D6C','\U1D6D','\U1D6E','\U1D6F','\U1D70','\U1D71','\U1D72','\U1D73','\U1D74','\U1D75','\U1D76','\U1D77','\U1D78','\U1D79','\U1D7A','\U1D7B','\U1D7C','\U1D7D','\U1D7E','\U1D7F','\U1D80','\U1D81','\U1D82','\U1D83','\U1D84','\U1D85','\U1D86','\U1D87','\U1D88','\U1D89','\U1D8A','\U1D8B','\U1D8C','\U1D8D','\U1D8E','\U1D8F','\U1D90','\U1D91','\U1D92','\U1D93','\U1D94','\U1D95','\U1D96','\U1D97','\U1D98','\U1D99','\U1D9A','\U1D9B','\U1D9C','\U1D9D','\U1D9E','\U1D9F','\U1DA0','\U1DA1','\U1DA2','\U1DA3','\U1DA4','\U1DA5','\U1DA6','\U1DA7','\U1DA8','\U1DA9','\U1DAA','\U1DAB','\U1DAC','\U1DAD','\U1DAE','\U1DAF','\U1DB0','\U1DB1','\U1DB2','\U1DB3','\U1DB4','\U1DB5','\U1DB6','\U1DB7','\U1DB8','\U1DB9','\U1DBA','\U1DBB','\U1DBC','\U1DBD','\U1DBE','\U1DBF','\U1DC0','\U1DC1','\U1DC2','\U1DC3','\U1DC4','\U1DC5','\U1DC6','\U1DC7','\U1DC8','\U1DC9','\U1DCA','\U1DCB','\U1DCC','\U1DCD','\U1DCE','\U1DCF','\U1DD0','\U1DD1','\U1DD2','\U1DD3','\U1DD4','\U1DD5','\U1DD6','\U1DD7','\U1DD8','\U1DD9','\U1DDA','\U1DDB','\U1DDC','\U1DDD','\U1DDE','\U1DDF','\U1DE0','\U1DE1','\U1DE2','\U1DE3','\U1DE4','\U1DE5','\U1DE6','\U1DE7','\U1DE8','\U1DE9','\U1DEA','\U1DEB','\U1DEC','\U1DED','\U1DEE','\U1DEF','\U1DF0','\U1DF1','\U1DF2','\U1DF3','\U1DF4','\U1DF5','\U1DF6','\U1DF7','\U1DF8','\U1DF9','\U1DFA','\U1DFB','\U1DFC','\U1DFD','\U1DFE','\U1DFF','\U1E00','\U1E01','\U1E02','\U1E03','\U1E04','\U1E05','\U1E06','\U1E07','\U1E08','\U1E09','\U1E0A','\U1E0B','\U1E0C','\U1E0D','\U1E0E','\U1E0F','\U1E10','\U1E11','\U1E12','\U1E13','\U1E14','\U1E15','\U1E16','\U1E17','\U1E18','\U1E19','\U1E1A','\U1E1B','\U1E1C','\U1E1D','\U1E1E','\U1E1F','\U1E20','\U1E21','\U1E22','\U1E23','\U1E24','\U1E25','\U1E26','\U1E27','\U1E28','\U1E29','\U1E2A','\U1E2B','\U1E2C','\U1E2D','\U1E2E','\U1E2F','\U1E30','\U1E31','\U1E32','\U1E33','\U1E34','\U1E35','\U1E36','\U1E37','\U1E38','\U1E39','\U1E3A','\U1E3B','\U1E3C','\U1E3D','\U1E3E','\U1E3F','\U1E40','\U1E41','\U1E42','\U1E43','\U1E44','\U1E45','\U1E46','\U1E47','\U1E48','\U1E49','\U1E4A','\U1E4B','\U1E4C','\U1E4D','\U1E4E','\U1E4F','\U1E50','\U1E51','\U1E52','\U1E53','\U1E54','\U1E55','\U1E56','\U1E57','\U1E58','\U1E59','\U1E5A','\U1E5B','\U1E5C','\U1E5D','\U1E5E','\U1E5F','\U1E60','\U1E61','\U1E62','\U1E63','\U1E64','\U1E65','\U1E66','\U1E67','\U1E68','\U1E69','\U1E6A','\U1E6B','\U1E6C','\U1E6D','\U1E6E','\U1E6F','\U1E70','\U1E71','\U1E72','\U1E73','\U1E74','\U1E75','\U1E76','\U1E77','\U1E78','\U1E79','\U1E7A','\U1E7B','\U1E7C','\U1E7D','\U1E7E','\U1E7F','\U1E80','\U1E81','\U1E82','\U1E83','\U1E84','\U1E85','\U1E86','\U1E87','\U1E88','\U1E89','\U1E8A','\U1E8B','\U1E8C','\U1E8D','\U1E8E','\U1E8F','\U1E90','\U1E91','\U1E92','\U1E93','\U1E94','\U1E95','\U1E96','\U1E97','\U1E98','\U1E99','\U1E9A','\U1E9B','\U1E9C','\U1E9D','\U1E9E','\U1E9F','\U1EA0','\U1EA1','\U1EA2','\U1EA3','\U1EA4','\U1EA5','\U1EA6','\U1EA7','\U1EA8','\U1EA9','\U1EAA','\U1EAB','\U1EAC','\U1EAD','\U1EAE','\U1EAF','\U1EB0','\U1EB1','\U1EB2','\U1EB3','\U1EB4','\U1EB5','\U1EB6','\U1EB7','\U1EB8','\U1EB9','\U1EBA','\U1EBB','\U1EBC','\U1EBD','\U1EBE','\U1EBF','\U1EC0','\U1EC1','\U1EC2','\U1EC3','\U1EC4','\U1EC5','\U1EC6','\U1EC7','\U1EC8','\U1EC9','\U1ECA','\U1ECB','\U1ECC','\U1ECD','\U1ECE','\U1ECF','\U1ED0','\U1ED1','\U1ED2','\U1ED3','\U1ED4','\U1ED5','\U1ED6','\U1ED7','\U1ED8','\U1ED9','\U1EDA','\U1EDB','\U1EDC','\U1EDD','\U1EDE','\U1EDF','\U1EE0','\U1EE1','\U1EE2','\U1EE3','\U1EE4','\U1EE5','\U1EE6','\U1EE7','\U1EE8','\U1EE9','\U1EEA','\U1EEB','\U1EEC','\U1EED','\U1EEE','\U1EEF','\U1EF0','\U1EF1','\U1EF2','\U1EF3','\U1EF4','\U1EF5','\U1EF6','\U1EF7','\U1EF8','\U1EF9','\U1EFA','\U1EFB','\U1EFC','\U1EFD','\U1EFE','\U1EFF','\U1F00','\U1F01','\U1F02','\U1F03','\U1F04','\U1F05','\U1F06','\U1F07','\U1F08','\U1F09','\U1F0A','\U1F0B','\U1F0C','\U1F0D','\U1F0E','\U1F0F','\U1F10','\U1F11','\U1F12','\U1F13','\U1F14','\U1F15','\U1F16','\U1F17','\U1F18','\U1F19','\U1F1A','\U1F1B','\U1F1C','\U1F1D','\U1F1E','\U1F1F','\U1F20','\U1F21','\U1F22','\U1F23','\U1F24','\U1F25','\U1F26','\U1F27','\U1F28','\U1F29','\U1F2A','\U1F2B','\U1F2C','\U1F2D','\U1F2E','\U1F2F','\U1F30','\U1F31','\U1F32','\U1F33','\U1F34','\U1F35','\U1F36','\U1F37','\U1F38','\U1F39','\U1F3A','\U1F3B','\U1F3C','\U1F3D','\U1F3E','\U1F3F','\U1F40','\U1F41','\U1F42','\U1F43','\U1F44','\U1F45','\U1F46','\U1F47','\U1F48','\U1F49','\U1F4A','\U1F4B','\U1F4C','\U1F4D','\U1F4E','\U1F4F','\U1F50','\U1F51','\U1F52','\U1F53','\U1F54','\U1F55','\U1F56','\U1F57','\U1F58','\U1F59','\U1F5A','\U1F5B','\U1F5C','\U1F5D','\U1F5E','\U1F5F','\U1F60','\U1F61','\U1F62','\U1F63','\U1F64','\U1F65','\U1F66','\U1F67','\U1F68','\U1F69','\U1F6A','\U1F6B','\U1F6C','\U1F6D','\U1F6E','\U1F6F','\U1F70','\U1F71','\U1F72','\U1F73','\U1F74','\U1F75','\U1F76','\U1F77','\U1F78','\U1F79','\U1F7A','\U1F7B','\U1F7C','\U1F7D','\U1F7E','\U1F7F','\U1F80','\U1F81','\U1F82','\U1F83','\U1F84','\U1F85','\U1F86','\U1F87','\U1F88','\U1F89','\U1F8A','\U1F8B','\U1F8C','\U1F8D','\U1F8E','\U1F8F','\U1F90','\U1F91','\U1F92','\U1F93','\U1F94','\U1F95','\U1F96','\U1F97','\U1F98','\U1F99','\U1F9A','\U1F9B','\U1F9C','\U1F9D','\U1F9E','\U1F9F','\U1FA0','\U1FA1','\U1FA2','\U1FA3','\U1FA4','\U1FA5','\U1FA6','\U1FA7','\U1FA8','\U1FA9','\U1FAA','\U1FAB','\U1FAC','\U1FAD','\U1FAE','\U1FAF','\U1FB0','\U1FB1','\U1FB2','\U1FB3','\U1FB4','\U1FB5','\U1FB6','\U1FB7','\U1FB8','\U1FB9','\U1FBA','\U1FBB','\U1FBC','\U1FBD','\U1FBE','\U1FBF','\U1FC0','\U1FC1','\U1FC2','\U1FC3','\U1FC4','\U1FC5','\U1FC6','\U1FC7','\U1FC8','\U1FC9','\U1FCA','\U1FCB','\U1FCC','\U1FCD','\U1FCE','\U1FCF','\U1FD0','\U1FD1','\U1FD2','\U1FD3','\U1FD4','\U1FD5','\U1FD6','\U1FD7','\U1FD8','\U1FD9','\U1FDA','\U1FDB','\U1FDC','\U1FDD','\U1FDE','\U1FDF','\U1FE0','\U1FE1','\U1FE2','\U1FE3','\U1FE4','\U1FE5','\U1FE6','\U1FE7','\U1FE8','\U1FE9','\U1FEA','\U1FEB','\U1FEC','\U1FED','\U1FEE','\U1FEF','\U1FF0','\U1FF1','\U1FF2','\U1FF3','\U1FF4','\U1FF5','\U1FF6','\U1FF7','\U1FF8','\U1FF9','\U1FFA','\U1FFB','\U1FFC','\U1FFD','\U1FFE','\U1FFF','\U2000','\U2001','\U2002','\U2003','\U2004','\U2005','\U2006','\U2007','\U2008','\U2009','\U200A','\U200B','\U200C','\U200D','\U200E','\U200F','\U2010','\U2011','\U2012','\U2013','\U2014','\U2015','\U2016','\U2017','\U2018','\U2019','\U201A','\U201B','\U201C','\U201D','\U201E','\U201F','\U2020','\U2021','\U2022','\U2023','\U2024','\U2025','\U2026','\U2027','\U2028','\U2029','\U202A','\U202B','\U202C','\U202D','\U202E','\U202F','\U2030','\U2031','\U2032','\U2033','\U2034','\U2035','\U2036','\U2037','\U2038','\U2039','\U203A','\U203B','\U203C','\U203D','\U203E','\U203F','\U2040','\U2041','\U2042','\U2043','\U2044','\U2045','\U2046','\U2047','\U2048','\U2049','\U204A','\U204B','\U204C','\U204D','\U204E','\U204F','\U2050','\U2051','\U2052','\U2053','\U2054','\U2055','\U2056','\U2057','\U2058','\U2059','\U205A','\U205B','\U205C','\U205D','\U205E','\U205F','\U2060','\U2061','\U2062','\U2063','\U2064','\U2065','\U2066','\U2067','\U2068','\U2069','\U206A','\U206B','\U206C','\U206D','\U206E','\U206F','\U2070','\U2071','\U2072','\U2073','\U2074','\U2075','\U2076','\U2077','\U2078','\U2079','\U207A','\U207B','\U207C','\U207D','\U207E','\U207F','\U2080','\U2081','\U2082','\U2083','\U2084','\U2085','\U2086','\U2087','\U2088','\U2089','\U208A','\U208B','\U208C','\U208D','\U208E','\U208F','\U2090','\U2091','\U2092','\U2093','\U2094','\U2095','\U2096','\U2097','\U2098','\U2099','\U209A','\U209B','\U209C','\U209D','\U209E','\U209F','\U20A0','\U20A1','\U20A2','\U20A3','\U20A4','\U20A5','\U20A6','\U20A7','\U20A8','\U20A9','\U20AA','\U20AB','\U20AC','\U20AD','\U20AE','\U20AF','\U20B0','\U20B1','\U20B2','\U20B3','\U20B4','\U20B5','\U20B6','\U20B7','\U20B8','\U20B9','\U20BA','\U20BB','\U20BC','\U20BD','\U20BE','\U20BF','\U20C0','\U20C1','\U20C2','\U20C3','\U20C4','\U20C5','\U20C6','\U20C7','\U20C8','\U20C9','\U20CA','\U20CB','\U20CC','\U20CD','\U20CE','\U20CF','\U20D0','\U20D1','\U20D2','\U20D3','\U20D4','\U20D5','\U20D6','\U20D7','\U20D8','\U20D9','\U20DA','\U20DB','\U20DC','\U20DD','\U20DE','\U20DF','\U20E0','\U20E1','\U20E2','\U20E3','\U20E4','\U20E5','\U20E6','\U20E7','\U20E8','\U20E9','\U20EA','\U20EB','\U20EC','\U20ED','\U20EE','\U20EF','\U20F0','\U20F1','\U20F2','\U20F3','\U20F4','\U20F5','\U20F6','\U20F7','\U20F8','\U20F9','\U20FA','\U20FB','\U20FC','\U20FD','\U20FE','\U20FF','\U2100','\U2101','\U2102','\U2103','\U2104','\U2105','\U2106','\U2107','\U2108','\U2109','\U210A','\U210B','\U210C','\U210D','\U210E','\U210F','\U2110','\U2111','\U2112','\U2113','\U2114','\U2115','\U2116','\U2117','\U2118','\U2119','\U211A','\U211B','\U211C','\U211D','\U211E','\U211F','\U2120','\U2121','\U2122','\U2123','\U2124','\U2125','\U2126','\U2127','\U2128','\U2129','\U212A','\U212B','\U212C','\U212D','\U212E','\U212F','\U2130','\U2131','\U2132','\U2133','\U2134','\U2135','\U2136','\U2137','\U2138','\U2139','\U213A','\U213B','\U213C','\U213D','\U213E','\U213F','\U2140','\U2141','\U2142','\U2143','\U2144','\U2145','\U2146','\U2147','\U2148','\U2149','\U214A','\U214B','\U214C','\U214D','\U214E','\U214F','\U2150','\U2151','\U2152','\U2153','\U2154','\U2155','\U2156','\U2157','\U2158','\U2159','\U215A','\U215B','\U215C','\U215D','\U215E','\U215F','\U2160','\U2161','\U2162','\U2163','\U2164','\U2165','\U2166','\U2167','\U2168','\U2169','\U216A','\U216B','\U216C','\U216D','\U216E','\U216F','\U2170','\U2171','\U2172','\U2173','\U2174','\U2175','\U2176','\U2177','\U2178','\U2179','\U217A','\U217B','\U217C','\U217D','\U217E','\U217F','\U2180','\U2181','\U2182','\U2183','\U2184','\U2185','\U2186','\U2187','\U2188','\U2189','\U218A','\U218B','\U218C','\U218D','\U218E','\U218F','\U2190','\U2191','\U2192','\U2193','\U2194','\U2195','\U2196','\U2197','\U2198','\U2199','\U219A','\U219B','\U219C','\U219D','\U219E','\U219F','\U21A0','\U21A1','\U21A2','\U21A3','\U21A4','\U21A5','\U21A6','\U21A7','\U21A8','\U21A9','\U21AA','\U21AB','\U21AC','\U21AD','\U21AE','\U21AF','\U21B0','\U21B1','\U21B2','\U21B3','\U21B4','\U21B5','\U21B6','\U21B7','\U21B8','\U21B9','\U21BA','\U21BB','\U21BC','\U21BD','\U21BE','\U21BF','\U21C0','\U21C1','\U21C2','\U21C3','\U21C4','\U21C5','\U21C6','\U21C7','\U21C8','\U21C9','\U21CA','\U21CB','\U21CC','\U21CD','\U21CE','\U21CF','\U21D0','\U21D1','\U21D2','\U21D3','\U21D4','\U21D5','\U21D6','\U21D7','\U21D8','\U21D9','\U21DA','\U21DB','\U21DC','\U21DD','\U21DE','\U21DF','\U21E0','\U21E1','\U21E2','\U21E3','\U21E4','\U21E5','\U21E6','\U21E7','\U21E8','\U21E9','\U21EA','\U21EB','\U21EC','\U21ED','\U21EE','\U21EF','\U21F0','\U21F1','\U21F2','\U21F3','\U21F4','\U21F5','\U21F6','\U21F7','\U21F8','\U21F9','\U21FA','\U21FB','\U21FC','\U21FD','\U21FE','\U21FF','\U2200','\U2201','\U2202','\U2203','\U2204','\U2205','\U2206','\U2207','\U2208','\U2209','\U220A','\U220B','\U220C','\U220D','\U220E','\U220F','\U2210','\U2211','\U2212','\U2213','\U2214','\U2215','\U2216','\U2217','\U2218','\U2219','\U221A','\U221B','\U221C','\U221D','\U221E','\U221F','\U2220','\U2221','\U2222','\U2223','\U2224','\U2225','\U2226','\U2227','\U2228','\U2229','\U222A','\U222B','\U222C','\U222D','\U222E','\U222F','\U2230','\U2231','\U2232','\U2233','\U2234','\U2235','\U2236','\U2237','\U2238','\U2239','\U223A','\U223B','\U223C','\U223D','\U223E','\U223F','\U2240','\U2241','\U2242','\U2243','\U2244','\U2245','\U2246','\U2247','\U2248','\U2249','\U224A','\U224B','\U224C','\U224D','\U224E','\U224F','\U2250','\U2251','\U2252','\U2253','\U2254','\U2255','\U2256','\U2257','\U2258','\U2259','\U225A','\U225B','\U225C','\U225D','\U225E','\U225F','\U2260','\U2261','\U2262','\U2263','\U2264','\U2265','\U2266','\U2267','\U2268','\U2269','\U226A','\U226B','\U226C','\U226D','\U226E','\U226F','\U2270','\U2271','\U2272','\U2273','\U2274','\U2275','\U2276','\U2277','\U2278','\U2279','\U227A','\U227B','\U227C','\U227D','\U227E','\U227F','\U2280','\U2281','\U2282','\U2283','\U2284','\U2285','\U2286','\U2287','\U2288','\U2289','\U228A','\U228B','\U228C','\U228D','\U228E','\U228F','\U2290','\U2291','\U2292','\U2293','\U2294','\U2295','\U2296','\U2297','\U2298','\U2299','\U229A','\U229B','\U229C','\U229D','\U229E','\U229F','\U22A0','\U22A1','\U22A2','\U22A3','\U22A4','\U22A5','\U22A6','\U22A7','\U22A8','\U22A9','\U22AA','\U22AB','\U22AC','\U22AD','\U22AE','\U22AF','\U22B0','\U22B1','\U22B2','\U22B3','\U22B4','\U22B5','\U22B6','\U22B7','\U22B8','\U22B9','\U22BA','\U22BB','\U22BC','\U22BD','\U22BE','\U22BF','\U22C0','\U22C1','\U22C2','\U22C3','\U22C4','\U22C5','\U22C6','\U22C7','\U22C8','\U22C9','\U22CA','\U22CB','\U22CC','\U22CD','\U22CE','\U22CF','\U22D0','\U22D1','\U22D2','\U22D3','\U22D4','\U22D5','\U22D6','\U22D7','\U22D8','\U22D9','\U22DA','\U22DB','\U22DC','\U22DD','\U22DE','\U22DF','\U22E0','\U22E1','\U22E2','\U22E3','\U22E4','\U22E5','\U22E6','\U22E7','\U22E8','\U22E9','\U22EA','\U22EB','\U22EC','\U22ED','\U22EE','\U22EF','\U22F0','\U22F1','\U22F2','\U22F3','\U22F4','\U22F5','\U22F6','\U22F7','\U22F8','\U22F9','\U22FA','\U22FB','\U22FC','\U22FD','\U22FE','\U22FF','\U2300','\U2301','\U2302','\U2303','\U2304','\U2305','\U2306','\U2307','\U2308','\U2309','\U230A','\U230B','\U230C','\U230D','\U230E','\U230F','\U2310','\U2311','\U2312','\U2313','\U2314','\U2315','\U2316','\U2317','\U2318','\U2319','\U231A','\U231B','\U231C','\U231D','\U231E','\U231F','\U2320','\U2321','\U2322','\U2323','\U2324','\U2325','\U2326','\U2327','\U2328','\U2329','\U232A','\U232B','\U232C','\U232D','\U232E','\U232F','\U2330','\U2331','\U2332','\U2333','\U2334','\U2335','\U2336','\U2337','\U2338','\U2339','\U233A','\U233B','\U233C','\U233D','\U233E','\U233F','\U2340','\U2341','\U2342','\U2343','\U2344','\U2345','\U2346','\U2347','\U2348','\U2349','\U234A','\U234B','\U234C','\U234D','\U234E','\U234F','\U2350','\U2351','\U2352','\U2353','\U2354','\U2355','\U2356','\U2357','\U2358','\U2359','\U235A','\U235B','\U235C','\U235D','\U235E','\U235F','\U2360','\U2361','\U2362','\U2363','\U2364','\U2365','\U2366','\U2367','\U2368','\U2369','\U236A','\U236B','\U236C','\U236D','\U236E','\U236F','\U2370','\U2371','\U2372','\U2373','\U2374','\U2375','\U2376','\U2377','\U2378','\U2379','\U237A','\U237B','\U237C','\U237D','\U237E','\U237F','\U2380','\U2381','\U2382','\U2383','\U2384','\U2385','\U2386','\U2387','\U2388','\U2389','\U238A','\U238B','\U238C','\U238D','\U238E','\U238F','\U2390','\U2391','\U2392','\U2393','\U2394','\U2395','\U2396','\U2397','\U2398','\U2399','\U239A','\U239B','\U239C','\U239D','\U239E','\U239F','\U23A0','\U23A1','\U23A2','\U23A3','\U23A4','\U23A5','\U23A6','\U23A7','\U23A8','\U23A9','\U23AA','\U23AB','\U23AC','\U23AD','\U23AE','\U23AF','\U23B0','\U23B1','\U23B2','\U23B3','\U23B4','\U23B5','\U23B6','\U23B7','\U23B8','\U23B9','\U23BA','\U23BB','\U23BC','\U23BD','\U23BE','\U23BF','\U23C0','\U23C1','\U23C2','\U23C3','\U23C4','\U23C5','\U23C6','\U23C7','\U23C8','\U23C9','\U23CA','\U23CB','\U23CC','\U23CD','\U23CE','\U23CF','\U23D0','\U23D1','\U23D2','\U23D3','\U23D4','\U23D5','\U23D6','\U23D7','\U23D8','\U23D9','\U23DA','\U23DB','\U23DC','\U23DD','\U23DE','\U23DF','\U23E0','\U23E1','\U23E2','\U23E3','\U23E4','\U23E5','\U23E6','\U23E7','\U23E8','\U23E9','\U23EA','\U23EB','\U23EC','\U23ED','\U23EE','\U23EF','\U23F0','\U23F1','\U23F2','\U23F3','\U23F4','\U23F5','\U23F6','\U23F7','\U23F8','\U23F9','\U23FA','\U23FB','\U23FC','\U23FD','\U23FE','\U23FF','\U2400','\U2401','\U2402','\U2403','\U2404','\U2405','\U2406','\U2407','\U2408','\U2409','\U240A','\U240B','\U240C','\U240D','\U240E','\U240F','\U2410','\U2411','\U2412','\U2413','\U2414','\U2415','\U2416','\U2417','\U2418','\U2419','\U241A','\U241B','\U241C','\U241D','\U241E','\U241F','\U2420','\U2421','\U2422','\U2423','\U2424','\U2425','\U2426','\U2427','\U2428','\U2429','\U242A','\U242B','\U242C','\U242D','\U242E','\U242F','\U2430','\U2431','\U2432','\U2433','\U2434','\U2435','\U2436','\U2437','\U2438','\U2439','\U243A','\U243B','\U243C','\U243D','\U243E','\U243F','\U2440','\U2441','\U2442','\U2443','\U2444','\U2445','\U2446','\U2447','\U2448','\U2449','\U244A','\U244B','\U244C','\U244D','\U244E','\U244F','\U2450','\U2451','\U2452','\U2453','\U2454','\U2455','\U2456','\U2457','\U2458','\U2459','\U245A','\U245B','\U245C','\U245D','\U245E','\U245F','\U2460','\U2461','\U2462','\U2463','\U2464','\U2465','\U2466','\U2467','\U2468','\U2469','\U246A','\U246B','\U246C','\U246D','\U246E','\U246F','\U2470','\U2471','\U2472','\U2473','\U2474','\U2475','\U2476','\U2477','\U2478','\U2479','\U247A','\U247B','\U247C','\U247D','\U247E','\U247F','\U2480','\U2481','\U2482','\U2483','\U2484','\U2485','\U2486','\U2487','\U2488','\U2489','\U248A','\U248B','\U248C','\U248D','\U248E','\U248F','\U2490','\U2491','\U2492','\U2493','\U2494','\U2495','\U2496','\U2497','\U2498','\U2499','\U249A','\U249B','\U249C','\U249D','\U249E','\U249F','\U24A0','\U24A1','\U24A2','\U24A3','\U24A4','\U24A5','\U24A6','\U24A7','\U24A8','\U24A9','\U24AA','\U24AB','\U24AC','\U24AD','\U24AE','\U24AF','\U24B0','\U24B1','\U24B2','\U24B3','\U24B4','\U24B5','\U24B6','\U24B7','\U24B8','\U24B9','\U24BA','\U24BB','\U24BC','\U24BD','\U24BE','\U24BF','\U24C0','\U24C1','\U24C2','\U24C3','\U24C4','\U24C5','\U24C6','\U24C7','\U24C8','\U24C9','\U24CA','\U24CB','\U24CC','\U24CD','\U24CE','\U24CF','\U24D0','\U24D1','\U24D2','\U24D3','\U24D4','\U24D5','\U24D6','\U24D7','\U24D8','\U24D9','\U24DA','\U24DB','\U24DC','\U24DD','\U24DE','\U24DF','\U24E0','\U24E1','\U24E2','\U24E3','\U24E4','\U24E5','\U24E6','\U24E7','\U24E8','\U24E9','\U24EA','\U24EB','\U24EC','\U24ED','\U24EE','\U24EF','\U24F0','\U24F1','\U24F2','\U24F3','\U24F4','\U24F5','\U24F6','\U24F7','\U24F8','\U24F9','\U24FA','\U24FB','\U24FC','\U24FD','\U24FE','\U24FF','\U2500','\U2501','\U2502','\U2503','\U2504','\U2505','\U2506','\U2507','\U2508','\U2509','\U250A','\U250B','\U250C','\U250D','\U250E','\U250F','\U2510','\U2511','\U2512','\U2513','\U2514','\U2515','\U2516','\U2517','\U2518','\U2519','\U251A','\U251B','\U251C','\U251D','\U251E','\U251F','\U2520','\U2521','\U2522','\U2523','\U2524','\U2525','\U2526','\U2527','\U2528','\U2529','\U252A','\U252B','\U252C','\U252D','\U252E','\U252F','\U2530','\U2531','\U2532','\U2533','\U2534','\U2535','\U2536','\U2537','\U2538','\U2539','\U253A','\U253B','\U253C','\U253D','\U253E','\U253F','\U2540','\U2541','\U2542','\U2543','\U2544','\U2545','\U2546','\U2547','\U2548','\U2549','\U254A','\U254B','\U254C','\U254D','\U254E','\U254F','\U2550','\U2551','\U2552','\U2553','\U2554','\U2555','\U2556','\U2557','\U2558','\U2559','\U255A','\U255B','\U255C','\U255D','\U255E','\U255F','\U2560','\U2561','\U2562','\U2563','\U2564','\U2565','\U2566','\U2567','\U2568','\U2569','\U256A','\U256B','\U256C','\U256D','\U256E','\U256F','\U2570','\U2571','\U2572','\U2573','\U2574','\U2575','\U2576','\U2577','\U2578','\U2579','\U257A','\U257B','\U257C','\U257D','\U257E','\U257F','\U2580','\U2581','\U2582','\U2583','\U2584','\U2585','\U2586','\U2587','\U2588','\U2589','\U258A','\U258B','\U258C','\U258D','\U258E','\U258F','\U2590','\U2591','\U2592','\U2593','\U2594','\U2595','\U2596','\U2597','\U2598','\U2599','\U259A','\U259B','\U259C','\U259D','\U259E','\U259F','\U25A0','\U25A1','\U25A2','\U25A3','\U25A4','\U25A5','\U25A6','\U25A7','\U25A8','\U25A9','\U25AA','\U25AB','\U25AC','\U25AD','\U25AE','\U25AF','\U25B0','\U25B1','\U25B2','\U25B3','\U25B4','\U25B5','\U25B6','\U25B7','\U25B8','\U25B9','\U25BA','\U25BB','\U25BC','\U25BD','\U25BE','\U25BF','\U25C0','\U25C1','\U25C2','\U25C3','\U25C4','\U25C5','\U25C6','\U25C7','\U25C8','\U25C9','\U25CA','\U25CB','\U25CC','\U25CD','\U25CE','\U25CF','\U25D0','\U25D1','\U25D2','\U25D3','\U25D4','\U25D5','\U25D6','\U25D7','\U25D8','\U25D9','\U25DA','\U25DB','\U25DC','\U25DD','\U25DE','\U25DF','\U25E0','\U25E1','\U25E2','\U25E3','\U25E4','\U25E5','\U25E6','\U25E7','\U25E8','\U25E9','\U25EA','\U25EB','\U25EC','\U25ED','\U25EE','\U25EF','\U25F0','\U25F1','\U25F2','\U25F3','\U25F4','\U25F5','\U25F6','\U25F7','\U25F8','\U25F9','\U25FA','\U25FB','\U25FC','\U25FD','\U25FE','\U25FF','\U2600','\U2601','\U2602','\U2603','\U2604','\U2605','\U2606','\U2607','\U2608','\U2609','\U260A','\U260B','\U260C','\U260D','\U260E','\U260F','\U2610','\U2611','\U2612','\U2613','\U2614','\U2615','\U2616','\U2617','\U2618','\U2619','\U261A','\U261B','\U261C','\U261D','\U261E','\U261F','\U2620','\U2621','\U2622','\U2623','\U2624','\U2625','\U2626','\U2627','\U2628','\U2629','\U262A','\U262B','\U262C','\U262D','\U262E','\U262F','\U2630','\U2631','\U2632','\U2633','\U2634','\U2635','\U2636','\U2637','\U2638','\U2639','\U263A','\U263B','\U263C','\U263D','\U263E','\U263F','\U2640','\U2641','\U2642','\U2643','\U2644','\U2645','\U2646','\U2647','\U2648','\U2649','\U264A','\U264B','\U264C','\U264D','\U264E','\U264F','\U2650','\U2651','\U2652','\U2653','\U2654','\U2655','\U2656','\U2657','\U2658','\U2659','\U265A','\U265B','\U265C','\U265D','\U265E','\U265F','\U2660','\U2661','\U2662','\U2663','\U2664','\U2665','\U2666','\U2667','\U2668','\U2669','\U266A','\U266B','\U266C','\U266D','\U266E','\U266F','\U2670','\U2671','\U2672','\U2673','\U2674','\U2675','\U2676','\U2677','\U2678','\U2679','\U267A','\U267B','\U267C','\U267D','\U267E','\U267F','\U2680','\U2681','\U2682','\U2683','\U2684','\U2685','\U2686','\U2687','\U2688','\U2689','\U268A','\U268B','\U268C','\U268D','\U268E','\U268F','\U2690','\U2691','\U2692','\U2693','\U2694','\U2695','\U2696','\U2697','\U2698','\U2699','\U269A','\U269B','\U269C','\U269D','\U269E','\U269F','\U26A0','\U26A1','\U26A2','\U26A3','\U26A4','\U26A5','\U26A6','\U26A7','\U26A8','\U26A9','\U26AA','\U26AB','\U26AC','\U26AD','\U26AE','\U26AF','\U26B0','\U26B1','\U26B2','\U26B3','\U26B4','\U26B5','\U26B6','\U26B7','\U26B8','\U26B9','\U26BA','\U26BB','\U26BC','\U26BD','\U26BE','\U26BF','\U26C0','\U26C1','\U26C2','\U26C3','\U26C4','\U26C5','\U26C6','\U26C7','\U26C8','\U26C9','\U26CA','\U26CB','\U26CC','\U26CD','\U26CE','\U26CF','\U26D0','\U26D1','\U26D2','\U26D3','\U26D4','\U26D5','\U26D6','\U26D7','\U26D8','\U26D9','\U26DA','\U26DB','\U26DC','\U26DD','\U26DE','\U26DF','\U26E0','\U26E1','\U26E2','\U26E3','\U26E4','\U26E5','\U26E6','\U26E7','\U26E8','\U26E9','\U26EA','\U26EB','\U26EC','\U26ED','\U26EE','\U26EF','\U26F0','\U26F1','\U26F2','\U26F3','\U26F4','\U26F5','\U26F6','\U26F7','\U26F8','\U26F9','\U26FA','\U26FB','\U26FC','\U26FD','\U26FE','\U26FF','\U2700','\U2701','\U2702','\U2703','\U2704','\U2705','\U2706','\U2707','\U2708','\U2709','\U270A','\U270B','\U270C','\U270D','\U270E','\U270F','\U2710','\U2711','\U2712','\U2713','\U2714','\U2715','\U2716','\U2717','\U2718','\U2719','\U271A','\U271B','\U271C','\U271D','\U271E','\U271F','\U2720','\U2721','\U2722','\U2723','\U2724','\U2725','\U2726','\U2727','\U2728','\U2729','\U272A','\U272B','\U272C','\U272D','\U272E','\U272F','\U2730','\U2731','\U2732','\U2733','\U2734','\U2735','\U2736','\U2737','\U2738','\U2739','\U273A','\U273B','\U273C','\U273D','\U273E','\U273F','\U2740','\U2741','\U2742','\U2743','\U2744','\U2745','\U2746','\U2747','\U2748','\U2749','\U274A','\U274B','\U274C','\U274D','\U274E','\U274F','\U2750','\U2751','\U2752','\U2753','\U2754','\U2755','\U2756','\U2757','\U2758','\U2759','\U275A','\U275B','\U275C','\U275D','\U275E','\U275F','\U2760','\U2761','\U2762','\U2763','\U2764','\U2765','\U2766','\U2767','\U2768','\U2769','\U276A','\U276B','\U276C','\U276D','\U276E','\U276F','\U2770','\U2771','\U2772','\U2773','\U2774','\U2775','\U2776','\U2777','\U2778','\U2779','\U277A','\U277B','\U277C','\U277D','\U277E','\U277F','\U2780','\U2781','\U2782','\U2783','\U2784','\U2785','\U2786','\U2787','\U2788','\U2789','\U278A','\U278B','\U278C','\U278D','\U278E','\U278F','\U2790','\U2791','\U2792','\U2793','\U2794','\U2795','\U2796','\U2797','\U2798','\U2799','\U279A','\U279B','\U279C','\U279D','\U279E','\U279F','\U27A0','\U27A1','\U27A2','\U27A3','\U27A4','\U27A5','\U27A6','\U27A7','\U27A8','\U27A9','\U27AA','\U27AB','\U27AC','\U27AD','\U27AE','\U27AF','\U27B0','\U27B1','\U27B2','\U27B3','\U27B4','\U27B5','\U27B6','\U27B7','\U27B8','\U27B9','\U27BA','\U27BB','\U27BC','\U27BD','\U27BE','\U27BF','\U27C0','\U27C1','\U27C2','\U27C3','\U27C4','\U27C5','\U27C6','\U27C7','\U27C8','\U27C9','\U27CA','\U27CB','\U27CC','\U27CD','\U27CE','\U27CF','\U27D0','\U27D1','\U27D2','\U27D3','\U27D4','\U27D5','\U27D6','\U27D7','\U27D8','\U27D9','\U27DA','\U27DB','\U27DC','\U27DD','\U27DE','\U27DF','\U27E0','\U27E1','\U27E2','\U27E3','\U27E4','\U27E5','\U27E6','\U27E7','\U27E8','\U27E9','\U27EA','\U27EB','\U27EC','\U27ED','\U27EE','\U27EF','\U27F0','\U27F1','\U27F2','\U27F3','\U27F4','\U27F5','\U27F6','\U27F7','\U27F8','\U27F9','\U27FA','\U27FB','\U27FC','\U27FD','\U27FE','\U27FF','\U2800','\U2801','\U2802','\U2803','\U2804','\U2805','\U2806','\U2807','\U2808','\U2809','\U280A','\U280B','\U280C','\U280D','\U280E','\U280F','\U2810','\U2811','\U2812','\U2813','\U2814','\U2815','\U2816','\U2817','\U2818','\U2819','\U281A','\U281B','\U281C','\U281D','\U281E','\U281F','\U2820','\U2821','\U2822','\U2823','\U2824','\U2825','\U2826','\U2827','\U2828','\U2829','\U282A','\U282B','\U282C','\U282D','\U282E','\U282F','\U2830','\U2831','\U2832','\U2833','\U2834','\U2835','\U2836','\U2837','\U2838','\U2839','\U283A','\U283B','\U283C','\U283D','\U283E','\U283F','\U2840','\U2841','\U2842','\U2843','\U2844','\U2845','\U2846','\U2847','\U2848','\U2849','\U284A','\U284B','\U284C','\U284D','\U284E','\U284F','\U2850','\U2851','\U2852','\U2853','\U2854','\U2855','\U2856','\U2857','\U2858','\U2859','\U285A','\U285B','\U285C','\U285D','\U285E','\U285F','\U2860','\U2861','\U2862','\U2863','\U2864','\U2865','\U2866','\U2867','\U2868','\U2869','\U286A','\U286B','\U286C','\U286D','\U286E','\U286F','\U2870','\U2871','\U2872','\U2873','\U2874','\U2875','\U2876','\U2877','\U2878','\U2879','\U287A','\U287B','\U287C','\U287D','\U287E','\U287F','\U2880','\U2881','\U2882','\U2883','\U2884','\U2885','\U2886','\U2887','\U2888','\U2889','\U288A','\U288B','\U288C','\U288D','\U288E','\U288F','\U2890','\U2891','\U2892','\U2893','\U2894','\U2895','\U2896','\U2897','\U2898','\U2899','\U289A','\U289B','\U289C','\U289D','\U289E','\U289F','\U28A0','\U28A1','\U28A2','\U28A3','\U28A4','\U28A5','\U28A6','\U28A7','\U28A8','\U28A9','\U28AA','\U28AB','\U28AC','\U28AD','\U28AE','\U28AF','\U28B0','\U28B1','\U28B2','\U28B3','\U28B4','\U28B5','\U28B6','\U28B7','\U28B8','\U28B9','\U28BA','\U28BB','\U28BC','\U28BD','\U28BE','\U28BF','\U28C0','\U28C1','\U28C2','\U28C3','\U28C4','\U28C5','\U28C6','\U28C7','\U28C8','\U28C9','\U28CA','\U28CB','\U28CC','\U28CD','\U28CE','\U28CF','\U28D0','\U28D1','\U28D2','\U28D3','\U28D4','\U28D5','\U28D6','\U28D7','\U28D8','\U28D9','\U28DA','\U28DB','\U28DC','\U28DD','\U28DE','\U28DF','\U28E0','\U28E1','\U28E2','\U28E3','\U28E4','\U28E5','\U28E6','\U28E7','\U28E8','\U28E9','\U28EA','\U28EB','\U28EC','\U28ED','\U28EE','\U28EF','\U28F0','\U28F1','\U28F2','\U28F3','\U28F4','\U28F5','\U28F6','\U28F7','\U28F8','\U28F9','\U28FA','\U28FB','\U28FC','\U28FD','\U28FE','\U28FF','\U2900','\U2901','\U2902','\U2903','\U2904','\U2905','\U2906','\U2907','\U2908','\U2909','\U290A','\U290B','\U290C','\U290D','\U290E','\U290F','\U2910','\U2911','\U2912','\U2913','\U2914','\U2915','\U2916','\U2917','\U2918','\U2919','\U291A','\U291B','\U291C','\U291D','\U291E','\U291F','\U2920','\U2921','\U2922','\U2923','\U2924','\U2925','\U2926','\U2927','\U2928','\U2929','\U292A','\U292B','\U292C','\U292D','\U292E','\U292F','\U2930','\U2931','\U2932','\U2933','\U2934','\U2935','\U2936','\U2937','\U2938','\U2939','\U293A','\U293B','\U293C','\U293D','\U293E','\U293F','\U2940','\U2941','\U2942','\U2943','\U2944','\U2945','\U2946','\U2947','\U2948','\U2949','\U294A','\U294B','\U294C','\U294D','\U294E','\U294F','\U2950','\U2951','\U2952','\U2953','\U2954','\U2955','\U2956','\U2957','\U2958','\U2959','\U295A','\U295B','\U295C','\U295D','\U295E','\U295F','\U2960','\U2961','\U2962','\U2963','\U2964','\U2965','\U2966','\U2967','\U2968','\U2969','\U296A','\U296B','\U296C','\U296D','\U296E','\U296F','\U2970','\U2971','\U2972','\U2973','\U2974','\U2975','\U2976','\U2977','\U2978','\U2979','\U297A','\U297B','\U297C','\U297D','\U297E','\U297F','\U2980','\U2981','\U2982','\U2983','\U2984','\U2985','\U2986','\U2987','\U2988','\U2989','\U298A','\U298B','\U298C','\U298D','\U298E','\U298F','\U2990','\U2991','\U2992','\U2993','\U2994','\U2995','\U2996','\U2997','\U2998','\U2999','\U299A','\U299B','\U299C','\U299D','\U299E','\U299F','\U29A0','\U29A1','\U29A2','\U29A3','\U29A4','\U29A5','\U29A6','\U29A7','\U29A8','\U29A9','\U29AA','\U29AB','\U29AC','\U29AD','\U29AE','\U29AF','\U29B0','\U29B1','\U29B2','\U29B3','\U29B4','\U29B5','\U29B6','\U29B7','\U29B8','\U29B9','\U29BA','\U29BB','\U29BC','\U29BD','\U29BE','\U29BF','\U29C0','\U29C1','\U29C2','\U29C3','\U29C4','\U29C5','\U29C6','\U29C7','\U29C8','\U29C9','\U29CA','\U29CB','\U29CC','\U29CD','\U29CE','\U29CF','\U29D0','\U29D1','\U29D2','\U29D3','\U29D4','\U29D5','\U29D6','\U29D7','\U29D8','\U29D9','\U29DA','\U29DB','\U29DC','\U29DD','\U29DE','\U29DF','\U29E0','\U29E1','\U29E2','\U29E3','\U29E4','\U29E5','\U29E6','\U29E7','\U29E8','\U29E9','\U29EA','\U29EB','\U29EC','\U29ED','\U29EE','\U29EF','\U29F0','\U29F1','\U29F2','\U29F3','\U29F4','\U29F5','\U29F6','\U29F7','\U29F8','\U29F9','\U29FA','\U29FB','\U29FC','\U29FD','\U29FE','\U29FF','\U2A00','\U2A01','\U2A02','\U2A03','\U2A04','\U2A05','\U2A06','\U2A07','\U2A08','\U2A09','\U2A0A','\U2A0B','\U2A0C','\U2A0D','\U2A0E','\U2A0F','\U2A10','\U2A11','\U2A12','\U2A13','\U2A14','\U2A15','\U2A16','\U2A17','\U2A18','\U2A19','\U2A1A','\U2A1B','\U2A1C','\U2A1D','\U2A1E','\U2A1F','\U2A20','\U2A21','\U2A22','\U2A23','\U2A24','\U2A25','\U2A26','\U2A27','\U2A28','\U2A29','\U2A2A','\U2A2B','\U2A2C','\U2A2D','\U2A2E','\U2A2F','\U2A30','\U2A31','\U2A32','\U2A33','\U2A34','\U2A35','\U2A36','\U2A37','\U2A38','\U2A39','\U2A3A','\U2A3B','\U2A3C','\U2A3D','\U2A3E','\U2A3F','\U2A40','\U2A41','\U2A42','\U2A43','\U2A44','\U2A45','\U2A46','\U2A47','\U2A48','\U2A49','\U2A4A','\U2A4B','\U2A4C','\U2A4D','\U2A4E','\U2A4F','\U2A50','\U2A51','\U2A52','\U2A53','\U2A54','\U2A55','\U2A56','\U2A57','\U2A58','\U2A59','\U2A5A','\U2A5B','\U2A5C','\U2A5D','\U2A5E','\U2A5F','\U2A60','\U2A61','\U2A62','\U2A63','\U2A64','\U2A65','\U2A66','\U2A67','\U2A68','\U2A69','\U2A6A','\U2A6B','\U2A6C','\U2A6D','\U2A6E','\U2A6F','\U2A70','\U2A71','\U2A72','\U2A73','\U2A74','\U2A75','\U2A76','\U2A77','\U2A78','\U2A79','\U2A7A','\U2A7B','\U2A7C','\U2A7D','\U2A7E','\U2A7F','\U2A80','\U2A81','\U2A82','\U2A83','\U2A84','\U2A85','\U2A86','\U2A87','\U2A88','\U2A89','\U2A8A','\U2A8B','\U2A8C','\U2A8D','\U2A8E','\U2A8F','\U2A90','\U2A91','\U2A92','\U2A93','\U2A94','\U2A95','\U2A96','\U2A97','\U2A98','\U2A99','\U2A9A','\U2A9B','\U2A9C','\U2A9D','\U2A9E','\U2A9F','\U2AA0','\U2AA1','\U2AA2','\U2AA3','\U2AA4','\U2AA5','\U2AA6','\U2AA7','\U2AA8','\U2AA9','\U2AAA','\U2AAB','\U2AAC','\U2AAD','\U2AAE','\U2AAF','\U2AB0','\U2AB1','\U2AB2','\U2AB3','\U2AB4','\U2AB5','\U2AB6','\U2AB7','\U2AB8','\U2AB9','\U2ABA','\U2ABB','\U2ABC','\U2ABD','\U2ABE','\U2ABF','\U2AC0','\U2AC1','\U2AC2','\U2AC3','\U2AC4','\U2AC5','\U2AC6','\U2AC7','\U2AC8','\U2AC9','\U2ACA','\U2ACB','\U2ACC','\U2ACD','\U2ACE','\U2ACF','\U2AD0','\U2AD1','\U2AD2','\U2AD3','\U2AD4','\U2AD5','\U2AD6','\U2AD7','\U2AD8','\U2AD9','\U2ADA','\U2ADB','\U2ADC','\U2ADD','\U2ADE','\U2ADF','\U2AE0','\U2AE1','\U2AE2','\U2AE3','\U2AE4','\U2AE5','\U2AE6','\U2AE7','\U2AE8','\U2AE9','\U2AEA','\U2AEB','\U2AEC','\U2AED','\U2AEE','\U2AEF','\U2AF0','\U2AF1','\U2AF2','\U2AF3','\U2AF4','\U2AF5','\U2AF6','\U2AF7','\U2AF8','\U2AF9','\U2AFA','\U2AFB','\U2AFC','\U2AFD','\U2AFE','\U2AFF','\U2B00','\U2B01','\U2B02','\U2B03','\U2B04','\U2B05','\U2B06','\U2B07','\U2B08','\U2B09','\U2B0A','\U2B0B','\U2B0C','\U2B0D','\U2B0E','\U2B0F','\U2B10','\U2B11','\U2B12','\U2B13','\U2B14','\U2B15','\U2B16','\U2B17','\U2B18','\U2B19','\U2B1A','\U2B1B','\U2B1C','\U2B1D','\U2B1E','\U2B1F','\U2B20','\U2B21','\U2B22','\U2B23','\U2B24','\U2B25','\U2B26','\U2B27','\U2B28','\U2B29','\U2B2A','\U2B2B','\U2B2C','\U2B2D','\U2B2E','\U2B2F','\U2B30','\U2B31','\U2B32','\U2B33','\U2B34','\U2B35','\U2B36','\U2B37','\U2B38','\U2B39','\U2B3A','\U2B3B','\U2B3C','\U2B3D','\U2B3E','\U2B3F','\U2B40','\U2B41','\U2B42','\U2B43','\U2B44','\U2B45','\U2B46','\U2B47','\U2B48','\U2B49','\U2B4A','\U2B4B','\U2B4C','\U2B4D','\U2B4E','\U2B4F','\U2B50','\U2B51','\U2B52','\U2B53','\U2B54','\U2B55','\U2B56','\U2B57','\U2B58','\U2B59','\U2B5A','\U2B5B','\U2B5C','\U2B5D','\U2B5E','\U2B5F','\U2B60','\U2B61','\U2B62','\U2B63','\U2B64','\U2B65','\U2B66','\U2B67','\U2B68','\U2B69','\U2B6A','\U2B6B','\U2B6C','\U2B6D','\U2B6E','\U2B6F','\U2B70','\U2B71','\U2B72','\U2B73','\U2B74','\U2B75','\U2B76','\U2B77','\U2B78','\U2B79','\U2B7A','\U2B7B','\U2B7C','\U2B7D','\U2B7E','\U2B7F','\U2B80','\U2B81','\U2B82','\U2B83','\U2B84','\U2B85','\U2B86','\U2B87','\U2B88','\U2B89','\U2B8A','\U2B8B','\U2B8C','\U2B8D','\U2B8E','\U2B8F','\U2B90','\U2B91','\U2B92','\U2B93','\U2B94','\U2B95','\U2B96','\U2B97','\U2B98','\U2B99','\U2B9A','\U2B9B','\U2B9C','\U2B9D','\U2B9E','\U2B9F','\U2BA0','\U2BA1','\U2BA2','\U2BA3','\U2BA4','\U2BA5','\U2BA6','\U2BA7','\U2BA8','\U2BA9','\U2BAA','\U2BAB','\U2BAC','\U2BAD','\U2BAE','\U2BAF','\U2BB0','\U2BB1','\U2BB2','\U2BB3','\U2BB4','\U2BB5','\U2BB6','\U2BB7','\U2BB8','\U2BB9','\U2BBA','\U2BBB','\U2BBC','\U2BBD','\U2BBE','\U2BBF','\U2BC0','\U2BC1','\U2BC2','\U2BC3','\U2BC4','\U2BC5','\U2BC6','\U2BC7','\U2BC8','\U2BC9','\U2BCA','\U2BCB','\U2BCC','\U2BCD','\U2BCE','\U2BCF','\U2BD0','\U2BD1','\U2BD2','\U2BD3','\U2BD4','\U2BD5','\U2BD6','\U2BD7','\U2BD8','\U2BD9','\U2BDA','\U2BDB','\U2BDC','\U2BDD','\U2BDE','\U2BDF','\U2BE0','\U2BE1','\U2BE2','\U2BE3','\U2BE4','\U2BE5','\U2BE6','\U2BE7','\U2BE8','\U2BE9','\U2BEA','\U2BEB','\U2BEC','\U2BED','\U2BEE','\U2BEF','\U2BF0','\U2BF1','\U2BF2','\U2BF3','\U2BF4','\U2BF5','\U2BF6','\U2BF7','\U2BF8','\U2BF9','\U2BFA','\U2BFB','\U2BFC','\U2BFD','\U2BFE','\U2BFF','\U2C00','\U2C01','\U2C02','\U2C03','\U2C04','\U2C05','\U2C06','\U2C07','\U2C08','\U2C09','\U2C0A','\U2C0B','\U2C0C','\U2C0D','\U2C0E','\U2C0F','\U2C10','\U2C11','\U2C12','\U2C13','\U2C14','\U2C15','\U2C16','\U2C17','\U2C18','\U2C19','\U2C1A','\U2C1B','\U2C1C','\U2C1D','\U2C1E','\U2C1F','\U2C20','\U2C21','\U2C22','\U2C23','\U2C24','\U2C25','\U2C26','\U2C27','\U2C28','\U2C29','\U2C2A','\U2C2B','\U2C2C','\U2C2D','\U2C2E','\U2C2F','\U2C30','\U2C31','\U2C32','\U2C33','\U2C34','\U2C35','\U2C36','\U2C37','\U2C38','\U2C39','\U2C3A','\U2C3B','\U2C3C','\U2C3D','\U2C3E','\U2C3F','\U2C40','\U2C41','\U2C42','\U2C43','\U2C44','\U2C45','\U2C46','\U2C47','\U2C48','\U2C49','\U2C4A','\U2C4B','\U2C4C','\U2C4D','\U2C4E','\U2C4F','\U2C50','\U2C51','\U2C52','\U2C53','\U2C54','\U2C55','\U2C56','\U2C57','\U2C58','\U2C59','\U2C5A','\U2C5B','\U2C5C','\U2C5D','\U2C5E','\U2C5F','\U2C60','\U2C61','\U2C62','\U2C63','\U2C64','\U2C65','\U2C66','\U2C67','\U2C68','\U2C69','\U2C6A','\U2C6B','\U2C6C','\U2C6D','\U2C6E','\U2C6F','\U2C70','\U2C71','\U2C72','\U2C73','\U2C74','\U2C75','\U2C76','\U2C77','\U2C78','\U2C79','\U2C7A','\U2C7B','\U2C7C','\U2C7D','\U2C7E','\U2C7F','\U2C80','\U2C81','\U2C82','\U2C83','\U2C84','\U2C85','\U2C86','\U2C87','\U2C88','\U2C89','\U2C8A','\U2C8B','\U2C8C','\U2C8D','\U2C8E','\U2C8F','\U2C90','\U2C91','\U2C92','\U2C93','\U2C94','\U2C95','\U2C96','\U2C97','\U2C98','\U2C99','\U2C9A','\U2C9B','\U2C9C','\U2C9D','\U2C9E','\U2C9F','\U2CA0','\U2CA1','\U2CA2','\U2CA3','\U2CA4','\U2CA5','\U2CA6','\U2CA7','\U2CA8','\U2CA9','\U2CAA','\U2CAB','\U2CAC','\U2CAD','\U2CAE','\U2CAF','\U2CB0','\U2CB1','\U2CB2','\U2CB3','\U2CB4','\U2CB5','\U2CB6','\U2CB7','\U2CB8','\U2CB9','\U2CBA','\U2CBB','\U2CBC','\U2CBD','\U2CBE','\U2CBF','\U2CC0','\U2CC1','\U2CC2','\U2CC3','\U2CC4','\U2CC5','\U2CC6','\U2CC7','\U2CC8','\U2CC9','\U2CCA','\U2CCB','\U2CCC','\U2CCD','\U2CCE','\U2CCF','\U2CD0','\U2CD1','\U2CD2','\U2CD3','\U2CD4','\U2CD5','\U2CD6','\U2CD7','\U2CD8','\U2CD9','\U2CDA','\U2CDB','\U2CDC','\U2CDD','\U2CDE','\U2CDF','\U2CE0','\U2CE1','\U2CE2','\U2CE3','\U2CE4','\U2CE5','\U2CE6','\U2CE7','\U2CE8','\U2CE9','\U2CEA','\U2CEB','\U2CEC','\U2CED','\U2CEE','\U2CEF','\U2CF0','\U2CF1','\U2CF2','\U2CF3','\U2CF4','\U2CF5','\U2CF6','\U2CF7','\U2CF8','\U2CF9','\U2CFA','\U2CFB','\U2CFC','\U2CFD','\U2CFE','\U2CFF','\U2D00','\U2D01','\U2D02','\U2D03','\U2D04','\U2D05','\U2D06','\U2D07','\U2D08','\U2D09','\U2D0A','\U2D0B','\U2D0C','\U2D0D','\U2D0E','\U2D0F','\U2D10','\U2D11','\U2D12','\U2D13','\U2D14','\U2D15','\U2D16','\U2D17','\U2D18','\U2D19','\U2D1A','\U2D1B','\U2D1C','\U2D1D','\U2D1E','\U2D1F','\U2D20','\U2D21','\U2D22','\U2D23','\U2D24','\U2D25','\U2D26','\U2D27','\U2D28','\U2D29','\U2D2A','\U2D2B','\U2D2C','\U2D2D','\U2D2E','\U2D2F','\U2D30','\U2D31','\U2D32','\U2D33','\U2D34','\U2D35','\U2D36','\U2D37','\U2D38','\U2D39','\U2D3A','\U2D3B','\U2D3C','\U2D3D','\U2D3E','\U2D3F','\U2D40','\U2D41','\U2D42','\U2D43','\U2D44','\U2D45','\U2D46','\U2D47','\U2D48','\U2D49','\U2D4A','\U2D4B','\U2D4C','\U2D4D','\U2D4E','\U2D4F','\U2D50','\U2D51','\U2D52','\U2D53','\U2D54','\U2D55','\U2D56','\U2D57','\U2D58','\U2D59','\U2D5A','\U2D5B','\U2D5C','\U2D5D','\U2D5E','\U2D5F','\U2D60','\U2D61','\U2D62','\U2D63','\U2D64','\U2D65','\U2D66','\U2D67','\U2D68','\U2D69','\U2D6A','\U2D6B','\U2D6C','\U2D6D','\U2D6E','\U2D6F','\U2D70','\U2D71','\U2D72','\U2D73','\U2D74','\U2D75','\U2D76','\U2D77','\U2D78','\U2D79','\U2D7A','\U2D7B','\U2D7C','\U2D7D','\U2D7E','\U2D7F','\U2D80','\U2D81','\U2D82','\U2D83','\U2D84','\U2D85','\U2D86','\U2D87','\U2D88','\U2D89','\U2D8A','\U2D8B','\U2D8C','\U2D8D','\U2D8E','\U2D8F','\U2D90','\U2D91','\U2D92','\U2D93','\U2D94','\U2D95','\U2D96','\U2D97','\U2D98','\U2D99','\U2D9A','\U2D9B','\U2D9C','\U2D9D','\U2D9E','\U2D9F','\U2DA0','\U2DA1','\U2DA2','\U2DA3','\U2DA4','\U2DA5','\U2DA6','\U2DA7','\U2DA8','\U2DA9','\U2DAA','\U2DAB','\U2DAC','\U2DAD','\U2DAE','\U2DAF','\U2DB0','\U2DB1','\U2DB2','\U2DB3','\U2DB4','\U2DB5','\U2DB6','\U2DB7','\U2DB8','\U2DB9','\U2DBA','\U2DBB','\U2DBC','\U2DBD','\U2DBE','\U2DBF','\U2DC0','\U2DC1','\U2DC2','\U2DC3','\U2DC4','\U2DC5','\U2DC6','\U2DC7','\U2DC8','\U2DC9','\U2DCA','\U2DCB','\U2DCC','\U2DCD','\U2DCE','\U2DCF','\U2DD0','\U2DD1','\U2DD2','\U2DD3','\U2DD4','\U2DD5','\U2DD6','\U2DD7','\U2DD8','\U2DD9','\U2DDA','\U2DDB','\U2DDC','\U2DDD','\U2DDE','\U2DDF','\U2DE0','\U2DE1','\U2DE2','\U2DE3','\U2DE4','\U2DE5','\U2DE6','\U2DE7','\U2DE8','\U2DE9','\U2DEA','\U2DEB','\U2DEC','\U2DED','\U2DEE','\U2DEF','\U2DF0','\U2DF1','\U2DF2','\U2DF3','\U2DF4','\U2DF5','\U2DF6','\U2DF7','\U2DF8','\U2DF9','\U2DFA','\U2DFB','\U2DFC','\U2DFD','\U2DFE','\U2DFF','\U2E00','\U2E01','\U2E02','\U2E03','\U2E04','\U2E05','\U2E06','\U2E07','\U2E08','\U2E09','\U2E0A','\U2E0B','\U2E0C','\U2E0D','\U2E0E','\U2E0F','\U2E10','\U2E11','\U2E12','\U2E13','\U2E14','\U2E15','\U2E16','\U2E17','\U2E18','\U2E19','\U2E1A','\U2E1B','\U2E1C','\U2E1D','\U2E1E','\U2E1F','\U2E20','\U2E21','\U2E22','\U2E23','\U2E24','\U2E25','\U2E26','\U2E27','\U2E28','\U2E29','\U2E2A','\U2E2B','\U2E2C','\U2E2D','\U2E2E','\U2E2F','\U2E30','\U2E31','\U2E32','\U2E33','\U2E34','\U2E35','\U2E36','\U2E37','\U2E38','\U2E39','\U2E3A','\U2E3B','\U2E3C','\U2E3D','\U2E3E','\U2E3F','\U2E40','\U2E41','\U2E42','\U2E43','\U2E44','\U2E45','\U2E46','\U2E47','\U2E48','\U2E49','\U2E4A','\U2E4B','\U2E4C','\U2E4D','\U2E4E','\U2E4F','\U2E50','\U2E51','\U2E52','\U2E53','\U2E54','\U2E55','\U2E56','\U2E57','\U2E58','\U2E59','\U2E5A','\U2E5B','\U2E5C','\U2E5D','\U2E5E','\U2E5F','\U2E60','\U2E61','\U2E62','\U2E63','\U2E64','\U2E65','\U2E66','\U2E67','\U2E68','\U2E69','\U2E6A','\U2E6B','\U2E6C','\U2E6D','\U2E6E','\U2E6F','\U2E70','\U2E71','\U2E72','\U2E73','\U2E74','\U2E75','\U2E76','\U2E77','\U2E78','\U2E79','\U2E7A','\U2E7B','\U2E7C','\U2E7D','\U2E7E','\U2E7F','\U2E80','\U2E81','\U2E82','\U2E83','\U2E84','\U2E85','\U2E86','\U2E87','\U2E88','\U2E89','\U2E8A','\U2E8B','\U2E8C','\U2E8D','\U2E8E','\U2E8F','\U2E90','\U2E91','\U2E92','\U2E93','\U2E94','\U2E95','\U2E96','\U2E97','\U2E98','\U2E99','\U2E9A','\U2E9B','\U2E9C','\U2E9D','\U2E9E','\U2E9F','\U2EA0','\U2EA1','\U2EA2','\U2EA3','\U2EA4','\U2EA5','\U2EA6','\U2EA7','\U2EA8','\U2EA9','\U2EAA','\U2EAB','\U2EAC','\U2EAD','\U2EAE','\U2EAF','\U2EB0','\U2EB1','\U2EB2','\U2EB3','\U2EB4','\U2EB5','\U2EB6','\U2EB7','\U2EB8','\U2EB9','\U2EBA','\U2EBB','\U2EBC','\U2EBD','\U2EBE','\U2EBF','\U2EC0','\U2EC1','\U2EC2','\U2EC3','\U2EC4','\U2EC5','\U2EC6','\U2EC7','\U2EC8','\U2EC9','\U2ECA','\U2ECB','\U2ECC','\U2ECD','\U2ECE','\U2ECF','\U2ED0','\U2ED1','\U2ED2','\U2ED3','\U2ED4','\U2ED5','\U2ED6','\U2ED7','\U2ED8','\U2ED9','\U2EDA','\U2EDB','\U2EDC','\U2EDD','\U2EDE','\U2EDF','\U2EE0','\U2EE1','\U2EE2','\U2EE3','\U2EE4','\U2EE5','\U2EE6','\U2EE7','\U2EE8','\U2EE9','\U2EEA','\U2EEB','\U2EEC','\U2EED','\U2EEE','\U2EEF','\U2EF0','\U2EF1','\U2EF2','\U2EF3','\U2EF4','\U2EF5','\U2EF6','\U2EF7','\U2EF8','\U2EF9','\U2EFA','\U2EFB','\U2EFC','\U2EFD','\U2EFE','\U2EFF','\U2F00','\U2F01','\U2F02','\U2F03','\U2F04','\U2F05','\U2F06','\U2F07','\U2F08','\U2F09','\U2F0A','\U2F0B','\U2F0C','\U2F0D','\U2F0E','\U2F0F','\U2F10','\U2F11','\U2F12','\U2F13','\U2F14','\U2F15','\U2F16','\U2F17','\U2F18','\U2F19','\U2F1A','\U2F1B','\U2F1C','\U2F1D','\U2F1E','\U2F1F','\U2F20','\U2F21','\U2F22','\U2F23','\U2F24','\U2F25','\U2F26','\U2F27','\U2F28','\U2F29','\U2F2A','\U2F2B','\U2F2C','\U2F2D','\U2F2E','\U2F2F','\U2F30','\U2F31','\U2F32','\U2F33','\U2F34','\U2F35','\U2F36','\U2F37','\U2F38','\U2F39','\U2F3A','\U2F3B','\U2F3C','\U2F3D','\U2F3E','\U2F3F','\U2F40','\U2F41','\U2F42','\U2F43','\U2F44','\U2F45','\U2F46','\U2F47','\U2F48','\U2F49','\U2F4A','\U2F4B','\U2F4C','\U2F4D','\U2F4E','\U2F4F','\U2F50','\U2F51','\U2F52','\U2F53','\U2F54','\U2F55','\U2F56','\U2F57','\U2F58','\U2F59','\U2F5A','\U2F5B','\U2F5C','\U2F5D','\U2F5E','\U2F5F','\U2F60','\U2F61','\U2F62','\U2F63','\U2F64','\U2F65','\U2F66','\U2F67','\U2F68','\U2F69','\U2F6A','\U2F6B','\U2F6C','\U2F6D','\U2F6E','\U2F6F','\U2F70','\U2F71','\U2F72','\U2F73','\U2F74','\U2F75','\U2F76','\U2F77','\U2F78','\U2F79','\U2F7A','\U2F7B','\U2F7C','\U2F7D','\U2F7E','\U2F7F','\U2F80','\U2F81','\U2F82','\U2F83','\U2F84','\U2F85','\U2F86','\U2F87','\U2F88','\U2F89','\U2F8A','\U2F8B','\U2F8C','\U2F8D','\U2F8E','\U2F8F','\U2F90','\U2F91','\U2F92','\U2F93','\U2F94','\U2F95','\U2F96','\U2F97','\U2F98','\U2F99','\U2F9A','\U2F9B','\U2F9C','\U2F9D','\U2F9E','\U2F9F','\U2FA0','\U2FA1','\U2FA2','\U2FA3','\U2FA4','\U2FA5','\U2FA6','\U2FA7','\U2FA8','\U2FA9','\U2FAA','\U2FAB','\U2FAC','\U2FAD','\U2FAE','\U2FAF','\U2FB0','\U2FB1','\U2FB2','\U2FB3','\U2FB4','\U2FB5','\U2FB6','\U2FB7','\U2FB8','\U2FB9','\U2FBA','\U2FBB','\U2FBC','\U2FBD','\U2FBE','\U2FBF','\U2FC0','\U2FC1','\U2FC2','\U2FC3','\U2FC4','\U2FC5','\U2FC6','\U2FC7','\U2FC8','\U2FC9','\U2FCA','\U2FCB','\U2FCC','\U2FCD','\U2FCE','\U2FCF','\U2FD0','\U2FD1','\U2FD2','\U2FD3','\U2FD4','\U2FD5','\U2FD6','\U2FD7','\U2FD8','\U2FD9','\U2FDA','\U2FDB','\U2FDC','\U2FDD','\U2FDE','\U2FDF','\U2FE0','\U2FE1','\U2FE2','\U2FE3','\U2FE4','\U2FE5','\U2FE6','\U2FE7','\U2FE8','\U2FE9','\U2FEA','\U2FEB','\U2FEC','\U2FED','\U2FEE','\U2FEF','\U2FF0','\U2FF1','\U2FF2','\U2FF3','\U2FF4','\U2FF5','\U2FF6','\U2FF7','\U2FF8','\U2FF9','\U2FFA','\U2FFB','\U2FFC','\U2FFD','\U2FFE','\U2FFF','\U3000','\U3001','\U3002','\U3003','\U3004','\U3005','\U3006','\U3007','\U3008','\U3009','\U300A','\U300B','\U300C','\U300D','\U300E','\U300F','\U3010','\U3011','\U3012','\U3013','\U3014','\U3015','\U3016','\U3017','\U3018','\U3019','\U301A','\U301B','\U301C','\U301D','\U301E','\U301F','\U3020','\U3021','\U3022','\U3023','\U3024','\U3025','\U3026','\U3027','\U3028','\U3029','\U302A','\U302B','\U302C','\U302D','\U302E','\U302F','\U3030','\U3031','\U3032','\U3033','\U3034','\U3035','\U3036','\U3037','\U3038','\U3039','\U303A','\U303B','\U303C','\U303D','\U303E','\U303F','\U3040','\U3041','\U3042','\U3043','\U3044','\U3045','\U3046','\U3047','\U3048','\U3049','\U304A','\U304B','\U304C','\U304D','\U304E','\U304F','\U3050','\U3051','\U3052','\U3053','\U3054','\U3055','\U3056','\U3057','\U3058','\U3059','\U305A','\U305B','\U305C','\U305D','\U305E','\U305F','\U3060','\U3061','\U3062','\U3063','\U3064','\U3065','\U3066','\U3067','\U3068','\U3069','\U306A','\U306B','\U306C','\U306D','\U306E','\U306F','\U3070','\U3071','\U3072','\U3073','\U3074','\U3075','\U3076','\U3077','\U3078','\U3079','\U307A','\U307B','\U307C','\U307D','\U307E','\U307F','\U3080','\U3081','\U3082','\U3083','\U3084','\U3085','\U3086','\U3087','\U3088','\U3089','\U308A','\U308B','\U308C','\U308D','\U308E','\U308F','\U3090','\U3091','\U3092','\U3093','\U3094','\U3095','\U3096','\U3097','\U3098','\U3099','\U309A','\U309B','\U309C','\U309D','\U309E','\U309F','\U30A0','\U30A1','\U30A2','\U30A3','\U30A4','\U30A5','\U30A6','\U30A7','\U30A8','\U30A9','\U30AA','\U30AB','\U30AC','\U30AD','\U30AE','\U30AF','\U30B0','\U30B1','\U30B2','\U30B3','\U30B4','\U30B5','\U30B6','\U30B7','\U30B8','\U30B9','\U30BA','\U30BB','\U30BC','\U30BD','\U30BE','\U30BF','\U30C0','\U30C1','\U30C2','\U30C3','\U30C4','\U30C5','\U30C6','\U30C7','\U30C8','\U30C9','\U30CA','\U30CB','\U30CC','\U30CD','\U30CE','\U30CF','\U30D0','\U30D1','\U30D2','\U30D3','\U30D4','\U30D5','\U30D6','\U30D7','\U30D8','\U30D9','\U30DA','\U30DB','\U30DC','\U30DD','\U30DE','\U30DF','\U30E0','\U30E1','\U30E2','\U30E3','\U30E4','\U30E5','\U30E6','\U30E7','\U30E8','\U30E9','\U30EA','\U30EB','\U30EC','\U30ED','\U30EE','\U30EF','\U30F0','\U30F1','\U30F2','\U30F3','\U30F4','\U30F5','\U30F6','\U30F7','\U30F8','\U30F9','\U30FA','\U30FB','\U30FC','\U30FD','\U30FE','\U30FF','\U3100','\U3101','\U3102','\U3103','\U3104','\U3105','\U3106','\U3107','\U3108','\U3109','\U310A','\U310B','\U310C','\U310D','\U310E','\U310F','\U3110','\U3111','\U3112','\U3113','\U3114','\U3115','\U3116','\U3117','\U3118','\U3119','\U311A','\U311B','\U311C','\U311D','\U311E','\U311F','\U3120','\U3121','\U3122','\U3123','\U3124','\U3125','\U3126','\U3127','\U3128','\U3129','\U312A','\U312B','\U312C','\U312D','\U312E','\U312F','\U3130','\U3131','\U3132','\U3133','\U3134','\U3135','\U3136','\U3137','\U3138','\U3139','\U313A','\U313B','\U313C','\U313D','\U313E','\U313F','\U3140','\U3141','\U3142','\U3143','\U3144','\U3145','\U3146','\U3147','\U3148','\U3149','\U314A','\U314B','\U314C','\U314D','\U314E','\U314F','\U3150','\U3151','\U3152','\U3153','\U3154','\U3155','\U3156','\U3157','\U3158','\U3159','\U315A','\U315B','\U315C','\U315D','\U315E','\U315F','\U3160','\U3161','\U3162','\U3163','\U3164','\U3165','\U3166','\U3167','\U3168','\U3169','\U316A','\U316B','\U316C','\U316D','\U316E','\U316F','\U3170','\U3171','\U3172','\U3173','\U3174','\U3175','\U3176','\U3177','\U3178','\U3179','\U317A','\U317B','\U317C','\U317D','\U317E','\U317F','\U3180','\U3181','\U3182','\U3183','\U3184','\U3185','\U3186','\U3187','\U3188','\U3189','\U318A','\U318B','\U318C','\U318D','\U318E','\U318F','\U3190','\U3191','\U3192','\U3193','\U3194','\U3195','\U3196','\U3197','\U3198','\U3199','\U319A','\U319B','\U319C','\U319D','\U319E','\U319F','\U31A0','\U31A1','\U31A2','\U31A3','\U31A4','\U31A5','\U31A6','\U31A7','\U31A8','\U31A9','\U31AA','\U31AB','\U31AC','\U31AD','\U31AE','\U31AF','\U31B0','\U31B1','\U31B2','\U31B3','\U31B4','\U31B5','\U31B6','\U31B7','\U31B8','\U31B9','\U31BA','\U31BB','\U31BC','\U31BD','\U31BE','\U31BF','\U31C0','\U31C1','\U31C2','\U31C3','\U31C4','\U31C5','\U31C6','\U31C7','\U31C8','\U31C9','\U31CA','\U31CB','\U31CC','\U31CD','\U31CE','\U31CF','\U31D0','\U31D1','\U31D2','\U31D3','\U31D4','\U31D5','\U31D6','\U31D7','\U31D8','\U31D9','\U31DA','\U31DB','\U31DC','\U31DD','\U31DE','\U31DF','\U31E0','\U31E1','\U31E2','\U31E3','\U31E4','\U31E5','\U31E6','\U31E7','\U31E8','\U31E9','\U31EA','\U31EB','\U31EC','\U31ED','\U31EE','\U31EF','\U31F0','\U31F1','\U31F2','\U31F3','\U31F4','\U31F5','\U31F6','\U31F7','\U31F8','\U31F9','\U31FA','\U31FB','\U31FC','\U31FD','\U31FE','\U31FF','\U3200','\U3201','\U3202','\U3203','\U3204','\U3205','\U3206','\U3207','\U3208','\U3209','\U320A','\U320B','\U320C','\U320D','\U320E','\U320F','\U3210','\U3211','\U3212','\U3213','\U3214','\U3215','\U3216','\U3217','\U3218','\U3219','\U321A','\U321B','\U321C','\U321D','\U321E','\U321F','\U3220','\U3221','\U3222','\U3223','\U3224','\U3225','\U3226','\U3227','\U3228','\U3229','\U322A','\U322B','\U322C','\U322D','\U322E','\U322F','\U3230','\U3231','\U3232','\U3233','\U3234','\U3235','\U3236','\U3237','\U3238','\U3239','\U323A','\U323B','\U323C','\U323D','\U323E','\U323F','\U3240','\U3241','\U3242','\U3243','\U3244','\U3245','\U3246','\U3247','\U3248','\U3249','\U324A','\U324B','\U324C','\U324D','\U324E','\U324F','\U3250','\U3251','\U3252','\U3253','\U3254','\U3255','\U3256','\U3257','\U3258','\U3259','\U325A','\U325B','\U325C','\U325D','\U325E','\U325F','\U3260','\U3261','\U3262','\U3263','\U3264','\U3265','\U3266','\U3267','\U3268','\U3269','\U326A','\U326B','\U326C','\U326D','\U326E','\U326F','\U3270','\U3271','\U3272','\U3273','\U3274','\U3275','\U3276','\U3277','\U3278','\U3279','\U327A','\U327B','\U327C','\U327D','\U327E','\U327F','\U3280','\U3281','\U3282','\U3283','\U3284','\U3285','\U3286','\U3287','\U3288','\U3289','\U328A','\U328B','\U328C','\U328D','\U328E','\U328F','\U3290','\U3291','\U3292','\U3293','\U3294','\U3295','\U3296','\U3297','\U3298','\U3299','\U329A','\U329B','\U329C','\U329D','\U329E','\U329F','\U32A0','\U32A1','\U32A2','\U32A3','\U32A4','\U32A5','\U32A6','\U32A7','\U32A8','\U32A9','\U32AA','\U32AB','\U32AC','\U32AD','\U32AE','\U32AF','\U32B0','\U32B1','\U32B2','\U32B3','\U32B4','\U32B5','\U32B6','\U32B7','\U32B8','\U32B9','\U32BA','\U32BB','\U32BC','\U32BD','\U32BE','\U32BF','\U32C0','\U32C1','\U32C2','\U32C3','\U32C4','\U32C5','\U32C6','\U32C7','\U32C8','\U32C9','\U32CA','\U32CB','\U32CC','\U32CD','\U32CE','\U32CF','\U32D0','\U32D1','\U32D2','\U32D3','\U32D4','\U32D5','\U32D6','\U32D7','\U32D8','\U32D9','\U32DA','\U32DB','\U32DC','\U32DD','\U32DE','\U32DF','\U32E0','\U32E1','\U32E2','\U32E3','\U32E4','\U32E5','\U32E6','\U32E7','\U32E8','\U32E9','\U32EA','\U32EB','\U32EC','\U32ED','\U32EE','\U32EF','\U32F0','\U32F1','\U32F2','\U32F3','\U32F4','\U32F5','\U32F6','\U32F7','\U32F8','\U32F9','\U32FA','\U32FB','\U32FC','\U32FD','\U32FE','\U32FF','\U3300','\U3301','\U3302','\U3303','\U3304','\U3305','\U3306','\U3307','\U3308','\U3309','\U330A','\U330B','\U330C','\U330D','\U330E','\U330F','\U3310','\U3311','\U3312','\U3313','\U3314','\U3315','\U3316','\U3317','\U3318','\U3319','\U331A','\U331B','\U331C','\U331D','\U331E','\U331F','\U3320','\U3321','\U3322','\U3323','\U3324','\U3325','\U3326','\U3327','\U3328','\U3329','\U332A','\U332B','\U332C','\U332D','\U332E','\U332F','\U3330','\U3331','\U3332','\U3333','\U3334','\U3335','\U3336','\U3337','\U3338','\U3339','\U333A','\U333B','\U333C','\U333D','\U333E','\U333F','\U3340','\U3341','\U3342','\U3343','\U3344','\U3345','\U3346','\U3347','\U3348','\U3349','\U334A','\U334B','\U334C','\U334D','\U334E','\U334F','\U3350','\U3351','\U3352','\U3353','\U3354','\U3355','\U3356','\U3357','\U3358','\U3359','\U335A','\U335B','\U335C','\U335D','\U335E','\U335F','\U3360','\U3361','\U3362','\U3363','\U3364','\U3365','\U3366','\U3367','\U3368','\U3369','\U336A','\U336B','\U336C','\U336D','\U336E','\U336F','\U3370','\U3371','\U3372','\U3373','\U3374','\U3375','\U3376','\U3377','\U3378','\U3379','\U337A','\U337B','\U337C','\U337D','\U337E','\U337F','\U3380','\U3381','\U3382','\U3383','\U3384','\U3385','\U3386','\U3387','\U3388','\U3389','\U338A','\U338B','\U338C','\U338D','\U338E','\U338F','\U3390','\U3391','\U3392','\U3393','\U3394','\U3395','\U3396','\U3397','\U3398','\U3399','\U339A','\U339B','\U339C','\U339D','\U339E','\U339F','\U33A0','\U33A1','\U33A2','\U33A3','\U33A4','\U33A5','\U33A6','\U33A7','\U33A8','\U33A9','\U33AA','\U33AB','\U33AC','\U33AD','\U33AE','\U33AF','\U33B0','\U33B1','\U33B2','\U33B3','\U33B4','\U33B5','\U33B6','\U33B7','\U33B8','\U33B9','\U33BA','\U33BB','\U33BC','\U33BD','\U33BE','\U33BF','\U33C0','\U33C1','\U33C2','\U33C3','\U33C4','\U33C5','\U33C6','\U33C7','\U33C8','\U33C9','\U33CA','\U33CB','\U33CC','\U33CD','\U33CE','\U33CF','\U33D0','\U33D1','\U33D2','\U33D3','\U33D4','\U33D5','\U33D6','\U33D7','\U33D8','\U33D9','\U33DA','\U33DB','\U33DC','\U33DD','\U33DE','\U33DF','\U33E0','\U33E1','\U33E2','\U33E3','\U33E4','\U33E5','\U33E6','\U33E7','\U33E8','\U33E9','\U33EA','\U33EB','\U33EC','\U33ED','\U33EE','\U33EF','\U33F0','\U33F1','\U33F2','\U33F3','\U33F4','\U33F5','\U33F6','\U33F7','\U33F8','\U33F9','\U33FA','\U33FB','\U33FC','\U33FD','\U33FE','\U33FF','\U3400','\U3401','\U3402','\U3403','\U3404','\U3405','\U3406','\U3407','\U3408','\U3409','\U340A','\U340B','\U340C','\U340D','\U340E','\U340F','\U3410','\U3411','\U3412','\U3413','\U3414','\U3415','\U3416','\U3417','\U3418','\U3419','\U341A','\U341B','\U341C','\U341D','\U341E','\U341F','\U3420','\U3421','\U3422','\U3423','\U3424','\U3425','\U3426','\U3427','\U3428','\U3429','\U342A','\U342B','\U342C','\U342D','\U342E','\U342F','\U3430','\U3431','\U3432','\U3433','\U3434','\U3435','\U3436','\U3437','\U3438','\U3439','\U343A','\U343B','\U343C','\U343D','\U343E','\U343F','\U3440','\U3441','\U3442','\U3443','\U3444','\U3445','\U3446','\U3447','\U3448','\U3449','\U344A','\U344B','\U344C','\U344D','\U344E','\U344F','\U3450','\U3451','\U3452','\U3453','\U3454','\U3455','\U3456','\U3457','\U3458','\U3459','\U345A','\U345B','\U345C','\U345D','\U345E','\U345F','\U3460','\U3461','\U3462','\U3463','\U3464','\U3465','\U3466','\U3467','\U3468','\U3469','\U346A','\U346B','\U346C','\U346D','\U346E','\U346F','\U3470','\U3471','\U3472','\U3473','\U3474','\U3475','\U3476','\U3477','\U3478','\U3479','\U347A','\U347B','\U347C','\U347D','\U347E','\U347F','\U3480','\U3481','\U3482','\U3483','\U3484','\U3485','\U3486','\U3487','\U3488','\U3489','\U348A','\U348B','\U348C','\U348D','\U348E','\U348F','\U3490','\U3491','\U3492','\U3493','\U3494','\U3495','\U3496','\U3497','\U3498','\U3499','\U349A','\U349B','\U349C','\U349D','\U349E','\U349F','\U34A0','\U34A1','\U34A2','\U34A3','\U34A4','\U34A5','\U34A6','\U34A7','\U34A8','\U34A9','\U34AA','\U34AB','\U34AC','\U34AD','\U34AE','\U34AF','\U34B0','\U34B1','\U34B2','\U34B3','\U34B4','\U34B5','\U34B6','\U34B7','\U34B8','\U34B9','\U34BA','\U34BB','\U34BC','\U34BD','\U34BE','\U34BF','\U34C0','\U34C1','\U34C2','\U34C3','\U34C4','\U34C5','\U34C6','\U34C7','\U34C8','\U34C9','\U34CA','\U34CB','\U34CC','\U34CD','\U34CE','\U34CF','\U34D0','\U34D1','\U34D2','\U34D3','\U34D4','\U34D5','\U34D6','\U34D7','\U34D8','\U34D9','\U34DA','\U34DB','\U34DC','\U34DD','\U34DE','\U34DF','\U34E0','\U34E1','\U34E2','\U34E3','\U34E4','\U34E5','\U34E6','\U34E7','\U34E8','\U34E9','\U34EA','\U34EB','\U34EC','\U34ED','\U34EE','\U34EF','\U34F0','\U34F1','\U34F2','\U34F3','\U34F4','\U34F5','\U34F6','\U34F7','\U34F8','\U34F9','\U34FA','\U34FB','\U34FC','\U34FD','\U34FE','\U34FF','\U3500','\U3501','\U3502','\U3503','\U3504','\U3505','\U3506','\U3507','\U3508','\U3509','\U350A','\U350B','\U350C','\U350D','\U350E','\U350F','\U3510','\U3511','\U3512','\U3513','\U3514','\U3515','\U3516','\U3517','\U3518','\U3519','\U351A','\U351B','\U351C','\U351D','\U351E','\U351F','\U3520','\U3521','\U3522','\U3523','\U3524','\U3525','\U3526','\U3527','\U3528','\U3529','\U352A','\U352B','\U352C','\U352D','\U352E','\U352F','\U3530','\U3531','\U3532','\U3533','\U3534','\U3535','\U3536','\U3537','\U3538','\U3539','\U353A','\U353B','\U353C','\U353D','\U353E','\U353F','\U3540','\U3541','\U3542','\U3543','\U3544','\U3545','\U3546','\U3547','\U3548','\U3549','\U354A','\U354B','\U354C','\U354D','\U354E','\U354F','\U3550','\U3551','\U3552','\U3553','\U3554','\U3555','\U3556','\U3557','\U3558','\U3559','\U355A','\U355B','\U355C','\U355D','\U355E','\U355F','\U3560','\U3561','\U3562','\U3563','\U3564','\U3565','\U3566','\U3567','\U3568','\U3569','\U356A','\U356B','\U356C','\U356D','\U356E','\U356F','\U3570','\U3571','\U3572','\U3573','\U3574','\U3575','\U3576','\U3577','\U3578','\U3579','\U357A','\U357B','\U357C','\U357D','\U357E','\U357F','\U3580','\U3581','\U3582','\U3583','\U3584','\U3585','\U3586','\U3587','\U3588','\U3589','\U358A','\U358B','\U358C','\U358D','\U358E','\U358F','\U3590','\U3591','\U3592','\U3593','\U3594','\U3595','\U3596','\U3597','\U3598','\U3599','\U359A','\U359B','\U359C','\U359D','\U359E','\U359F','\U35A0','\U35A1','\U35A2','\U35A3','\U35A4','\U35A5','\U35A6','\U35A7','\U35A8','\U35A9','\U35AA','\U35AB','\U35AC','\U35AD','\U35AE','\U35AF','\U35B0','\U35B1','\U35B2','\U35B3','\U35B4','\U35B5','\U35B6','\U35B7','\U35B8','\U35B9','\U35BA','\U35BB','\U35BC','\U35BD','\U35BE','\U35BF','\U35C0','\U35C1','\U35C2','\U35C3','\U35C4','\U35C5','\U35C6','\U35C7','\U35C8','\U35C9','\U35CA','\U35CB','\U35CC','\U35CD','\U35CE','\U35CF','\U35D0','\U35D1','\U35D2','\U35D3','\U35D4','\U35D5','\U35D6','\U35D7','\U35D8','\U35D9','\U35DA','\U35DB','\U35DC','\U35DD','\U35DE','\U35DF','\U35E0','\U35E1','\U35E2','\U35E3','\U35E4','\U35E5','\U35E6','\U35E7','\U35E8','\U35E9','\U35EA','\U35EB','\U35EC','\U35ED','\U35EE','\U35EF','\U35F0','\U35F1','\U35F2','\U35F3','\U35F4','\U35F5','\U35F6','\U35F7','\U35F8','\U35F9','\U35FA','\U35FB','\U35FC','\U35FD','\U35FE','\U35FF','\U3600','\U3601','\U3602','\U3603','\U3604','\U3605','\U3606','\U3607','\U3608','\U3609','\U360A','\U360B','\U360C','\U360D','\U360E','\U360F','\U3610','\U3611','\U3612','\U3613','\U3614','\U3615','\U3616','\U3617','\U3618','\U3619','\U361A','\U361B','\U361C','\U361D','\U361E','\U361F','\U3620','\U3621','\U3622','\U3623','\U3624','\U3625','\U3626','\U3627','\U3628','\U3629','\U362A','\U362B','\U362C','\U362D','\U362E','\U362F','\U3630','\U3631','\U3632','\U3633','\U3634','\U3635','\U3636','\U3637','\U3638','\U3639','\U363A','\U363B','\U363C','\U363D','\U363E','\U363F','\U3640','\U3641','\U3642','\U3643','\U3644','\U3645','\U3646','\U3647','\U3648','\U3649','\U364A','\U364B','\U364C','\U364D','\U364E','\U364F','\U3650','\U3651','\U3652','\U3653','\U3654','\U3655','\U3656','\U3657','\U3658','\U3659','\U365A','\U365B','\U365C','\U365D','\U365E','\U365F','\U3660','\U3661','\U3662','\U3663','\U3664','\U3665','\U3666','\U3667','\U3668','\U3669','\U366A','\U366B','\U366C','\U366D','\U366E','\U366F','\U3670','\U3671','\U3672','\U3673','\U3674','\U3675','\U3676','\U3677','\U3678','\U3679','\U367A','\U367B','\U367C','\U367D','\U367E','\U367F','\U3680','\U3681','\U3682','\U3683','\U3684','\U3685','\U3686','\U3687','\U3688','\U3689','\U368A','\U368B','\U368C','\U368D','\U368E','\U368F','\U3690','\U3691','\U3692','\U3693','\U3694','\U3695','\U3696','\U3697','\U3698','\U3699','\U369A','\U369B','\U369C','\U369D','\U369E','\U369F','\U36A0','\U36A1','\U36A2','\U36A3','\U36A4','\U36A5','\U36A6','\U36A7','\U36A8','\U36A9','\U36AA','\U36AB','\U36AC','\U36AD','\U36AE','\U36AF','\U36B0','\U36B1','\U36B2','\U36B3','\U36B4','\U36B5','\U36B6','\U36B7','\U36B8','\U36B9','\U36BA','\U36BB','\U36BC','\U36BD','\U36BE','\U36BF','\U36C0','\U36C1','\U36C2','\U36C3','\U36C4','\U36C5','\U36C6','\U36C7','\U36C8','\U36C9','\U36CA','\U36CB','\U36CC','\U36CD','\U36CE','\U36CF','\U36D0','\U36D1','\U36D2','\U36D3','\U36D4','\U36D5','\U36D6','\U36D7','\U36D8','\U36D9','\U36DA','\U36DB','\U36DC','\U36DD','\U36DE','\U36DF','\U36E0','\U36E1','\U36E2','\U36E3','\U36E4','\U36E5','\U36E6','\U36E7','\U36E8','\U36E9','\U36EA','\U36EB','\U36EC','\U36ED','\U36EE','\U36EF','\U36F0','\U36F1','\U36F2','\U36F3','\U36F4','\U36F5','\U36F6','\U36F7','\U36F8','\U36F9','\U36FA','\U36FB','\U36FC','\U36FD','\U36FE','\U36FF','\U3700','\U3701','\U3702','\U3703','\U3704','\U3705','\U3706','\U3707','\U3708','\U3709','\U370A','\U370B','\U370C','\U370D','\U370E','\U370F','\U3710','\U3711','\U3712','\U3713','\U3714','\U3715','\U3716','\U3717','\U3718','\U3719','\U371A','\U371B','\U371C','\U371D','\U371E','\U371F','\U3720','\U3721','\U3722','\U3723','\U3724','\U3725','\U3726','\U3727','\U3728','\U3729','\U372A','\U372B','\U372C','\U372D','\U372E','\U372F','\U3730','\U3731','\U3732','\U3733','\U3734','\U3735','\U3736','\U3737','\U3738','\U3739','\U373A','\U373B','\U373C','\U373D','\U373E','\U373F','\U3740','\U3741','\U3742','\U3743','\U3744','\U3745','\U3746','\U3747','\U3748','\U3749','\U374A','\U374B','\U374C','\U374D','\U374E','\U374F','\U3750','\U3751','\U3752','\U3753','\U3754','\U3755','\U3756','\U3757','\U3758','\U3759','\U375A','\U375B','\U375C','\U375D','\U375E','\U375F','\U3760','\U3761','\U3762','\U3763','\U3764','\U3765','\U3766','\U3767','\U3768','\U3769','\U376A','\U376B','\U376C','\U376D','\U376E','\U376F','\U3770','\U3771','\U3772','\U3773','\U3774','\U3775','\U3776','\U3777','\U3778','\U3779','\U377A','\U377B','\U377C','\U377D','\U377E','\U377F','\U3780','\U3781','\U3782','\U3783','\U3784','\U3785','\U3786','\U3787','\U3788','\U3789','\U378A','\U378B','\U378C','\U378D','\U378E','\U378F','\U3790','\U3791','\U3792','\U3793','\U3794','\U3795','\U3796','\U3797','\U3798','\U3799','\U379A','\U379B','\U379C','\U379D','\U379E','\U379F','\U37A0','\U37A1','\U37A2','\U37A3','\U37A4','\U37A5','\U37A6','\U37A7','\U37A8','\U37A9','\U37AA','\U37AB','\U37AC','\U37AD','\U37AE','\U37AF','\U37B0','\U37B1','\U37B2','\U37B3','\U37B4','\U37B5','\U37B6','\U37B7','\U37B8','\U37B9','\U37BA','\U37BB','\U37BC','\U37BD','\U37BE','\U37BF','\U37C0','\U37C1','\U37C2','\U37C3','\U37C4','\U37C5','\U37C6','\U37C7','\U37C8','\U37C9','\U37CA','\U37CB','\U37CC','\U37CD','\U37CE','\U37CF','\U37D0','\U37D1','\U37D2','\U37D3','\U37D4','\U37D5','\U37D6','\U37D7','\U37D8','\U37D9','\U37DA','\U37DB','\U37DC','\U37DD','\U37DE','\U37DF','\U37E0','\U37E1','\U37E2','\U37E3','\U37E4','\U37E5','\U37E6','\U37E7','\U37E8','\U37E9','\U37EA','\U37EB','\U37EC','\U37ED','\U37EE','\U37EF','\U37F0','\U37F1','\U37F2','\U37F3','\U37F4','\U37F5','\U37F6','\U37F7','\U37F8','\U37F9','\U37FA','\U37FB','\U37FC','\U37FD','\U37FE','\U37FF','\U3800','\U3801','\U3802','\U3803','\U3804','\U3805','\U3806','\U3807','\U3808','\U3809','\U380A','\U380B','\U380C','\U380D','\U380E','\U380F','\U3810','\U3811','\U3812','\U3813','\U3814','\U3815','\U3816','\U3817','\U3818','\U3819','\U381A','\U381B','\U381C','\U381D','\U381E','\U381F','\U3820','\U3821','\U3822','\U3823','\U3824','\U3825','\U3826','\U3827','\U3828','\U3829','\U382A','\U382B','\U382C','\U382D','\U382E','\U382F','\U3830','\U3831','\U3832','\U3833','\U3834','\U3835','\U3836','\U3837','\U3838','\U3839','\U383A','\U383B','\U383C','\U383D','\U383E','\U383F','\U3840','\U3841','\U3842','\U3843','\U3844','\U3845','\U3846','\U3847','\U3848','\U3849','\U384A','\U384B','\U384C','\U384D','\U384E','\U384F','\U3850','\U3851','\U3852','\U3853','\U3854','\U3855','\U3856','\U3857','\U3858','\U3859','\U385A','\U385B','\U385C','\U385D','\U385E','\U385F','\U3860','\U3861','\U3862','\U3863','\U3864','\U3865','\U3866','\U3867','\U3868','\U3869','\U386A','\U386B','\U386C','\U386D','\U386E','\U386F','\U3870','\U3871','\U3872','\U3873','\U3874','\U3875','\U3876','\U3877','\U3878','\U3879','\U387A','\U387B','\U387C','\U387D','\U387E','\U387F','\U3880','\U3881','\U3882','\U3883','\U3884','\U3885','\U3886','\U3887','\U3888','\U3889','\U388A','\U388B','\U388C','\U388D','\U388E','\U388F','\U3890','\U3891','\U3892','\U3893','\U3894','\U3895','\U3896','\U3897','\U3898','\U3899','\U389A','\U389B','\U389C','\U389D','\U389E','\U389F','\U38A0','\U38A1','\U38A2','\U38A3','\U38A4','\U38A5','\U38A6','\U38A7','\U38A8','\U38A9','\U38AA','\U38AB','\U38AC','\U38AD','\U38AE','\U38AF','\U38B0','\U38B1','\U38B2','\U38B3','\U38B4','\U38B5','\U38B6','\U38B7','\U38B8','\U38B9','\U38BA','\U38BB','\U38BC','\U38BD','\U38BE','\U38BF','\U38C0','\U38C1','\U38C2','\U38C3','\U38C4','\U38C5','\U38C6','\U38C7','\U38C8','\U38C9','\U38CA','\U38CB','\U38CC','\U38CD','\U38CE','\U38CF','\U38D0','\U38D1','\U38D2','\U38D3','\U38D4','\U38D5','\U38D6','\U38D7','\U38D8','\U38D9','\U38DA','\U38DB','\U38DC','\U38DD','\U38DE','\U38DF','\U38E0','\U38E1','\U38E2','\U38E3','\U38E4','\U38E5','\U38E6','\U38E7','\U38E8','\U38E9','\U38EA','\U38EB','\U38EC','\U38ED','\U38EE','\U38EF','\U38F0','\U38F1','\U38F2','\U38F3','\U38F4','\U38F5','\U38F6','\U38F7','\U38F8','\U38F9','\U38FA','\U38FB','\U38FC','\U38FD','\U38FE','\U38FF','\U3900','\U3901','\U3902','\U3903','\U3904','\U3905','\U3906','\U3907','\U3908','\U3909','\U390A','\U390B','\U390C','\U390D','\U390E','\U390F','\U3910','\U3911','\U3912','\U3913','\U3914','\U3915','\U3916','\U3917','\U3918','\U3919','\U391A','\U391B','\U391C','\U391D','\U391E','\U391F','\U3920','\U3921','\U3922','\U3923','\U3924','\U3925','\U3926','\U3927','\U3928','\U3929','\U392A','\U392B','\U392C','\U392D','\U392E','\U392F','\U3930','\U3931','\U3932','\U3933','\U3934','\U3935','\U3936','\U3937','\U3938','\U3939','\U393A','\U393B','\U393C','\U393D','\U393E','\U393F','\U3940','\U3941','\U3942','\U3943','\U3944','\U3945','\U3946','\U3947','\U3948','\U3949','\U394A','\U394B','\U394C','\U394D','\U394E','\U394F','\U3950','\U3951','\U3952','\U3953','\U3954','\U3955','\U3956','\U3957','\U3958','\U3959','\U395A','\U395B','\U395C','\U395D','\U395E','\U395F','\U3960','\U3961','\U3962','\U3963','\U3964','\U3965','\U3966','\U3967','\U3968','\U3969','\U396A','\U396B','\U396C','\U396D','\U396E','\U396F','\U3970','\U3971','\U3972','\U3973','\U3974','\U3975','\U3976','\U3977','\U3978','\U3979','\U397A','\U397B','\U397C','\U397D','\U397E','\U397F','\U3980','\U3981','\U3982','\U3983','\U3984','\U3985','\U3986','\U3987','\U3988','\U3989','\U398A','\U398B','\U398C','\U398D','\U398E','\U398F','\U3990','\U3991','\U3992','\U3993','\U3994','\U3995','\U3996','\U3997','\U3998','\U3999','\U399A','\U399B','\U399C','\U399D','\U399E','\U399F','\U39A0','\U39A1','\U39A2','\U39A3','\U39A4','\U39A5','\U39A6','\U39A7','\U39A8','\U39A9','\U39AA','\U39AB','\U39AC','\U39AD','\U39AE','\U39AF','\U39B0','\U39B1','\U39B2','\U39B3','\U39B4','\U39B5','\U39B6','\U39B7','\U39B8','\U39B9','\U39BA','\U39BB','\U39BC','\U39BD','\U39BE','\U39BF','\U39C0','\U39C1','\U39C2','\U39C3','\U39C4','\U39C5','\U39C6','\U39C7','\U39C8','\U39C9','\U39CA','\U39CB','\U39CC','\U39CD','\U39CE','\U39CF','\U39D0','\U39D1','\U39D2','\U39D3','\U39D4','\U39D5','\U39D6','\U39D7','\U39D8','\U39D9','\U39DA','\U39DB','\U39DC','\U39DD','\U39DE','\U39DF','\U39E0','\U39E1','\U39E2','\U39E3','\U39E4','\U39E5','\U39E6','\U39E7','\U39E8','\U39E9','\U39EA','\U39EB','\U39EC','\U39ED','\U39EE','\U39EF','\U39F0','\U39F1','\U39F2','\U39F3','\U39F4','\U39F5','\U39F6','\U39F7','\U39F8','\U39F9','\U39FA','\U39FB','\U39FC','\U39FD','\U39FE','\U39FF','\U3A00','\U3A01','\U3A02','\U3A03','\U3A04','\U3A05','\U3A06','\U3A07','\U3A08','\U3A09','\U3A0A','\U3A0B','\U3A0C','\U3A0D','\U3A0E','\U3A0F','\U3A10','\U3A11','\U3A12','\U3A13','\U3A14','\U3A15','\U3A16','\U3A17','\U3A18','\U3A19','\U3A1A','\U3A1B','\U3A1C','\U3A1D','\U3A1E','\U3A1F','\U3A20','\U3A21','\U3A22','\U3A23','\U3A24','\U3A25','\U3A26','\U3A27','\U3A28','\U3A29','\U3A2A','\U3A2B','\U3A2C','\U3A2D','\U3A2E','\U3A2F','\U3A30','\U3A31','\U3A32','\U3A33','\U3A34','\U3A35','\U3A36','\U3A37','\U3A38','\U3A39','\U3A3A','\U3A3B','\U3A3C','\U3A3D','\U3A3E','\U3A3F','\U3A40','\U3A41','\U3A42','\U3A43','\U3A44','\U3A45','\U3A46','\U3A47','\U3A48','\U3A49','\U3A4A','\U3A4B','\U3A4C','\U3A4D','\U3A4E','\U3A4F','\U3A50','\U3A51','\U3A52','\U3A53','\U3A54','\U3A55','\U3A56','\U3A57','\U3A58','\U3A59','\U3A5A','\U3A5B','\U3A5C','\U3A5D','\U3A5E','\U3A5F','\U3A60','\U3A61','\U3A62','\U3A63','\U3A64','\U3A65','\U3A66','\U3A67','\U3A68','\U3A69','\U3A6A','\U3A6B','\U3A6C','\U3A6D','\U3A6E','\U3A6F','\U3A70','\U3A71','\U3A72','\U3A73','\U3A74','\U3A75','\U3A76','\U3A77','\U3A78','\U3A79','\U3A7A','\U3A7B','\U3A7C','\U3A7D','\U3A7E','\U3A7F','\U3A80','\U3A81','\U3A82','\U3A83','\U3A84','\U3A85','\U3A86','\U3A87','\U3A88','\U3A89','\U3A8A','\U3A8B','\U3A8C','\U3A8D','\U3A8E','\U3A8F','\U3A90','\U3A91','\U3A92','\U3A93','\U3A94','\U3A95','\U3A96','\U3A97','\U3A98','\U3A99','\U3A9A','\U3A9B','\U3A9C','\U3A9D','\U3A9E','\U3A9F','\U3AA0','\U3AA1','\U3AA2','\U3AA3','\U3AA4','\U3AA5','\U3AA6','\U3AA7','\U3AA8','\U3AA9','\U3AAA','\U3AAB','\U3AAC','\U3AAD','\U3AAE','\U3AAF','\U3AB0','\U3AB1','\U3AB2','\U3AB3','\U3AB4','\U3AB5','\U3AB6','\U3AB7','\U3AB8','\U3AB9','\U3ABA','\U3ABB','\U3ABC','\U3ABD','\U3ABE','\U3ABF','\U3AC0','\U3AC1','\U3AC2','\U3AC3','\U3AC4','\U3AC5','\U3AC6','\U3AC7','\U3AC8','\U3AC9','\U3ACA','\U3ACB','\U3ACC','\U3ACD','\U3ACE','\U3ACF','\U3AD0','\U3AD1','\U3AD2','\U3AD3','\U3AD4','\U3AD5','\U3AD6','\U3AD7','\U3AD8','\U3AD9','\U3ADA','\U3ADB','\U3ADC','\U3ADD','\U3ADE','\U3ADF','\U3AE0','\U3AE1','\U3AE2','\U3AE3','\U3AE4','\U3AE5','\U3AE6','\U3AE7','\U3AE8','\U3AE9','\U3AEA','\U3AEB','\U3AEC','\U3AED','\U3AEE','\U3AEF','\U3AF0','\U3AF1','\U3AF2','\U3AF3','\U3AF4','\U3AF5','\U3AF6','\U3AF7','\U3AF8','\U3AF9','\U3AFA','\U3AFB','\U3AFC','\U3AFD','\U3AFE','\U3AFF','\U3B00','\U3B01','\U3B02','\U3B03','\U3B04','\U3B05','\U3B06','\U3B07','\U3B08','\U3B09','\U3B0A','\U3B0B','\U3B0C','\U3B0D','\U3B0E','\U3B0F','\U3B10','\U3B11','\U3B12','\U3B13','\U3B14','\U3B15','\U3B16','\U3B17','\U3B18','\U3B19','\U3B1A','\U3B1B','\U3B1C','\U3B1D','\U3B1E','\U3B1F','\U3B20','\U3B21','\U3B22','\U3B23','\U3B24','\U3B25','\U3B26','\U3B27','\U3B28','\U3B29','\U3B2A','\U3B2B','\U3B2C','\U3B2D','\U3B2E','\U3B2F','\U3B30','\U3B31','\U3B32','\U3B33','\U3B34','\U3B35','\U3B36','\U3B37','\U3B38','\U3B39','\U3B3A','\U3B3B','\U3B3C','\U3B3D','\U3B3E','\U3B3F','\U3B40','\U3B41','\U3B42','\U3B43','\U3B44','\U3B45','\U3B46','\U3B47','\U3B48','\U3B49','\U3B4A','\U3B4B','\U3B4C','\U3B4D','\U3B4E','\U3B4F','\U3B50','\U3B51','\U3B52','\U3B53','\U3B54','\U3B55','\U3B56','\U3B57','\U3B58','\U3B59','\U3B5A','\U3B5B','\U3B5C','\U3B5D','\U3B5E','\U3B5F','\U3B60','\U3B61','\U3B62','\U3B63','\U3B64','\U3B65','\U3B66','\U3B67','\U3B68','\U3B69','\U3B6A','\U3B6B','\U3B6C','\U3B6D','\U3B6E','\U3B6F','\U3B70','\U3B71','\U3B72','\U3B73','\U3B74','\U3B75','\U3B76','\U3B77','\U3B78','\U3B79','\U3B7A','\U3B7B','\U3B7C','\U3B7D','\U3B7E','\U3B7F','\U3B80','\U3B81','\U3B82','\U3B83','\U3B84','\U3B85','\U3B86','\U3B87','\U3B88','\U3B89','\U3B8A','\U3B8B','\U3B8C','\U3B8D','\U3B8E','\U3B8F','\U3B90','\U3B91','\U3B92','\U3B93','\U3B94','\U3B95','\U3B96','\U3B97','\U3B98','\U3B99','\U3B9A','\U3B9B','\U3B9C','\U3B9D','\U3B9E','\U3B9F','\U3BA0','\U3BA1','\U3BA2','\U3BA3','\U3BA4','\U3BA5','\U3BA6','\U3BA7','\U3BA8','\U3BA9','\U3BAA','\U3BAB','\U3BAC','\U3BAD','\U3BAE','\U3BAF','\U3BB0','\U3BB1','\U3BB2','\U3BB3','\U3BB4','\U3BB5','\U3BB6','\U3BB7','\U3BB8','\U3BB9','\U3BBA','\U3BBB','\U3BBC','\U3BBD','\U3BBE','\U3BBF','\U3BC0','\U3BC1','\U3BC2','\U3BC3','\U3BC4','\U3BC5','\U3BC6','\U3BC7','\U3BC8','\U3BC9','\U3BCA','\U3BCB','\U3BCC','\U3BCD','\U3BCE','\U3BCF','\U3BD0','\U3BD1','\U3BD2','\U3BD3','\U3BD4','\U3BD5','\U3BD6','\U3BD7','\U3BD8','\U3BD9','\U3BDA','\U3BDB','\U3BDC','\U3BDD','\U3BDE','\U3BDF','\U3BE0','\U3BE1','\U3BE2','\U3BE3','\U3BE4','\U3BE5','\U3BE6','\U3BE7','\U3BE8','\U3BE9','\U3BEA','\U3BEB','\U3BEC','\U3BED','\U3BEE','\U3BEF','\U3BF0','\U3BF1','\U3BF2','\U3BF3','\U3BF4','\U3BF5','\U3BF6','\U3BF7','\U3BF8','\U3BF9','\U3BFA','\U3BFB','\U3BFC','\U3BFD','\U3BFE','\U3BFF','\U3C00','\U3C01','\U3C02','\U3C03','\U3C04','\U3C05','\U3C06','\U3C07','\U3C08','\U3C09','\U3C0A','\U3C0B','\U3C0C','\U3C0D','\U3C0E','\U3C0F','\U3C10','\U3C11','\U3C12','\U3C13','\U3C14','\U3C15','\U3C16','\U3C17','\U3C18','\U3C19','\U3C1A','\U3C1B','\U3C1C','\U3C1D','\U3C1E','\U3C1F','\U3C20','\U3C21','\U3C22','\U3C23','\U3C24','\U3C25','\U3C26','\U3C27','\U3C28','\U3C29','\U3C2A','\U3C2B','\U3C2C','\U3C2D','\U3C2E','\U3C2F','\U3C30','\U3C31','\U3C32','\U3C33','\U3C34','\U3C35','\U3C36','\U3C37','\U3C38','\U3C39','\U3C3A','\U3C3B','\U3C3C','\U3C3D','\U3C3E','\U3C3F','\U3C40','\U3C41','\U3C42','\U3C43','\U3C44','\U3C45','\U3C46','\U3C47','\U3C48','\U3C49','\U3C4A','\U3C4B','\U3C4C','\U3C4D','\U3C4E','\U3C4F','\U3C50','\U3C51','\U3C52','\U3C53','\U3C54','\U3C55','\U3C56','\U3C57','\U3C58','\U3C59','\U3C5A','\U3C5B','\U3C5C','\U3C5D','\U3C5E','\U3C5F','\U3C60','\U3C61','\U3C62','\U3C63','\U3C64','\U3C65','\U3C66','\U3C67','\U3C68','\U3C69','\U3C6A','\U3C6B','\U3C6C','\U3C6D','\U3C6E','\U3C6F','\U3C70','\U3C71','\U3C72','\U3C73','\U3C74','\U3C75','\U3C76','\U3C77','\U3C78','\U3C79','\U3C7A','\U3C7B','\U3C7C','\U3C7D','\U3C7E','\U3C7F','\U3C80','\U3C81','\U3C82','\U3C83','\U3C84','\U3C85','\U3C86','\U3C87','\U3C88','\U3C89','\U3C8A','\U3C8B','\U3C8C','\U3C8D','\U3C8E','\U3C8F','\U3C90','\U3C91','\U3C92','\U3C93','\U3C94','\U3C95','\U3C96','\U3C97','\U3C98','\U3C99','\U3C9A','\U3C9B','\U3C9C','\U3C9D','\U3C9E','\U3C9F','\U3CA0','\U3CA1','\U3CA2','\U3CA3','\U3CA4','\U3CA5','\U3CA6','\U3CA7','\U3CA8','\U3CA9','\U3CAA','\U3CAB','\U3CAC','\U3CAD','\U3CAE','\U3CAF','\U3CB0','\U3CB1','\U3CB2','\U3CB3','\U3CB4','\U3CB5','\U3CB6','\U3CB7','\U3CB8','\U3CB9','\U3CBA','\U3CBB','\U3CBC','\U3CBD','\U3CBE','\U3CBF','\U3CC0','\U3CC1','\U3CC2','\U3CC3','\U3CC4','\U3CC5','\U3CC6','\U3CC7','\U3CC8','\U3CC9','\U3CCA','\U3CCB','\U3CCC','\U3CCD','\U3CCE','\U3CCF','\U3CD0','\U3CD1','\U3CD2','\U3CD3','\U3CD4','\U3CD5','\U3CD6','\U3CD7','\U3CD8','\U3CD9','\U3CDA','\U3CDB','\U3CDC','\U3CDD','\U3CDE','\U3CDF','\U3CE0','\U3CE1','\U3CE2','\U3CE3','\U3CE4','\U3CE5','\U3CE6','\U3CE7','\U3CE8','\U3CE9','\U3CEA','\U3CEB','\U3CEC','\U3CED','\U3CEE','\U3CEF','\U3CF0','\U3CF1','\U3CF2','\U3CF3','\U3CF4','\U3CF5','\U3CF6','\U3CF7','\U3CF8','\U3CF9','\U3CFA','\U3CFB','\U3CFC','\U3CFD','\U3CFE','\U3CFF','\U3D00','\U3D01','\U3D02','\U3D03','\U3D04','\U3D05','\U3D06','\U3D07','\U3D08','\U3D09','\U3D0A','\U3D0B','\U3D0C','\U3D0D','\U3D0E','\U3D0F','\U3D10','\U3D11','\U3D12','\U3D13','\U3D14','\U3D15','\U3D16','\U3D17','\U3D18','\U3D19','\U3D1A','\U3D1B','\U3D1C','\U3D1D','\U3D1E','\U3D1F','\U3D20','\U3D21','\U3D22','\U3D23','\U3D24','\U3D25','\U3D26','\U3D27','\U3D28','\U3D29','\U3D2A','\U3D2B','\U3D2C','\U3D2D','\U3D2E','\U3D2F','\U3D30','\U3D31','\U3D32','\U3D33','\U3D34','\U3D35','\U3D36','\U3D37','\U3D38','\U3D39','\U3D3A','\U3D3B','\U3D3C','\U3D3D','\U3D3E','\U3D3F','\U3D40','\U3D41','\U3D42','\U3D43','\U3D44','\U3D45','\U3D46','\U3D47','\U3D48','\U3D49','\U3D4A','\U3D4B','\U3D4C','\U3D4D','\U3D4E','\U3D4F','\U3D50','\U3D51','\U3D52','\U3D53','\U3D54','\U3D55','\U3D56','\U3D57','\U3D58','\U3D59','\U3D5A','\U3D5B','\U3D5C','\U3D5D','\U3D5E','\U3D5F','\U3D60','\U3D61','\U3D62','\U3D63','\U3D64','\U3D65','\U3D66','\U3D67','\U3D68','\U3D69','\U3D6A','\U3D6B','\U3D6C','\U3D6D','\U3D6E','\U3D6F','\U3D70','\U3D71','\U3D72','\U3D73','\U3D74','\U3D75','\U3D76','\U3D77','\U3D78','\U3D79','\U3D7A','\U3D7B','\U3D7C','\U3D7D','\U3D7E','\U3D7F','\U3D80','\U3D81','\U3D82','\U3D83','\U3D84','\U3D85','\U3D86','\U3D87','\U3D88','\U3D89','\U3D8A','\U3D8B','\U3D8C','\U3D8D','\U3D8E','\U3D8F','\U3D90','\U3D91','\U3D92','\U3D93','\U3D94','\U3D95','\U3D96','\U3D97','\U3D98','\U3D99','\U3D9A','\U3D9B','\U3D9C','\U3D9D','\U3D9E','\U3D9F','\U3DA0','\U3DA1','\U3DA2','\U3DA3','\U3DA4','\U3DA5','\U3DA6','\U3DA7','\U3DA8','\U3DA9','\U3DAA','\U3DAB','\U3DAC','\U3DAD','\U3DAE','\U3DAF','\U3DB0','\U3DB1','\U3DB2','\U3DB3','\U3DB4','\U3DB5','\U3DB6','\U3DB7','\U3DB8','\U3DB9','\U3DBA','\U3DBB','\U3DBC','\U3DBD','\U3DBE','\U3DBF','\U3DC0','\U3DC1','\U3DC2','\U3DC3','\U3DC4','\U3DC5','\U3DC6','\U3DC7','\U3DC8','\U3DC9','\U3DCA','\U3DCB','\U3DCC','\U3DCD','\U3DCE','\U3DCF','\U3DD0','\U3DD1','\U3DD2','\U3DD3','\U3DD4','\U3DD5','\U3DD6','\U3DD7','\U3DD8','\U3DD9','\U3DDA','\U3DDB','\U3DDC','\U3DDD','\U3DDE','\U3DDF','\U3DE0','\U3DE1','\U3DE2','\U3DE3','\U3DE4','\U3DE5','\U3DE6','\U3DE7','\U3DE8','\U3DE9','\U3DEA','\U3DEB','\U3DEC','\U3DED','\U3DEE','\U3DEF','\U3DF0','\U3DF1','\U3DF2','\U3DF3','\U3DF4','\U3DF5','\U3DF6','\U3DF7','\U3DF8','\U3DF9','\U3DFA','\U3DFB','\U3DFC','\U3DFD','\U3DFE','\U3DFF','\U3E00','\U3E01','\U3E02','\U3E03','\U3E04','\U3E05','\U3E06','\U3E07','\U3E08','\U3E09','\U3E0A','\U3E0B','\U3E0C','\U3E0D','\U3E0E','\U3E0F','\U3E10','\U3E11','\U3E12','\U3E13','\U3E14','\U3E15','\U3E16','\U3E17','\U3E18','\U3E19','\U3E1A','\U3E1B','\U3E1C','\U3E1D','\U3E1E','\U3E1F','\U3E20','\U3E21','\U3E22','\U3E23','\U3E24','\U3E25','\U3E26','\U3E27','\U3E28','\U3E29','\U3E2A','\U3E2B','\U3E2C','\U3E2D','\U3E2E','\U3E2F','\U3E30','\U3E31','\U3E32','\U3E33','\U3E34','\U3E35','\U3E36','\U3E37','\U3E38','\U3E39','\U3E3A','\U3E3B','\U3E3C','\U3E3D','\U3E3E','\U3E3F','\U3E40','\U3E41','\U3E42','\U3E43','\U3E44','\U3E45','\U3E46','\U3E47','\U3E48','\U3E49','\U3E4A','\U3E4B','\U3E4C','\U3E4D','\U3E4E','\U3E4F','\U3E50','\U3E51','\U3E52','\U3E53','\U3E54','\U3E55','\U3E56','\U3E57','\U3E58','\U3E59','\U3E5A','\U3E5B','\U3E5C','\U3E5D','\U3E5E','\U3E5F','\U3E60','\U3E61','\U3E62','\U3E63','\U3E64','\U3E65','\U3E66','\U3E67','\U3E68','\U3E69','\U3E6A','\U3E6B','\U3E6C','\U3E6D','\U3E6E','\U3E6F','\U3E70','\U3E71','\U3E72','\U3E73','\U3E74','\U3E75','\U3E76','\U3E77','\U3E78','\U3E79','\U3E7A','\U3E7B','\U3E7C','\U3E7D','\U3E7E','\U3E7F','\U3E80','\U3E81','\U3E82','\U3E83','\U3E84','\U3E85','\U3E86','\U3E87','\U3E88','\U3E89','\U3E8A','\U3E8B','\U3E8C','\U3E8D','\U3E8E','\U3E8F','\U3E90','\U3E91','\U3E92','\U3E93','\U3E94','\U3E95','\U3E96','\U3E97','\U3E98','\U3E99','\U3E9A','\U3E9B','\U3E9C','\U3E9D','\U3E9E','\U3E9F','\U3EA0','\U3EA1','\U3EA2','\U3EA3','\U3EA4','\U3EA5','\U3EA6','\U3EA7','\U3EA8','\U3EA9','\U3EAA','\U3EAB','\U3EAC','\U3EAD','\U3EAE','\U3EAF','\U3EB0','\U3EB1','\U3EB2','\U3EB3','\U3EB4','\U3EB5','\U3EB6','\U3EB7','\U3EB8','\U3EB9','\U3EBA','\U3EBB','\U3EBC','\U3EBD','\U3EBE','\U3EBF','\U3EC0','\U3EC1','\U3EC2','\U3EC3','\U3EC4','\U3EC5','\U3EC6','\U3EC7','\U3EC8','\U3EC9','\U3ECA','\U3ECB','\U3ECC','\U3ECD','\U3ECE','\U3ECF','\U3ED0','\U3ED1','\U3ED2','\U3ED3','\U3ED4','\U3ED5','\U3ED6','\U3ED7','\U3ED8','\U3ED9','\U3EDA','\U3EDB','\U3EDC','\U3EDD','\U3EDE','\U3EDF','\U3EE0','\U3EE1','\U3EE2','\U3EE3','\U3EE4','\U3EE5','\U3EE6','\U3EE7','\U3EE8','\U3EE9','\U3EEA','\U3EEB','\U3EEC','\U3EED','\U3EEE','\U3EEF','\U3EF0','\U3EF1','\U3EF2','\U3EF3','\U3EF4','\U3EF5','\U3EF6','\U3EF7','\U3EF8','\U3EF9','\U3EFA','\U3EFB','\U3EFC','\U3EFD','\U3EFE','\U3EFF','\U3F00','\U3F01','\U3F02','\U3F03','\U3F04','\U3F05','\U3F06','\U3F07','\U3F08','\U3F09','\U3F0A','\U3F0B','\U3F0C','\U3F0D','\U3F0E','\U3F0F','\U3F10','\U3F11','\U3F12','\U3F13','\U3F14','\U3F15','\U3F16','\U3F17','\U3F18','\U3F19','\U3F1A','\U3F1B','\U3F1C','\U3F1D','\U3F1E','\U3F1F','\U3F20','\U3F21','\U3F22','\U3F23','\U3F24','\U3F25','\U3F26','\U3F27','\U3F28','\U3F29','\U3F2A','\U3F2B','\U3F2C','\U3F2D','\U3F2E','\U3F2F','\U3F30','\U3F31','\U3F32','\U3F33','\U3F34','\U3F35','\U3F36','\U3F37','\U3F38','\U3F39','\U3F3A','\U3F3B','\U3F3C','\U3F3D','\U3F3E','\U3F3F','\U3F40','\U3F41','\U3F42','\U3F43','\U3F44','\U3F45','\U3F46','\U3F47','\U3F48','\U3F49','\U3F4A','\U3F4B','\U3F4C','\U3F4D','\U3F4E','\U3F4F','\U3F50','\U3F51','\U3F52','\U3F53','\U3F54','\U3F55','\U3F56','\U3F57','\U3F58','\U3F59','\U3F5A','\U3F5B','\U3F5C','\U3F5D','\U3F5E','\U3F5F','\U3F60','\U3F61','\U3F62','\U3F63','\U3F64','\U3F65','\U3F66','\U3F67','\U3F68','\U3F69','\U3F6A','\U3F6B','\U3F6C','\U3F6D','\U3F6E','\U3F6F','\U3F70','\U3F71','\U3F72','\U3F73','\U3F74','\U3F75','\U3F76','\U3F77','\U3F78','\U3F79','\U3F7A','\U3F7B','\U3F7C','\U3F7D','\U3F7E','\U3F7F','\U3F80','\U3F81','\U3F82','\U3F83','\U3F84','\U3F85','\U3F86','\U3F87','\U3F88','\U3F89','\U3F8A','\U3F8B','\U3F8C','\U3F8D','\U3F8E','\U3F8F','\U3F90','\U3F91','\U3F92','\U3F93','\U3F94','\U3F95','\U3F96','\U3F97','\U3F98','\U3F99','\U3F9A','\U3F9B','\U3F9C','\U3F9D','\U3F9E','\U3F9F','\U3FA0','\U3FA1','\U3FA2','\U3FA3','\U3FA4','\U3FA5','\U3FA6','\U3FA7','\U3FA8','\U3FA9','\U3FAA','\U3FAB','\U3FAC','\U3FAD','\U3FAE','\U3FAF','\U3FB0','\U3FB1','\U3FB2','\U3FB3','\U3FB4','\U3FB5','\U3FB6','\U3FB7','\U3FB8','\U3FB9','\U3FBA','\U3FBB','\U3FBC','\U3FBD','\U3FBE','\U3FBF','\U3FC0','\U3FC1','\U3FC2','\U3FC3','\U3FC4','\U3FC5','\U3FC6','\U3FC7','\U3FC8','\U3FC9','\U3FCA','\U3FCB','\U3FCC','\U3FCD','\U3FCE','\U3FCF','\U3FD0','\U3FD1','\U3FD2','\U3FD3','\U3FD4','\U3FD5','\U3FD6','\U3FD7','\U3FD8','\U3FD9','\U3FDA','\U3FDB','\U3FDC','\U3FDD','\U3FDE','\U3FDF','\U3FE0','\U3FE1','\U3FE2','\U3FE3','\U3FE4','\U3FE5','\U3FE6','\U3FE7','\U3FE8','\U3FE9','\U3FEA','\U3FEB','\U3FEC','\U3FED','\U3FEE','\U3FEF','\U3FF0','\U3FF1','\U3FF2','\U3FF3','\U3FF4','\U3FF5','\U3FF6','\U3FF7','\U3FF8','\U3FF9','\U3FFA','\U3FFB','\U3FFC','\U3FFD','\U3FFE','\U3FFF','\U4000','\U4001','\U4002','\U4003','\U4004','\U4005','\U4006','\U4007','\U4008','\U4009','\U400A','\U400B','\U400C','\U400D','\U400E','\U400F','\U4010','\U4011','\U4012','\U4013','\U4014','\U4015','\U4016','\U4017','\U4018','\U4019','\U401A','\U401B','\U401C','\U401D','\U401E','\U401F','\U4020','\U4021','\U4022','\U4023','\U4024','\U4025','\U4026','\U4027','\U4028','\U4029','\U402A','\U402B','\U402C','\U402D','\U402E','\U402F','\U4030','\U4031','\U4032','\U4033','\U4034','\U4035','\U4036','\U4037','\U4038','\U4039','\U403A','\U403B','\U403C','\U403D','\U403E','\U403F','\U4040','\U4041','\U4042','\U4043','\U4044','\U4045','\U4046','\U4047','\U4048','\U4049','\U404A','\U404B','\U404C','\U404D','\U404E','\U404F','\U4050','\U4051','\U4052','\U4053','\U4054','\U4055','\U4056','\U4057','\U4058','\U4059','\U405A','\U405B','\U405C','\U405D','\U405E','\U405F','\U4060','\U4061','\U4062','\U4063','\U4064','\U4065','\U4066','\U4067','\U4068','\U4069','\U406A','\U406B','\U406C','\U406D','\U406E','\U406F','\U4070','\U4071','\U4072','\U4073','\U4074','\U4075','\U4076','\U4077','\U4078','\U4079','\U407A','\U407B','\U407C','\U407D','\U407E','\U407F','\U4080','\U4081','\U4082','\U4083','\U4084','\U4085','\U4086','\U4087','\U4088','\U4089','\U408A','\U408B','\U408C','\U408D','\U408E','\U408F','\U4090','\U4091','\U4092','\U4093','\U4094','\U4095','\U4096','\U4097','\U4098','\U4099','\U409A','\U409B','\U409C','\U409D','\U409E','\U409F','\U40A0','\U40A1','\U40A2','\U40A3','\U40A4','\U40A5','\U40A6','\U40A7','\U40A8','\U40A9','\U40AA','\U40AB','\U40AC','\U40AD','\U40AE','\U40AF','\U40B0','\U40B1','\U40B2','\U40B3','\U40B4','\U40B5','\U40B6','\U40B7','\U40B8','\U40B9','\U40BA','\U40BB','\U40BC','\U40BD','\U40BE','\U40BF','\U40C0','\U40C1','\U40C2','\U40C3','\U40C4','\U40C5','\U40C6','\U40C7','\U40C8','\U40C9','\U40CA','\U40CB','\U40CC','\U40CD','\U40CE','\U40CF','\U40D0','\U40D1','\U40D2','\U40D3','\U40D4','\U40D5','\U40D6','\U40D7','\U40D8','\U40D9','\U40DA','\U40DB','\U40DC','\U40DD','\U40DE','\U40DF','\U40E0','\U40E1','\U40E2','\U40E3','\U40E4','\U40E5','\U40E6','\U40E7','\U40E8','\U40E9','\U40EA','\U40EB','\U40EC','\U40ED','\U40EE','\U40EF','\U40F0','\U40F1','\U40F2','\U40F3','\U40F4','\U40F5','\U40F6','\U40F7','\U40F8','\U40F9','\U40FA','\U40FB','\U40FC','\U40FD','\U40FE','\U40FF','\U4100','\U4101','\U4102','\U4103','\U4104','\U4105','\U4106','\U4107','\U4108','\U4109','\U410A','\U410B','\U410C','\U410D','\U410E','\U410F','\U4110','\U4111','\U4112','\U4113','\U4114','\U4115','\U4116','\U4117','\U4118','\U4119','\U411A','\U411B','\U411C','\U411D','\U411E','\U411F','\U4120','\U4121','\U4122','\U4123','\U4124','\U4125','\U4126','\U4127','\U4128','\U4129','\U412A','\U412B','\U412C','\U412D','\U412E','\U412F','\U4130','\U4131','\U4132','\U4133','\U4134','\U4135','\U4136','\U4137','\U4138','\U4139','\U413A','\U413B','\U413C','\U413D','\U413E','\U413F','\U4140','\U4141','\U4142','\U4143','\U4144','\U4145','\U4146','\U4147','\U4148','\U4149','\U414A','\U414B','\U414C','\U414D','\U414E','\U414F','\U4150','\U4151','\U4152','\U4153','\U4154','\U4155','\U4156','\U4157','\U4158','\U4159','\U415A','\U415B','\U415C','\U415D','\U415E','\U415F','\U4160','\U4161','\U4162','\U4163','\U4164','\U4165','\U4166','\U4167','\U4168','\U4169','\U416A','\U416B','\U416C','\U416D','\U416E','\U416F','\U4170','\U4171','\U4172','\U4173','\U4174','\U4175','\U4176','\U4177','\U4178','\U4179','\U417A','\U417B','\U417C','\U417D','\U417E','\U417F','\U4180','\U4181','\U4182','\U4183','\U4184','\U4185','\U4186','\U4187','\U4188','\U4189','\U418A','\U418B','\U418C','\U418D','\U418E','\U418F','\U4190','\U4191','\U4192','\U4193','\U4194','\U4195','\U4196','\U4197','\U4198','\U4199','\U419A','\U419B','\U419C','\U419D','\U419E','\U419F','\U41A0','\U41A1','\U41A2','\U41A3','\U41A4','\U41A5','\U41A6','\U41A7','\U41A8','\U41A9','\U41AA','\U41AB','\U41AC','\U41AD','\U41AE','\U41AF','\U41B0','\U41B1','\U41B2','\U41B3','\U41B4','\U41B5','\U41B6','\U41B7','\U41B8','\U41B9','\U41BA','\U41BB','\U41BC','\U41BD','\U41BE','\U41BF','\U41C0','\U41C1','\U41C2','\U41C3','\U41C4','\U41C5','\U41C6','\U41C7','\U41C8','\U41C9','\U41CA','\U41CB','\U41CC','\U41CD','\U41CE','\U41CF','\U41D0','\U41D1','\U41D2','\U41D3','\U41D4','\U41D5','\U41D6','\U41D7','\U41D8','\U41D9','\U41DA','\U41DB','\U41DC','\U41DD','\U41DE','\U41DF','\U41E0','\U41E1','\U41E2','\U41E3','\U41E4','\U41E5','\U41E6','\U41E7','\U41E8','\U41E9','\U41EA','\U41EB','\U41EC','\U41ED','\U41EE','\U41EF','\U41F0','\U41F1','\U41F2','\U41F3','\U41F4','\U41F5','\U41F6','\U41F7','\U41F8','\U41F9','\U41FA','\U41FB','\U41FC','\U41FD','\U41FE','\U41FF','\U4200','\U4201','\U4202','\U4203','\U4204','\U4205','\U4206','\U4207','\U4208','\U4209','\U420A','\U420B','\U420C','\U420D','\U420E','\U420F','\U4210','\U4211','\U4212','\U4213','\U4214','\U4215','\U4216','\U4217','\U4218','\U4219','\U421A','\U421B','\U421C','\U421D','\U421E','\U421F','\U4220','\U4221','\U4222','\U4223','\U4224','\U4225','\U4226','\U4227','\U4228','\U4229','\U422A','\U422B','\U422C','\U422D','\U422E','\U422F','\U4230','\U4231','\U4232','\U4233','\U4234','\U4235','\U4236','\U4237','\U4238','\U4239','\U423A','\U423B','\U423C','\U423D','\U423E','\U423F','\U4240','\U4241','\U4242','\U4243','\U4244','\U4245','\U4246','\U4247','\U4248','\U4249','\U424A','\U424B','\U424C','\U424D','\U424E','\U424F','\U4250','\U4251','\U4252','\U4253','\U4254','\U4255','\U4256','\U4257','\U4258','\U4259','\U425A','\U425B','\U425C','\U425D','\U425E','\U425F','\U4260','\U4261','\U4262','\U4263','\U4264','\U4265','\U4266','\U4267','\U4268','\U4269','\U426A','\U426B','\U426C','\U426D','\U426E','\U426F','\U4270','\U4271','\U4272','\U4273','\U4274','\U4275','\U4276','\U4277','\U4278','\U4279','\U427A','\U427B','\U427C','\U427D','\U427E','\U427F','\U4280','\U4281','\U4282','\U4283','\U4284','\U4285','\U4286','\U4287','\U4288','\U4289','\U428A','\U428B','\U428C','\U428D','\U428E','\U428F','\U4290','\U4291','\U4292','\U4293','\U4294','\U4295','\U4296','\U4297','\U4298','\U4299','\U429A','\U429B','\U429C','\U429D','\U429E','\U429F','\U42A0','\U42A1','\U42A2','\U42A3','\U42A4','\U42A5','\U42A6','\U42A7','\U42A8','\U42A9','\U42AA','\U42AB','\U42AC','\U42AD','\U42AE','\U42AF','\U42B0','\U42B1','\U42B2','\U42B3','\U42B4','\U42B5','\U42B6','\U42B7','\U42B8','\U42B9','\U42BA','\U42BB','\U42BC','\U42BD','\U42BE','\U42BF','\U42C0','\U42C1','\U42C2','\U42C3','\U42C4','\U42C5','\U42C6','\U42C7','\U42C8','\U42C9','\U42CA','\U42CB','\U42CC','\U42CD','\U42CE','\U42CF','\U42D0','\U42D1','\U42D2','\U42D3','\U42D4','\U42D5','\U42D6','\U42D7','\U42D8','\U42D9','\U42DA','\U42DB','\U42DC','\U42DD','\U42DE','\U42DF','\U42E0','\U42E1','\U42E2','\U42E3','\U42E4','\U42E5','\U42E6','\U42E7','\U42E8','\U42E9','\U42EA','\U42EB','\U42EC','\U42ED','\U42EE','\U42EF','\U42F0','\U42F1','\U42F2','\U42F3','\U42F4','\U42F5','\U42F6','\U42F7','\U42F8','\U42F9','\U42FA','\U42FB','\U42FC','\U42FD','\U42FE','\U42FF','\U4300','\U4301','\U4302','\U4303','\U4304','\U4305','\U4306','\U4307','\U4308','\U4309','\U430A','\U430B','\U430C','\U430D','\U430E','\U430F','\U4310','\U4311','\U4312','\U4313','\U4314','\U4315','\U4316','\U4317','\U4318','\U4319','\U431A','\U431B','\U431C','\U431D','\U431E','\U431F','\U4320','\U4321','\U4322','\U4323','\U4324','\U4325','\U4326','\U4327','\U4328','\U4329','\U432A','\U432B','\U432C','\U432D','\U432E','\U432F','\U4330','\U4331','\U4332','\U4333','\U4334','\U4335','\U4336','\U4337','\U4338','\U4339','\U433A','\U433B','\U433C','\U433D','\U433E','\U433F','\U4340','\U4341','\U4342','\U4343','\U4344','\U4345','\U4346','\U4347','\U4348','\U4349','\U434A','\U434B','\U434C','\U434D','\U434E','\U434F','\U4350','\U4351','\U4352','\U4353','\U4354','\U4355','\U4356','\U4357','\U4358','\U4359','\U435A','\U435B','\U435C','\U435D','\U435E','\U435F','\U4360','\U4361','\U4362','\U4363','\U4364','\U4365','\U4366','\U4367','\U4368','\U4369','\U436A','\U436B','\U436C','\U436D','\U436E','\U436F','\U4370','\U4371','\U4372','\U4373','\U4374','\U4375','\U4376','\U4377','\U4378','\U4379','\U437A','\U437B','\U437C','\U437D','\U437E','\U437F','\U4380','\U4381','\U4382','\U4383','\U4384','\U4385','\U4386','\U4387','\U4388','\U4389','\U438A','\U438B','\U438C','\U438D','\U438E','\U438F','\U4390','\U4391','\U4392','\U4393','\U4394','\U4395','\U4396','\U4397','\U4398','\U4399','\U439A','\U439B','\U439C','\U439D','\U439E','\U439F','\U43A0','\U43A1','\U43A2','\U43A3','\U43A4','\U43A5','\U43A6','\U43A7','\U43A8','\U43A9','\U43AA','\U43AB','\U43AC','\U43AD','\U43AE','\U43AF','\U43B0','\U43B1','\U43B2','\U43B3','\U43B4','\U43B5','\U43B6','\U43B7','\U43B8','\U43B9','\U43BA','\U43BB','\U43BC','\U43BD','\U43BE','\U43BF','\U43C0','\U43C1','\U43C2','\U43C3','\U43C4','\U43C5','\U43C6','\U43C7','\U43C8','\U43C9','\U43CA','\U43CB','\U43CC','\U43CD','\U43CE','\U43CF','\U43D0','\U43D1','\U43D2','\U43D3','\U43D4','\U43D5','\U43D6','\U43D7','\U43D8','\U43D9','\U43DA','\U43DB','\U43DC','\U43DD','\U43DE','\U43DF','\U43E0','\U43E1','\U43E2','\U43E3','\U43E4','\U43E5','\U43E6','\U43E7','\U43E8','\U43E9','\U43EA','\U43EB','\U43EC','\U43ED','\U43EE','\U43EF','\U43F0','\U43F1','\U43F2','\U43F3','\U43F4','\U43F5','\U43F6','\U43F7','\U43F8','\U43F9','\U43FA','\U43FB','\U43FC','\U43FD','\U43FE','\U43FF','\U4400','\U4401','\U4402','\U4403','\U4404','\U4405','\U4406','\U4407','\U4408','\U4409','\U440A','\U440B','\U440C','\U440D','\U440E','\U440F','\U4410','\U4411','\U4412','\U4413','\U4414','\U4415','\U4416','\U4417','\U4418','\U4419','\U441A','\U441B','\U441C','\U441D','\U441E','\U441F','\U4420','\U4421','\U4422','\U4423','\U4424','\U4425','\U4426','\U4427','\U4428','\U4429','\U442A','\U442B','\U442C','\U442D','\U442E','\U442F','\U4430','\U4431','\U4432','\U4433','\U4434','\U4435','\U4436','\U4437','\U4438','\U4439','\U443A','\U443B','\U443C','\U443D','\U443E','\U443F','\U4440','\U4441','\U4442','\U4443','\U4444','\U4445','\U4446','\U4447','\U4448','\U4449','\U444A','\U444B','\U444C','\U444D','\U444E','\U444F','\U4450','\U4451','\U4452','\U4453','\U4454','\U4455','\U4456','\U4457','\U4458','\U4459','\U445A','\U445B','\U445C','\U445D','\U445E','\U445F','\U4460','\U4461','\U4462','\U4463','\U4464','\U4465','\U4466','\U4467','\U4468','\U4469','\U446A','\U446B','\U446C','\U446D','\U446E','\U446F','\U4470','\U4471','\U4472','\U4473','\U4474','\U4475','\U4476','\U4477','\U4478','\U4479','\U447A','\U447B','\U447C','\U447D','\U447E','\U447F','\U4480','\U4481','\U4482','\U4483','\U4484','\U4485','\U4486','\U4487','\U4488','\U4489','\U448A','\U448B','\U448C','\U448D','\U448E','\U448F','\U4490','\U4491','\U4492','\U4493','\U4494','\U4495','\U4496','\U4497','\U4498','\U4499','\U449A','\U449B','\U449C','\U449D','\U449E','\U449F','\U44A0','\U44A1','\U44A2','\U44A3','\U44A4','\U44A5','\U44A6','\U44A7','\U44A8','\U44A9','\U44AA','\U44AB','\U44AC','\U44AD','\U44AE','\U44AF','\U44B0','\U44B1','\U44B2','\U44B3','\U44B4','\U44B5','\U44B6','\U44B7','\U44B8','\U44B9','\U44BA','\U44BB','\U44BC','\U44BD','\U44BE','\U44BF','\U44C0','\U44C1','\U44C2','\U44C3','\U44C4','\U44C5','\U44C6','\U44C7','\U44C8','\U44C9','\U44CA','\U44CB','\U44CC','\U44CD','\U44CE','\U44CF','\U44D0','\U44D1','\U44D2','\U44D3','\U44D4','\U44D5','\U44D6','\U44D7','\U44D8','\U44D9','\U44DA','\U44DB','\U44DC','\U44DD','\U44DE','\U44DF','\U44E0','\U44E1','\U44E2','\U44E3','\U44E4','\U44E5','\U44E6','\U44E7','\U44E8','\U44E9','\U44EA','\U44EB','\U44EC','\U44ED','\U44EE','\U44EF','\U44F0','\U44F1','\U44F2','\U44F3','\U44F4','\U44F5','\U44F6','\U44F7','\U44F8','\U44F9','\U44FA','\U44FB','\U44FC','\U44FD','\U44FE','\U44FF','\U4500','\U4501','\U4502','\U4503','\U4504','\U4505','\U4506','\U4507','\U4508','\U4509','\U450A','\U450B','\U450C','\U450D','\U450E','\U450F','\U4510','\U4511','\U4512','\U4513','\U4514','\U4515','\U4516','\U4517','\U4518','\U4519','\U451A','\U451B','\U451C','\U451D','\U451E','\U451F','\U4520','\U4521','\U4522','\U4523','\U4524','\U4525','\U4526','\U4527','\U4528','\U4529','\U452A','\U452B','\U452C','\U452D','\U452E','\U452F','\U4530','\U4531','\U4532','\U4533','\U4534','\U4535','\U4536','\U4537','\U4538','\U4539','\U453A','\U453B','\U453C','\U453D','\U453E','\U453F','\U4540','\U4541','\U4542','\U4543','\U4544','\U4545','\U4546','\U4547','\U4548','\U4549','\U454A','\U454B','\U454C','\U454D','\U454E','\U454F','\U4550','\U4551','\U4552','\U4553','\U4554','\U4555','\U4556','\U4557','\U4558','\U4559','\U455A','\U455B','\U455C','\U455D','\U455E','\U455F','\U4560','\U4561','\U4562','\U4563','\U4564','\U4565','\U4566','\U4567','\U4568','\U4569','\U456A','\U456B','\U456C','\U456D','\U456E','\U456F','\U4570','\U4571','\U4572','\U4573','\U4574','\U4575','\U4576','\U4577','\U4578','\U4579','\U457A','\U457B','\U457C','\U457D','\U457E','\U457F','\U4580','\U4581','\U4582','\U4583','\U4584','\U4585','\U4586','\U4587','\U4588','\U4589','\U458A','\U458B','\U458C','\U458D','\U458E','\U458F','\U4590','\U4591','\U4592','\U4593','\U4594','\U4595','\U4596','\U4597','\U4598','\U4599','\U459A','\U459B','\U459C','\U459D','\U459E','\U459F','\U45A0','\U45A1','\U45A2','\U45A3','\U45A4','\U45A5','\U45A6','\U45A7','\U45A8','\U45A9','\U45AA','\U45AB','\U45AC','\U45AD','\U45AE','\U45AF','\U45B0','\U45B1','\U45B2','\U45B3','\U45B4','\U45B5','\U45B6','\U45B7','\U45B8','\U45B9','\U45BA','\U45BB','\U45BC','\U45BD','\U45BE','\U45BF','\U45C0','\U45C1','\U45C2','\U45C3','\U45C4','\U45C5','\U45C6','\U45C7','\U45C8','\U45C9','\U45CA','\U45CB','\U45CC','\U45CD','\U45CE','\U45CF','\U45D0','\U45D1','\U45D2','\U45D3','\U45D4','\U45D5','\U45D6','\U45D7','\U45D8','\U45D9','\U45DA','\U45DB','\U45DC','\U45DD','\U45DE','\U45DF','\U45E0','\U45E1','\U45E2','\U45E3','\U45E4','\U45E5','\U45E6','\U45E7','\U45E8','\U45E9','\U45EA','\U45EB','\U45EC','\U45ED','\U45EE','\U45EF','\U45F0','\U45F1','\U45F2','\U45F3','\U45F4','\U45F5','\U45F6','\U45F7','\U45F8','\U45F9','\U45FA','\U45FB','\U45FC','\U45FD','\U45FE','\U45FF','\U4600','\U4601','\U4602','\U4603','\U4604','\U4605','\U4606','\U4607','\U4608','\U4609','\U460A','\U460B','\U460C','\U460D','\U460E','\U460F','\U4610','\U4611','\U4612','\U4613','\U4614','\U4615','\U4616','\U4617','\U4618','\U4619','\U461A','\U461B','\U461C','\U461D','\U461E','\U461F','\U4620','\U4621','\U4622','\U4623','\U4624','\U4625','\U4626','\U4627','\U4628','\U4629','\U462A','\U462B','\U462C','\U462D','\U462E','\U462F','\U4630','\U4631','\U4632','\U4633','\U4634','\U4635','\U4636','\U4637','\U4638','\U4639','\U463A','\U463B','\U463C','\U463D','\U463E','\U463F','\U4640','\U4641','\U4642','\U4643','\U4644','\U4645','\U4646','\U4647','\U4648','\U4649','\U464A','\U464B','\U464C','\U464D','\U464E','\U464F','\U4650','\U4651','\U4652','\U4653','\U4654','\U4655','\U4656','\U4657','\U4658','\U4659','\U465A','\U465B','\U465C','\U465D','\U465E','\U465F','\U4660','\U4661','\U4662','\U4663','\U4664','\U4665','\U4666','\U4667','\U4668','\U4669','\U466A','\U466B','\U466C','\U466D','\U466E','\U466F','\U4670','\U4671','\U4672','\U4673','\U4674','\U4675','\U4676','\U4677','\U4678','\U4679','\U467A','\U467B','\U467C','\U467D','\U467E','\U467F','\U4680','\U4681','\U4682','\U4683','\U4684','\U4685','\U4686','\U4687','\U4688','\U4689','\U468A','\U468B','\U468C','\U468D','\U468E','\U468F','\U4690','\U4691','\U4692','\U4693','\U4694','\U4695','\U4696','\U4697','\U4698','\U4699','\U469A','\U469B','\U469C','\U469D','\U469E','\U469F','\U46A0','\U46A1','\U46A2','\U46A3','\U46A4','\U46A5','\U46A6','\U46A7','\U46A8','\U46A9','\U46AA','\U46AB','\U46AC','\U46AD','\U46AE','\U46AF','\U46B0','\U46B1','\U46B2','\U46B3','\U46B4','\U46B5','\U46B6','\U46B7','\U46B8','\U46B9','\U46BA','\U46BB','\U46BC','\U46BD','\U46BE','\U46BF','\U46C0','\U46C1','\U46C2','\U46C3','\U46C4','\U46C5','\U46C6','\U46C7','\U46C8','\U46C9','\U46CA','\U46CB','\U46CC','\U46CD','\U46CE','\U46CF','\U46D0','\U46D1','\U46D2','\U46D3','\U46D4','\U46D5','\U46D6','\U46D7','\U46D8','\U46D9','\U46DA','\U46DB','\U46DC','\U46DD','\U46DE','\U46DF','\U46E0','\U46E1','\U46E2','\U46E3','\U46E4','\U46E5','\U46E6','\U46E7','\U46E8','\U46E9','\U46EA','\U46EB','\U46EC','\U46ED','\U46EE','\U46EF','\U46F0','\U46F1','\U46F2','\U46F3','\U46F4','\U46F5','\U46F6','\U46F7','\U46F8','\U46F9','\U46FA','\U46FB','\U46FC','\U46FD','\U46FE','\U46FF','\U4700','\U4701','\U4702','\U4703','\U4704','\U4705','\U4706','\U4707','\U4708','\U4709','\U470A','\U470B','\U470C','\U470D','\U470E','\U470F','\U4710','\U4711','\U4712','\U4713','\U4714','\U4715','\U4716','\U4717','\U4718','\U4719','\U471A','\U471B','\U471C','\U471D','\U471E','\U471F','\U4720','\U4721','\U4722','\U4723','\U4724','\U4725','\U4726','\U4727','\U4728','\U4729','\U472A','\U472B','\U472C','\U472D','\U472E','\U472F','\U4730','\U4731','\U4732','\U4733','\U4734','\U4735','\U4736','\U4737','\U4738','\U4739','\U473A','\U473B','\U473C','\U473D','\U473E','\U473F','\U4740','\U4741','\U4742','\U4743','\U4744','\U4745','\U4746','\U4747','\U4748','\U4749','\U474A','\U474B','\U474C','\U474D','\U474E','\U474F','\U4750','\U4751','\U4752','\U4753','\U4754','\U4755','\U4756','\U4757','\U4758','\U4759','\U475A','\U475B','\U475C','\U475D','\U475E','\U475F','\U4760','\U4761','\U4762','\U4763','\U4764','\U4765','\U4766','\U4767','\U4768','\U4769','\U476A','\U476B','\U476C','\U476D','\U476E','\U476F','\U4770','\U4771','\U4772','\U4773','\U4774','\U4775','\U4776','\U4777','\U4778','\U4779','\U477A','\U477B','\U477C','\U477D','\U477E','\U477F','\U4780','\U4781','\U4782','\U4783','\U4784','\U4785','\U4786','\U4787','\U4788','\U4789','\U478A','\U478B','\U478C','\U478D','\U478E','\U478F','\U4790','\U4791','\U4792','\U4793','\U4794','\U4795','\U4796','\U4797','\U4798','\U4799','\U479A','\U479B','\U479C','\U479D','\U479E','\U479F','\U47A0','\U47A1','\U47A2','\U47A3','\U47A4','\U47A5','\U47A6','\U47A7','\U47A8','\U47A9','\U47AA','\U47AB','\U47AC','\U47AD','\U47AE','\U47AF','\U47B0','\U47B1','\U47B2','\U47B3','\U47B4','\U47B5','\U47B6','\U47B7','\U47B8','\U47B9','\U47BA','\U47BB','\U47BC','\U47BD','\U47BE','\U47BF','\U47C0','\U47C1','\U47C2','\U47C3','\U47C4','\U47C5','\U47C6','\U47C7','\U47C8','\U47C9','\U47CA','\U47CB','\U47CC','\U47CD','\U47CE','\U47CF','\U47D0','\U47D1','\U47D2','\U47D3','\U47D4','\U47D5','\U47D6','\U47D7','\U47D8','\U47D9','\U47DA','\U47DB','\U47DC','\U47DD','\U47DE','\U47DF','\U47E0','\U47E1','\U47E2','\U47E3','\U47E4','\U47E5','\U47E6','\U47E7','\U47E8','\U47E9','\U47EA','\U47EB','\U47EC','\U47ED','\U47EE','\U47EF','\U47F0','\U47F1','\U47F2','\U47F3','\U47F4','\U47F5','\U47F6','\U47F7','\U47F8','\U47F9','\U47FA','\U47FB','\U47FC','\U47FD','\U47FE','\U47FF','\U4800','\U4801','\U4802','\U4803','\U4804','\U4805','\U4806','\U4807','\U4808','\U4809','\U480A','\U480B','\U480C','\U480D','\U480E','\U480F','\U4810','\U4811','\U4812','\U4813','\U4814','\U4815','\U4816','\U4817','\U4818','\U4819','\U481A','\U481B','\U481C','\U481D','\U481E','\U481F','\U4820','\U4821','\U4822','\U4823','\U4824','\U4825','\U4826','\U4827','\U4828','\U4829','\U482A','\U482B','\U482C','\U482D','\U482E','\U482F','\U4830','\U4831','\U4832','\U4833','\U4834','\U4835','\U4836','\U4837','\U4838','\U4839','\U483A','\U483B','\U483C','\U483D','\U483E','\U483F','\U4840','\U4841','\U4842','\U4843','\U4844','\U4845','\U4846','\U4847','\U4848','\U4849','\U484A','\U484B','\U484C','\U484D','\U484E','\U484F','\U4850','\U4851','\U4852','\U4853','\U4854','\U4855','\U4856','\U4857','\U4858','\U4859','\U485A','\U485B','\U485C','\U485D','\U485E','\U485F','\U4860','\U4861','\U4862','\U4863','\U4864','\U4865','\U4866','\U4867','\U4868','\U4869','\U486A','\U486B','\U486C','\U486D','\U486E','\U486F','\U4870','\U4871','\U4872','\U4873','\U4874','\U4875','\U4876','\U4877','\U4878','\U4879','\U487A','\U487B','\U487C','\U487D','\U487E','\U487F','\U4880','\U4881','\U4882','\U4883','\U4884','\U4885','\U4886','\U4887','\U4888','\U4889','\U488A','\U488B','\U488C','\U488D','\U488E','\U488F','\U4890','\U4891','\U4892','\U4893','\U4894','\U4895','\U4896','\U4897','\U4898','\U4899','\U489A','\U489B','\U489C','\U489D','\U489E','\U489F','\U48A0','\U48A1','\U48A2','\U48A3','\U48A4','\U48A5','\U48A6','\U48A7','\U48A8','\U48A9','\U48AA','\U48AB','\U48AC','\U48AD','\U48AE','\U48AF','\U48B0','\U48B1','\U48B2','\U48B3','\U48B4','\U48B5','\U48B6','\U48B7','\U48B8','\U48B9','\U48BA','\U48BB','\U48BC','\U48BD','\U48BE','\U48BF','\U48C0','\U48C1','\U48C2','\U48C3','\U48C4','\U48C5','\U48C6','\U48C7','\U48C8','\U48C9','\U48CA','\U48CB','\U48CC','\U48CD','\U48CE','\U48CF','\U48D0','\U48D1','\U48D2','\U48D3','\U48D4','\U48D5','\U48D6','\U48D7','\U48D8','\U48D9','\U48DA','\U48DB','\U48DC','\U48DD','\U48DE','\U48DF','\U48E0','\U48E1','\U48E2','\U48E3','\U48E4','\U48E5','\U48E6','\U48E7','\U48E8','\U48E9','\U48EA','\U48EB','\U48EC','\U48ED','\U48EE','\U48EF','\U48F0','\U48F1','\U48F2','\U48F3','\U48F4','\U48F5','\U48F6','\U48F7','\U48F8','\U48F9','\U48FA','\U48FB','\U48FC','\U48FD','\U48FE','\U48FF','\U4900','\U4901','\U4902','\U4903','\U4904','\U4905','\U4906','\U4907','\U4908','\U4909','\U490A','\U490B','\U490C','\U490D','\U490E','\U490F','\U4910','\U4911','\U4912','\U4913','\U4914','\U4915','\U4916','\U4917','\U4918','\U4919','\U491A','\U491B','\U491C','\U491D','\U491E','\U491F','\U4920','\U4921','\U4922','\U4923','\U4924','\U4925','\U4926','\U4927','\U4928','\U4929','\U492A','\U492B','\U492C','\U492D','\U492E','\U492F','\U4930','\U4931','\U4932','\U4933','\U4934','\U4935','\U4936','\U4937','\U4938','\U4939','\U493A','\U493B','\U493C','\U493D','\U493E','\U493F','\U4940','\U4941','\U4942','\U4943','\U4944','\U4945','\U4946','\U4947','\U4948','\U4949','\U494A','\U494B','\U494C','\U494D','\U494E','\U494F','\U4950','\U4951','\U4952','\U4953','\U4954','\U4955','\U4956','\U4957','\U4958','\U4959','\U495A','\U495B','\U495C','\U495D','\U495E','\U495F','\U4960','\U4961','\U4962','\U4963','\U4964','\U4965','\U4966','\U4967','\U4968','\U4969','\U496A','\U496B','\U496C','\U496D','\U496E','\U496F','\U4970','\U4971','\U4972','\U4973','\U4974','\U4975','\U4976','\U4977','\U4978','\U4979','\U497A','\U497B','\U497C','\U497D','\U497E','\U497F','\U4980','\U4981','\U4982','\U4983','\U4984','\U4985','\U4986','\U4987','\U4988','\U4989','\U498A','\U498B','\U498C','\U498D','\U498E','\U498F','\U4990','\U4991','\U4992','\U4993','\U4994','\U4995','\U4996','\U4997','\U4998','\U4999','\U499A','\U499B','\U499C','\U499D','\U499E','\U499F','\U49A0','\U49A1','\U49A2','\U49A3','\U49A4','\U49A5','\U49A6','\U49A7','\U49A8','\U49A9','\U49AA','\U49AB','\U49AC','\U49AD','\U49AE','\U49AF','\U49B0','\U49B1','\U49B2','\U49B3','\U49B4','\U49B5','\U49B6','\U49B7','\U49B8','\U49B9','\U49BA','\U49BB','\U49BC','\U49BD','\U49BE','\U49BF','\U49C0','\U49C1','\U49C2','\U49C3','\U49C4','\U49C5','\U49C6','\U49C7','\U49C8','\U49C9','\U49CA','\U49CB','\U49CC','\U49CD','\U49CE','\U49CF','\U49D0','\U49D1','\U49D2','\U49D3','\U49D4','\U49D5','\U49D6','\U49D7','\U49D8','\U49D9','\U49DA','\U49DB','\U49DC','\U49DD','\U49DE','\U49DF','\U49E0','\U49E1','\U49E2','\U49E3','\U49E4','\U49E5','\U49E6','\U49E7','\U49E8','\U49E9','\U49EA','\U49EB','\U49EC','\U49ED','\U49EE','\U49EF','\U49F0','\U49F1','\U49F2','\U49F3','\U49F4','\U49F5','\U49F6','\U49F7','\U49F8','\U49F9','\U49FA','\U49FB','\U49FC','\U49FD','\U49FE','\U49FF','\U4A00','\U4A01','\U4A02','\U4A03','\U4A04','\U4A05','\U4A06','\U4A07','\U4A08','\U4A09','\U4A0A','\U4A0B','\U4A0C','\U4A0D','\U4A0E','\U4A0F','\U4A10','\U4A11','\U4A12','\U4A13','\U4A14','\U4A15','\U4A16','\U4A17','\U4A18','\U4A19','\U4A1A','\U4A1B','\U4A1C','\U4A1D','\U4A1E','\U4A1F','\U4A20','\U4A21','\U4A22','\U4A23','\U4A24','\U4A25','\U4A26','\U4A27','\U4A28','\U4A29','\U4A2A','\U4A2B','\U4A2C','\U4A2D','\U4A2E','\U4A2F','\U4A30','\U4A31','\U4A32','\U4A33','\U4A34','\U4A35','\U4A36','\U4A37','\U4A38','\U4A39','\U4A3A','\U4A3B','\U4A3C','\U4A3D','\U4A3E','\U4A3F','\U4A40','\U4A41','\U4A42','\U4A43','\U4A44','\U4A45','\U4A46','\U4A47','\U4A48','\U4A49','\U4A4A','\U4A4B','\U4A4C','\U4A4D','\U4A4E','\U4A4F','\U4A50','\U4A51','\U4A52','\U4A53','\U4A54','\U4A55','\U4A56','\U4A57','\U4A58','\U4A59','\U4A5A','\U4A5B','\U4A5C','\U4A5D','\U4A5E','\U4A5F','\U4A60','\U4A61','\U4A62','\U4A63','\U4A64','\U4A65','\U4A66','\U4A67','\U4A68','\U4A69','\U4A6A','\U4A6B','\U4A6C','\U4A6D','\U4A6E','\U4A6F','\U4A70','\U4A71','\U4A72','\U4A73','\U4A74','\U4A75','\U4A76','\U4A77','\U4A78','\U4A79','\U4A7A','\U4A7B','\U4A7C','\U4A7D','\U4A7E','\U4A7F','\U4A80','\U4A81','\U4A82','\U4A83','\U4A84','\U4A85','\U4A86','\U4A87','\U4A88','\U4A89','\U4A8A','\U4A8B','\U4A8C','\U4A8D','\U4A8E','\U4A8F','\U4A90','\U4A91','\U4A92','\U4A93','\U4A94','\U4A95','\U4A96','\U4A97','\U4A98','\U4A99','\U4A9A','\U4A9B','\U4A9C','\U4A9D','\U4A9E','\U4A9F','\U4AA0','\U4AA1','\U4AA2','\U4AA3','\U4AA4','\U4AA5','\U4AA6','\U4AA7','\U4AA8','\U4AA9','\U4AAA','\U4AAB','\U4AAC','\U4AAD','\U4AAE','\U4AAF','\U4AB0','\U4AB1','\U4AB2','\U4AB3','\U4AB4','\U4AB5','\U4AB6','\U4AB7','\U4AB8','\U4AB9','\U4ABA','\U4ABB','\U4ABC','\U4ABD','\U4ABE','\U4ABF','\U4AC0','\U4AC1','\U4AC2','\U4AC3','\U4AC4','\U4AC5','\U4AC6','\U4AC7','\U4AC8','\U4AC9','\U4ACA','\U4ACB','\U4ACC','\U4ACD','\U4ACE','\U4ACF','\U4AD0','\U4AD1','\U4AD2','\U4AD3','\U4AD4','\U4AD5','\U4AD6','\U4AD7','\U4AD8','\U4AD9','\U4ADA','\U4ADB','\U4ADC','\U4ADD','\U4ADE','\U4ADF','\U4AE0','\U4AE1','\U4AE2','\U4AE3','\U4AE4','\U4AE5','\U4AE6','\U4AE7','\U4AE8','\U4AE9','\U4AEA','\U4AEB','\U4AEC','\U4AED','\U4AEE','\U4AEF','\U4AF0','\U4AF1','\U4AF2','\U4AF3','\U4AF4','\U4AF5','\U4AF6','\U4AF7','\U4AF8','\U4AF9','\U4AFA','\U4AFB','\U4AFC','\U4AFD','\U4AFE','\U4AFF','\U4B00','\U4B01','\U4B02','\U4B03','\U4B04','\U4B05','\U4B06','\U4B07','\U4B08','\U4B09','\U4B0A','\U4B0B','\U4B0C','\U4B0D','\U4B0E','\U4B0F','\U4B10','\U4B11','\U4B12','\U4B13','\U4B14','\U4B15','\U4B16','\U4B17','\U4B18','\U4B19','\U4B1A','\U4B1B','\U4B1C','\U4B1D','\U4B1E','\U4B1F','\U4B20','\U4B21','\U4B22','\U4B23','\U4B24','\U4B25','\U4B26','\U4B27','\U4B28','\U4B29','\U4B2A','\U4B2B','\U4B2C','\U4B2D','\U4B2E','\U4B2F','\U4B30','\U4B31','\U4B32','\U4B33','\U4B34','\U4B35','\U4B36','\U4B37','\U4B38','\U4B39','\U4B3A','\U4B3B','\U4B3C','\U4B3D','\U4B3E','\U4B3F','\U4B40','\U4B41','\U4B42','\U4B43','\U4B44','\U4B45','\U4B46','\U4B47','\U4B48','\U4B49','\U4B4A','\U4B4B','\U4B4C','\U4B4D','\U4B4E','\U4B4F','\U4B50','\U4B51','\U4B52','\U4B53','\U4B54','\U4B55','\U4B56','\U4B57','\U4B58','\U4B59','\U4B5A','\U4B5B','\U4B5C','\U4B5D','\U4B5E','\U4B5F','\U4B60','\U4B61','\U4B62','\U4B63','\U4B64','\U4B65','\U4B66','\U4B67','\U4B68','\U4B69','\U4B6A','\U4B6B','\U4B6C','\U4B6D','\U4B6E','\U4B6F','\U4B70','\U4B71','\U4B72','\U4B73','\U4B74','\U4B75','\U4B76','\U4B77','\U4B78','\U4B79','\U4B7A','\U4B7B','\U4B7C','\U4B7D','\U4B7E','\U4B7F','\U4B80','\U4B81','\U4B82','\U4B83','\U4B84','\U4B85','\U4B86','\U4B87','\U4B88','\U4B89','\U4B8A','\U4B8B','\U4B8C','\U4B8D','\U4B8E','\U4B8F','\U4B90','\U4B91','\U4B92','\U4B93','\U4B94','\U4B95','\U4B96','\U4B97','\U4B98','\U4B99','\U4B9A','\U4B9B','\U4B9C','\U4B9D','\U4B9E','\U4B9F','\U4BA0','\U4BA1','\U4BA2','\U4BA3','\U4BA4','\U4BA5','\U4BA6','\U4BA7','\U4BA8','\U4BA9','\U4BAA','\U4BAB','\U4BAC','\U4BAD','\U4BAE','\U4BAF','\U4BB0','\U4BB1','\U4BB2','\U4BB3','\U4BB4','\U4BB5','\U4BB6','\U4BB7','\U4BB8','\U4BB9','\U4BBA','\U4BBB','\U4BBC','\U4BBD','\U4BBE','\U4BBF','\U4BC0','\U4BC1','\U4BC2','\U4BC3','\U4BC4','\U4BC5','\U4BC6','\U4BC7','\U4BC8','\U4BC9','\U4BCA','\U4BCB','\U4BCC','\U4BCD','\U4BCE','\U4BCF','\U4BD0','\U4BD1','\U4BD2','\U4BD3','\U4BD4','\U4BD5','\U4BD6','\U4BD7','\U4BD8','\U4BD9','\U4BDA','\U4BDB','\U4BDC','\U4BDD','\U4BDE','\U4BDF','\U4BE0','\U4BE1','\U4BE2','\U4BE3','\U4BE4','\U4BE5','\U4BE6','\U4BE7','\U4BE8','\U4BE9','\U4BEA','\U4BEB','\U4BEC','\U4BED','\U4BEE','\U4BEF','\U4BF0','\U4BF1','\U4BF2','\U4BF3','\U4BF4','\U4BF5','\U4BF6','\U4BF7','\U4BF8','\U4BF9','\U4BFA','\U4BFB','\U4BFC','\U4BFD','\U4BFE','\U4BFF','\U4C00','\U4C01','\U4C02','\U4C03','\U4C04','\U4C05','\U4C06','\U4C07','\U4C08','\U4C09','\U4C0A','\U4C0B','\U4C0C','\U4C0D','\U4C0E','\U4C0F','\U4C10','\U4C11','\U4C12','\U4C13','\U4C14','\U4C15','\U4C16','\U4C17','\U4C18','\U4C19','\U4C1A','\U4C1B','\U4C1C','\U4C1D','\U4C1E','\U4C1F','\U4C20','\U4C21','\U4C22','\U4C23','\U4C24','\U4C25','\U4C26','\U4C27','\U4C28','\U4C29','\U4C2A','\U4C2B','\U4C2C','\U4C2D','\U4C2E','\U4C2F','\U4C30','\U4C31','\U4C32','\U4C33','\U4C34','\U4C35','\U4C36','\U4C37','\U4C38','\U4C39','\U4C3A','\U4C3B','\U4C3C','\U4C3D','\U4C3E','\U4C3F','\U4C40','\U4C41','\U4C42','\U4C43','\U4C44','\U4C45','\U4C46','\U4C47','\U4C48','\U4C49','\U4C4A','\U4C4B','\U4C4C','\U4C4D','\U4C4E','\U4C4F','\U4C50','\U4C51','\U4C52','\U4C53','\U4C54','\U4C55','\U4C56','\U4C57','\U4C58','\U4C59','\U4C5A','\U4C5B','\U4C5C','\U4C5D','\U4C5E','\U4C5F','\U4C60','\U4C61','\U4C62','\U4C63','\U4C64','\U4C65','\U4C66','\U4C67','\U4C68','\U4C69','\U4C6A','\U4C6B','\U4C6C','\U4C6D','\U4C6E','\U4C6F','\U4C70','\U4C71','\U4C72','\U4C73','\U4C74','\U4C75','\U4C76','\U4C77','\U4C78','\U4C79','\U4C7A','\U4C7B','\U4C7C','\U4C7D','\U4C7E','\U4C7F','\U4C80','\U4C81','\U4C82','\U4C83','\U4C84','\U4C85','\U4C86','\U4C87','\U4C88','\U4C89','\U4C8A','\U4C8B','\U4C8C','\U4C8D','\U4C8E','\U4C8F','\U4C90','\U4C91','\U4C92','\U4C93','\U4C94','\U4C95','\U4C96','\U4C97','\U4C98','\U4C99','\U4C9A','\U4C9B','\U4C9C','\U4C9D','\U4C9E','\U4C9F','\U4CA0','\U4CA1','\U4CA2','\U4CA3','\U4CA4','\U4CA5','\U4CA6','\U4CA7','\U4CA8','\U4CA9','\U4CAA','\U4CAB','\U4CAC','\U4CAD','\U4CAE','\U4CAF','\U4CB0','\U4CB1','\U4CB2','\U4CB3','\U4CB4','\U4CB5','\U4CB6','\U4CB7','\U4CB8','\U4CB9','\U4CBA','\U4CBB','\U4CBC','\U4CBD','\U4CBE','\U4CBF','\U4CC0','\U4CC1','\U4CC2','\U4CC3','\U4CC4','\U4CC5','\U4CC6','\U4CC7','\U4CC8','\U4CC9','\U4CCA','\U4CCB','\U4CCC','\U4CCD','\U4CCE','\U4CCF','\U4CD0','\U4CD1','\U4CD2','\U4CD3','\U4CD4','\U4CD5','\U4CD6','\U4CD7','\U4CD8','\U4CD9','\U4CDA','\U4CDB','\U4CDC','\U4CDD','\U4CDE','\U4CDF','\U4CE0','\U4CE1','\U4CE2','\U4CE3','\U4CE4','\U4CE5','\U4CE6','\U4CE7','\U4CE8','\U4CE9','\U4CEA','\U4CEB','\U4CEC','\U4CED','\U4CEE','\U4CEF','\U4CF0','\U4CF1','\U4CF2','\U4CF3','\U4CF4','\U4CF5','\U4CF6','\U4CF7','\U4CF8','\U4CF9','\U4CFA','\U4CFB','\U4CFC','\U4CFD','\U4CFE','\U4CFF','\U4D00','\U4D01','\U4D02','\U4D03','\U4D04','\U4D05','\U4D06','\U4D07','\U4D08','\U4D09','\U4D0A','\U4D0B','\U4D0C','\U4D0D','\U4D0E','\U4D0F','\U4D10','\U4D11','\U4D12','\U4D13','\U4D14','\U4D15','\U4D16','\U4D17','\U4D18','\U4D19','\U4D1A','\U4D1B','\U4D1C','\U4D1D','\U4D1E','\U4D1F','\U4D20','\U4D21','\U4D22','\U4D23','\U4D24','\U4D25','\U4D26','\U4D27','\U4D28','\U4D29','\U4D2A','\U4D2B','\U4D2C','\U4D2D','\U4D2E','\U4D2F','\U4D30','\U4D31','\U4D32','\U4D33','\U4D34','\U4D35','\U4D36','\U4D37','\U4D38','\U4D39','\U4D3A','\U4D3B','\U4D3C','\U4D3D','\U4D3E','\U4D3F','\U4D40','\U4D41','\U4D42','\U4D43','\U4D44','\U4D45','\U4D46','\U4D47','\U4D48','\U4D49','\U4D4A','\U4D4B','\U4D4C','\U4D4D','\U4D4E','\U4D4F','\U4D50','\U4D51','\U4D52','\U4D53','\U4D54','\U4D55','\U4D56','\U4D57','\U4D58','\U4D59','\U4D5A','\U4D5B','\U4D5C','\U4D5D','\U4D5E','\U4D5F','\U4D60','\U4D61','\U4D62','\U4D63','\U4D64','\U4D65','\U4D66','\U4D67','\U4D68','\U4D69','\U4D6A','\U4D6B','\U4D6C','\U4D6D','\U4D6E','\U4D6F','\U4D70','\U4D71','\U4D72','\U4D73','\U4D74','\U4D75','\U4D76','\U4D77','\U4D78','\U4D79','\U4D7A','\U4D7B','\U4D7C','\U4D7D','\U4D7E','\U4D7F','\U4D80','\U4D81','\U4D82','\U4D83','\U4D84','\U4D85','\U4D86','\U4D87','\U4D88','\U4D89','\U4D8A','\U4D8B','\U4D8C','\U4D8D','\U4D8E','\U4D8F','\U4D90','\U4D91','\U4D92','\U4D93','\U4D94','\U4D95','\U4D96','\U4D97','\U4D98','\U4D99','\U4D9A','\U4D9B','\U4D9C','\U4D9D','\U4D9E','\U4D9F','\U4DA0','\U4DA1','\U4DA2','\U4DA3','\U4DA4','\U4DA5','\U4DA6','\U4DA7','\U4DA8','\U4DA9','\U4DAA','\U4DAB','\U4DAC','\U4DAD','\U4DAE','\U4DAF','\U4DB0','\U4DB1','\U4DB2','\U4DB3','\U4DB4','\U4DB5','\U4DB6','\U4DB7','\U4DB8','\U4DB9','\U4DBA','\U4DBB','\U4DBC','\U4DBD','\U4DBE','\U4DBF','\U4DC0','\U4DC1','\U4DC2','\U4DC3','\U4DC4','\U4DC5','\U4DC6','\U4DC7','\U4DC8','\U4DC9','\U4DCA','\U4DCB','\U4DCC','\U4DCD','\U4DCE','\U4DCF','\U4DD0','\U4DD1','\U4DD2','\U4DD3','\U4DD4','\U4DD5','\U4DD6','\U4DD7','\U4DD8','\U4DD9','\U4DDA','\U4DDB','\U4DDC','\U4DDD','\U4DDE','\U4DDF','\U4DE0','\U4DE1','\U4DE2','\U4DE3','\U4DE4','\U4DE5','\U4DE6','\U4DE7','\U4DE8','\U4DE9','\U4DEA','\U4DEB','\U4DEC','\U4DED','\U4DEE','\U4DEF','\U4DF0','\U4DF1','\U4DF2','\U4DF3','\U4DF4','\U4DF5','\U4DF6','\U4DF7','\U4DF8','\U4DF9','\U4DFA','\U4DFB','\U4DFC','\U4DFD','\U4DFE','\U4DFF','\U4E00','\U4E01','\U4E02','\U4E03','\U4E04','\U4E05','\U4E06','\U4E07','\U4E08','\U4E09','\U4E0A','\U4E0B','\U4E0C','\U4E0D','\U4E0E','\U4E0F','\U4E10','\U4E11','\U4E12','\U4E13','\U4E14','\U4E15','\U4E16','\U4E17','\U4E18','\U4E19','\U4E1A','\U4E1B','\U4E1C','\U4E1D','\U4E1E','\U4E1F','\U4E20','\U4E21','\U4E22','\U4E23','\U4E24','\U4E25','\U4E26','\U4E27','\U4E28','\U4E29','\U4E2A','\U4E2B','\U4E2C','\U4E2D','\U4E2E','\U4E2F','\U4E30','\U4E31','\U4E32','\U4E33','\U4E34','\U4E35','\U4E36','\U4E37','\U4E38','\U4E39','\U4E3A','\U4E3B','\U4E3C','\U4E3D','\U4E3E','\U4E3F','\U4E40','\U4E41','\U4E42','\U4E43','\U4E44','\U4E45','\U4E46','\U4E47','\U4E48','\U4E49','\U4E4A','\U4E4B','\U4E4C','\U4E4D','\U4E4E','\U4E4F','\U4E50','\U4E51','\U4E52','\U4E53','\U4E54','\U4E55','\U4E56','\U4E57','\U4E58','\U4E59','\U4E5A','\U4E5B','\U4E5C','\U4E5D','\U4E5E','\U4E5F','\U4E60','\U4E61','\U4E62','\U4E63','\U4E64','\U4E65','\U4E66','\U4E67','\U4E68','\U4E69','\U4E6A','\U4E6B','\U4E6C','\U4E6D','\U4E6E','\U4E6F','\U4E70','\U4E71','\U4E72','\U4E73','\U4E74','\U4E75','\U4E76','\U4E77','\U4E78','\U4E79','\U4E7A','\U4E7B','\U4E7C','\U4E7D','\U4E7E','\U4E7F','\U4E80','\U4E81','\U4E82','\U4E83','\U4E84','\U4E85','\U4E86','\U4E87','\U4E88','\U4E89','\U4E8A','\U4E8B','\U4E8C','\U4E8D','\U4E8E','\U4E8F','\U4E90','\U4E91','\U4E92','\U4E93','\U4E94','\U4E95','\U4E96','\U4E97','\U4E98','\U4E99','\U4E9A','\U4E9B','\U4E9C','\U4E9D','\U4E9E','\U4E9F','\U4EA0','\U4EA1','\U4EA2','\U4EA3','\U4EA4','\U4EA5','\U4EA6','\U4EA7','\U4EA8','\U4EA9','\U4EAA','\U4EAB','\U4EAC','\U4EAD','\U4EAE','\U4EAF','\U4EB0','\U4EB1','\U4EB2','\U4EB3','\U4EB4','\U4EB5','\U4EB6','\U4EB7','\U4EB8','\U4EB9','\U4EBA','\U4EBB','\U4EBC','\U4EBD','\U4EBE','\U4EBF','\U4EC0','\U4EC1','\U4EC2','\U4EC3','\U4EC4','\U4EC5','\U4EC6','\U4EC7','\U4EC8','\U4EC9','\U4ECA','\U4ECB','\U4ECC','\U4ECD','\U4ECE','\U4ECF','\U4ED0','\U4ED1','\U4ED2','\U4ED3','\U4ED4','\U4ED5','\U4ED6','\U4ED7','\U4ED8','\U4ED9','\U4EDA','\U4EDB','\U4EDC','\U4EDD','\U4EDE','\U4EDF','\U4EE0','\U4EE1','\U4EE2','\U4EE3','\U4EE4','\U4EE5','\U4EE6','\U4EE7','\U4EE8','\U4EE9','\U4EEA','\U4EEB','\U4EEC','\U4EED','\U4EEE','\U4EEF','\U4EF0','\U4EF1','\U4EF2','\U4EF3','\U4EF4','\U4EF5','\U4EF6','\U4EF7','\U4EF8','\U4EF9','\U4EFA','\U4EFB','\U4EFC','\U4EFD','\U4EFE','\U4EFF','\U4F00','\U4F01','\U4F02','\U4F03','\U4F04','\U4F05','\U4F06','\U4F07','\U4F08','\U4F09','\U4F0A','\U4F0B','\U4F0C','\U4F0D','\U4F0E','\U4F0F','\U4F10','\U4F11','\U4F12','\U4F13','\U4F14','\U4F15','\U4F16','\U4F17','\U4F18','\U4F19','\U4F1A','\U4F1B','\U4F1C','\U4F1D','\U4F1E','\U4F1F','\U4F20','\U4F21','\U4F22','\U4F23','\U4F24','\U4F25','\U4F26','\U4F27','\U4F28','\U4F29','\U4F2A','\U4F2B','\U4F2C','\U4F2D','\U4F2E','\U4F2F','\U4F30','\U4F31','\U4F32','\U4F33','\U4F34','\U4F35','\U4F36','\U4F37','\U4F38','\U4F39','\U4F3A','\U4F3B','\U4F3C','\U4F3D','\U4F3E','\U4F3F','\U4F40','\U4F41','\U4F42','\U4F43','\U4F44','\U4F45','\U4F46','\U4F47','\U4F48','\U4F49','\U4F4A','\U4F4B','\U4F4C','\U4F4D','\U4F4E','\U4F4F','\U4F50','\U4F51','\U4F52','\U4F53','\U4F54','\U4F55','\U4F56','\U4F57','\U4F58','\U4F59','\U4F5A','\U4F5B','\U4F5C','\U4F5D','\U4F5E','\U4F5F','\U4F60','\U4F61','\U4F62','\U4F63','\U4F64','\U4F65','\U4F66','\U4F67','\U4F68','\U4F69','\U4F6A','\U4F6B','\U4F6C','\U4F6D','\U4F6E','\U4F6F','\U4F70','\U4F71','\U4F72','\U4F73','\U4F74','\U4F75','\U4F76','\U4F77','\U4F78','\U4F79','\U4F7A','\U4F7B','\U4F7C','\U4F7D','\U4F7E','\U4F7F','\U4F80','\U4F81','\U4F82','\U4F83','\U4F84','\U4F85','\U4F86','\U4F87','\U4F88','\U4F89','\U4F8A','\U4F8B','\U4F8C','\U4F8D','\U4F8E','\U4F8F','\U4F90','\U4F91','\U4F92','\U4F93','\U4F94','\U4F95','\U4F96','\U4F97','\U4F98','\U4F99','\U4F9A','\U4F9B','\U4F9C','\U4F9D','\U4F9E','\U4F9F','\U4FA0','\U4FA1','\U4FA2','\U4FA3','\U4FA4','\U4FA5','\U4FA6','\U4FA7','\U4FA8','\U4FA9','\U4FAA','\U4FAB','\U4FAC','\U4FAD','\U4FAE','\U4FAF','\U4FB0','\U4FB1','\U4FB2','\U4FB3','\U4FB4','\U4FB5','\U4FB6','\U4FB7','\U4FB8','\U4FB9','\U4FBA','\U4FBB','\U4FBC','\U4FBD','\U4FBE','\U4FBF','\U4FC0','\U4FC1','\U4FC2','\U4FC3','\U4FC4','\U4FC5','\U4FC6','\U4FC7','\U4FC8','\U4FC9','\U4FCA','\U4FCB','\U4FCC','\U4FCD','\U4FCE','\U4FCF','\U4FD0','\U4FD1','\U4FD2','\U4FD3','\U4FD4','\U4FD5','\U4FD6','\U4FD7','\U4FD8','\U4FD9','\U4FDA','\U4FDB','\U4FDC','\U4FDD','\U4FDE','\U4FDF','\U4FE0','\U4FE1','\U4FE2','\U4FE3','\U4FE4','\U4FE5','\U4FE6','\U4FE7','\U4FE8','\U4FE9','\U4FEA','\U4FEB','\U4FEC','\U4FED','\U4FEE','\U4FEF','\U4FF0','\U4FF1','\U4FF2','\U4FF3','\U4FF4','\U4FF5','\U4FF6','\U4FF7','\U4FF8','\U4FF9','\U4FFA','\U4FFB','\U4FFC','\U4FFD','\U4FFE','\U4FFF','\U5000','\U5001','\U5002','\U5003','\U5004','\U5005','\U5006','\U5007','\U5008','\U5009','\U500A','\U500B','\U500C','\U500D','\U500E','\U500F','\U5010','\U5011','\U5012','\U5013','\U5014','\U5015','\U5016','\U5017','\U5018','\U5019','\U501A','\U501B','\U501C','\U501D','\U501E','\U501F','\U5020','\U5021','\U5022','\U5023','\U5024','\U5025','\U5026','\U5027','\U5028','\U5029','\U502A','\U502B','\U502C','\U502D','\U502E','\U502F','\U5030','\U5031','\U5032','\U5033','\U5034','\U5035','\U5036','\U5037','\U5038','\U5039','\U503A','\U503B','\U503C','\U503D','\U503E','\U503F','\U5040','\U5041','\U5042','\U5043','\U5044','\U5045','\U5046','\U5047','\U5048','\U5049','\U504A','\U504B','\U504C','\U504D','\U504E','\U504F','\U5050','\U5051','\U5052','\U5053','\U5054','\U5055','\U5056','\U5057','\U5058','\U5059','\U505A','\U505B','\U505C','\U505D','\U505E','\U505F','\U5060','\U5061','\U5062','\U5063','\U5064','\U5065','\U5066','\U5067','\U5068','\U5069','\U506A','\U506B','\U506C','\U506D','\U506E','\U506F','\U5070','\U5071','\U5072','\U5073','\U5074','\U5075','\U5076','\U5077','\U5078','\U5079','\U507A','\U507B','\U507C','\U507D','\U507E','\U507F','\U5080','\U5081','\U5082','\U5083','\U5084','\U5085','\U5086','\U5087','\U5088','\U5089','\U508A','\U508B','\U508C','\U508D','\U508E','\U508F','\U5090','\U5091','\U5092','\U5093','\U5094','\U5095','\U5096','\U5097','\U5098','\U5099','\U509A','\U509B','\U509C','\U509D','\U509E','\U509F','\U50A0','\U50A1','\U50A2','\U50A3','\U50A4','\U50A5','\U50A6','\U50A7','\U50A8','\U50A9','\U50AA','\U50AB','\U50AC','\U50AD','\U50AE','\U50AF','\U50B0','\U50B1','\U50B2','\U50B3','\U50B4','\U50B5','\U50B6','\U50B7','\U50B8','\U50B9','\U50BA','\U50BB','\U50BC','\U50BD','\U50BE','\U50BF','\U50C0','\U50C1','\U50C2','\U50C3','\U50C4','\U50C5','\U50C6','\U50C7','\U50C8','\U50C9','\U50CA','\U50CB','\U50CC','\U50CD','\U50CE','\U50CF','\U50D0','\U50D1','\U50D2','\U50D3','\U50D4','\U50D5','\U50D6','\U50D7','\U50D8','\U50D9','\U50DA','\U50DB','\U50DC','\U50DD','\U50DE','\U50DF','\U50E0','\U50E1','\U50E2','\U50E3','\U50E4','\U50E5','\U50E6','\U50E7','\U50E8','\U50E9','\U50EA','\U50EB','\U50EC','\U50ED','\U50EE','\U50EF','\U50F0','\U50F1','\U50F2','\U50F3','\U50F4','\U50F5','\U50F6','\U50F7','\U50F8','\U50F9','\U50FA','\U50FB','\U50FC','\U50FD','\U50FE','\U50FF','\U5100','\U5101','\U5102','\U5103','\U5104','\U5105','\U5106','\U5107','\U5108','\U5109','\U510A','\U510B','\U510C','\U510D','\U510E','\U510F','\U5110','\U5111','\U5112','\U5113','\U5114','\U5115','\U5116','\U5117','\U5118','\U5119','\U511A','\U511B','\U511C','\U511D','\U511E','\U511F','\U5120','\U5121','\U5122','\U5123','\U5124','\U5125','\U5126','\U5127','\U5128','\U5129','\U512A','\U512B','\U512C','\U512D','\U512E','\U512F','\U5130','\U5131','\U5132','\U5133','\U5134','\U5135','\U5136','\U5137','\U5138','\U5139','\U513A','\U513B','\U513C','\U513D','\U513E','\U513F','\U5140','\U5141','\U5142','\U5143','\U5144','\U5145','\U5146','\U5147','\U5148','\U5149','\U514A','\U514B','\U514C','\U514D','\U514E','\U514F','\U5150','\U5151','\U5152','\U5153','\U5154','\U5155','\U5156','\U5157','\U5158','\U5159','\U515A','\U515B','\U515C','\U515D','\U515E','\U515F','\U5160','\U5161','\U5162','\U5163','\U5164','\U5165','\U5166','\U5167','\U5168','\U5169','\U516A','\U516B','\U516C','\U516D','\U516E','\U516F','\U5170','\U5171','\U5172','\U5173','\U5174','\U5175','\U5176','\U5177','\U5178','\U5179','\U517A','\U517B','\U517C','\U517D','\U517E','\U517F','\U5180','\U5181','\U5182','\U5183','\U5184','\U5185','\U5186','\U5187','\U5188','\U5189','\U518A','\U518B','\U518C','\U518D','\U518E','\U518F','\U5190','\U5191','\U5192','\U5193','\U5194','\U5195','\U5196','\U5197','\U5198','\U5199','\U519A','\U519B','\U519C','\U519D','\U519E','\U519F','\U51A0','\U51A1','\U51A2','\U51A3','\U51A4','\U51A5','\U51A6','\U51A7','\U51A8','\U51A9','\U51AA','\U51AB','\U51AC','\U51AD','\U51AE','\U51AF','\U51B0','\U51B1','\U51B2','\U51B3','\U51B4','\U51B5','\U51B6','\U51B7','\U51B8','\U51B9','\U51BA','\U51BB','\U51BC','\U51BD','\U51BE','\U51BF','\U51C0','\U51C1','\U51C2','\U51C3','\U51C4','\U51C5','\U51C6','\U51C7','\U51C8','\U51C9','\U51CA','\U51CB','\U51CC','\U51CD','\U51CE','\U51CF','\U51D0','\U51D1','\U51D2','\U51D3','\U51D4','\U51D5','\U51D6','\U51D7','\U51D8','\U51D9','\U51DA','\U51DB','\U51DC','\U51DD','\U51DE','\U51DF','\U51E0','\U51E1','\U51E2','\U51E3','\U51E4','\U51E5','\U51E6','\U51E7','\U51E8','\U51E9','\U51EA','\U51EB','\U51EC','\U51ED','\U51EE','\U51EF','\U51F0','\U51F1','\U51F2','\U51F3','\U51F4','\U51F5','\U51F6','\U51F7','\U51F8','\U51F9','\U51FA','\U51FB','\U51FC','\U51FD','\U51FE','\U51FF','\U5200','\U5201','\U5202','\U5203','\U5204','\U5205','\U5206','\U5207','\U5208','\U5209','\U520A','\U520B','\U520C','\U520D','\U520E','\U520F','\U5210','\U5211','\U5212','\U5213','\U5214','\U5215','\U5216','\U5217','\U5218','\U5219','\U521A','\U521B','\U521C','\U521D','\U521E','\U521F','\U5220','\U5221','\U5222','\U5223','\U5224','\U5225','\U5226','\U5227','\U5228','\U5229','\U522A','\U522B','\U522C','\U522D','\U522E','\U522F','\U5230','\U5231','\U5232','\U5233','\U5234','\U5235','\U5236','\U5237','\U5238','\U5239','\U523A','\U523B','\U523C','\U523D','\U523E','\U523F','\U5240','\U5241','\U5242','\U5243','\U5244','\U5245','\U5246','\U5247','\U5248','\U5249','\U524A','\U524B','\U524C','\U524D','\U524E','\U524F','\U5250','\U5251','\U5252','\U5253','\U5254','\U5255','\U5256','\U5257','\U5258','\U5259','\U525A','\U525B','\U525C','\U525D','\U525E','\U525F','\U5260','\U5261','\U5262','\U5263','\U5264','\U5265','\U5266','\U5267','\U5268','\U5269','\U526A','\U526B','\U526C','\U526D','\U526E','\U526F','\U5270','\U5271','\U5272','\U5273','\U5274','\U5275','\U5276','\U5277','\U5278','\U5279','\U527A','\U527B','\U527C','\U527D','\U527E','\U527F','\U5280','\U5281','\U5282','\U5283','\U5284','\U5285','\U5286','\U5287','\U5288','\U5289','\U528A','\U528B','\U528C','\U528D','\U528E','\U528F','\U5290','\U5291','\U5292','\U5293','\U5294','\U5295','\U5296','\U5297','\U5298','\U5299','\U529A','\U529B','\U529C','\U529D','\U529E','\U529F','\U52A0','\U52A1','\U52A2','\U52A3','\U52A4','\U52A5','\U52A6','\U52A7','\U52A8','\U52A9','\U52AA','\U52AB','\U52AC','\U52AD','\U52AE','\U52AF','\U52B0','\U52B1','\U52B2','\U52B3','\U52B4','\U52B5','\U52B6','\U52B7','\U52B8','\U52B9','\U52BA','\U52BB','\U52BC','\U52BD','\U52BE','\U52BF','\U52C0','\U52C1','\U52C2','\U52C3','\U52C4','\U52C5','\U52C6','\U52C7','\U52C8','\U52C9','\U52CA','\U52CB','\U52CC','\U52CD','\U52CE','\U52CF','\U52D0','\U52D1','\U52D2','\U52D3','\U52D4','\U52D5','\U52D6','\U52D7','\U52D8','\U52D9','\U52DA','\U52DB','\U52DC','\U52DD','\U52DE','\U52DF','\U52E0','\U52E1','\U52E2','\U52E3','\U52E4','\U52E5','\U52E6','\U52E7','\U52E8','\U52E9','\U52EA','\U52EB','\U52EC','\U52ED','\U52EE','\U52EF','\U52F0','\U52F1','\U52F2','\U52F3','\U52F4','\U52F5','\U52F6','\U52F7','\U52F8','\U52F9','\U52FA','\U52FB','\U52FC','\U52FD','\U52FE','\U52FF','\U5300','\U5301','\U5302','\U5303','\U5304','\U5305','\U5306','\U5307','\U5308','\U5309','\U530A','\U530B','\U530C','\U530D','\U530E','\U530F','\U5310','\U5311','\U5312','\U5313','\U5314','\U5315','\U5316','\U5317','\U5318','\U5319','\U531A','\U531B','\U531C','\U531D','\U531E','\U531F','\U5320','\U5321','\U5322','\U5323','\U5324','\U5325','\U5326','\U5327','\U5328','\U5329','\U532A','\U532B','\U532C','\U532D','\U532E','\U532F','\U5330','\U5331','\U5332','\U5333','\U5334','\U5335','\U5336','\U5337','\U5338','\U5339','\U533A','\U533B','\U533C','\U533D','\U533E','\U533F','\U5340','\U5341','\U5342','\U5343','\U5344','\U5345','\U5346','\U5347','\U5348','\U5349','\U534A','\U534B','\U534C','\U534D','\U534E','\U534F','\U5350','\U5351','\U5352','\U5353','\U5354','\U5355','\U5356','\U5357','\U5358','\U5359','\U535A','\U535B','\U535C','\U535D','\U535E','\U535F','\U5360','\U5361','\U5362','\U5363','\U5364','\U5365','\U5366','\U5367','\U5368','\U5369','\U536A','\U536B','\U536C','\U536D','\U536E','\U536F','\U5370','\U5371','\U5372','\U5373','\U5374','\U5375','\U5376','\U5377','\U5378','\U5379','\U537A','\U537B','\U537C','\U537D','\U537E','\U537F','\U5380','\U5381','\U5382','\U5383','\U5384','\U5385','\U5386','\U5387','\U5388','\U5389','\U538A','\U538B','\U538C','\U538D','\U538E','\U538F','\U5390','\U5391','\U5392','\U5393','\U5394','\U5395','\U5396','\U5397','\U5398','\U5399','\U539A','\U539B','\U539C','\U539D','\U539E','\U539F','\U53A0','\U53A1','\U53A2','\U53A3','\U53A4','\U53A5','\U53A6','\U53A7','\U53A8','\U53A9','\U53AA','\U53AB','\U53AC','\U53AD','\U53AE','\U53AF','\U53B0','\U53B1','\U53B2','\U53B3','\U53B4','\U53B5','\U53B6','\U53B7','\U53B8','\U53B9','\U53BA','\U53BB','\U53BC','\U53BD','\U53BE','\U53BF','\U53C0','\U53C1','\U53C2','\U53C3','\U53C4','\U53C5','\U53C6','\U53C7','\U53C8','\U53C9','\U53CA','\U53CB','\U53CC','\U53CD','\U53CE','\U53CF','\U53D0','\U53D1','\U53D2','\U53D3','\U53D4','\U53D5','\U53D6','\U53D7','\U53D8','\U53D9','\U53DA','\U53DB','\U53DC','\U53DD','\U53DE','\U53DF','\U53E0','\U53E1','\U53E2','\U53E3','\U53E4','\U53E5','\U53E6','\U53E7','\U53E8','\U53E9','\U53EA','\U53EB','\U53EC','\U53ED','\U53EE','\U53EF','\U53F0','\U53F1','\U53F2','\U53F3','\U53F4','\U53F5','\U53F6','\U53F7','\U53F8','\U53F9','\U53FA','\U53FB','\U53FC','\U53FD','\U53FE','\U53FF','\U5400','\U5401','\U5402','\U5403','\U5404','\U5405','\U5406','\U5407','\U5408','\U5409','\U540A','\U540B','\U540C','\U540D','\U540E','\U540F','\U5410','\U5411','\U5412','\U5413','\U5414','\U5415','\U5416','\U5417','\U5418','\U5419','\U541A','\U541B','\U541C','\U541D','\U541E','\U541F','\U5420','\U5421','\U5422','\U5423','\U5424','\U5425','\U5426','\U5427','\U5428','\U5429','\U542A','\U542B','\U542C','\U542D','\U542E','\U542F','\U5430','\U5431','\U5432','\U5433','\U5434','\U5435','\U5436','\U5437','\U5438','\U5439','\U543A','\U543B','\U543C','\U543D','\U543E','\U543F','\U5440','\U5441','\U5442','\U5443','\U5444','\U5445','\U5446','\U5447','\U5448','\U5449','\U544A','\U544B','\U544C','\U544D','\U544E','\U544F','\U5450','\U5451','\U5452','\U5453','\U5454','\U5455','\U5456','\U5457','\U5458','\U5459','\U545A','\U545B','\U545C','\U545D','\U545E','\U545F','\U5460','\U5461','\U5462','\U5463','\U5464','\U5465','\U5466','\U5467','\U5468','\U5469','\U546A','\U546B','\U546C','\U546D','\U546E','\U546F','\U5470','\U5471','\U5472','\U5473','\U5474','\U5475','\U5476','\U5477','\U5478','\U5479','\U547A','\U547B','\U547C','\U547D','\U547E','\U547F','\U5480','\U5481','\U5482','\U5483','\U5484','\U5485','\U5486','\U5487','\U5488','\U5489','\U548A','\U548B','\U548C','\U548D','\U548E','\U548F','\U5490','\U5491','\U5492','\U5493','\U5494','\U5495','\U5496','\U5497','\U5498','\U5499','\U549A','\U549B','\U549C','\U549D','\U549E','\U549F','\U54A0','\U54A1','\U54A2','\U54A3','\U54A4','\U54A5','\U54A6','\U54A7','\U54A8','\U54A9','\U54AA','\U54AB','\U54AC','\U54AD','\U54AE','\U54AF','\U54B0','\U54B1','\U54B2','\U54B3','\U54B4','\U54B5','\U54B6','\U54B7','\U54B8','\U54B9','\U54BA','\U54BB','\U54BC','\U54BD','\U54BE','\U54BF','\U54C0','\U54C1','\U54C2','\U54C3','\U54C4','\U54C5','\U54C6','\U54C7','\U54C8','\U54C9','\U54CA','\U54CB','\U54CC','\U54CD','\U54CE','\U54CF','\U54D0','\U54D1','\U54D2','\U54D3','\U54D4','\U54D5','\U54D6','\U54D7','\U54D8','\U54D9','\U54DA','\U54DB','\U54DC','\U54DD','\U54DE','\U54DF','\U54E0','\U54E1','\U54E2','\U54E3','\U54E4','\U54E5','\U54E6','\U54E7','\U54E8','\U54E9','\U54EA','\U54EB','\U54EC','\U54ED','\U54EE','\U54EF','\U54F0','\U54F1','\U54F2','\U54F3','\U54F4','\U54F5','\U54F6','\U54F7','\U54F8','\U54F9','\U54FA','\U54FB','\U54FC','\U54FD','\U54FE','\U54FF','\U5500','\U5501','\U5502','\U5503','\U5504','\U5505','\U5506','\U5507','\U5508','\U5509','\U550A','\U550B','\U550C','\U550D','\U550E','\U550F','\U5510','\U5511','\U5512','\U5513','\U5514','\U5515','\U5516','\U5517','\U5518','\U5519','\U551A','\U551B','\U551C','\U551D','\U551E','\U551F','\U5520','\U5521','\U5522','\U5523','\U5524','\U5525','\U5526','\U5527','\U5528','\U5529','\U552A','\U552B','\U552C','\U552D','\U552E','\U552F','\U5530','\U5531','\U5532','\U5533','\U5534','\U5535','\U5536','\U5537','\U5538','\U5539','\U553A','\U553B','\U553C','\U553D','\U553E','\U553F','\U5540','\U5541','\U5542','\U5543','\U5544','\U5545','\U5546','\U5547','\U5548','\U5549','\U554A','\U554B','\U554C','\U554D','\U554E','\U554F','\U5550','\U5551','\U5552','\U5553','\U5554','\U5555','\U5556','\U5557','\U5558','\U5559','\U555A','\U555B','\U555C','\U555D','\U555E','\U555F','\U5560','\U5561','\U5562','\U5563','\U5564','\U5565','\U5566','\U5567','\U5568','\U5569','\U556A','\U556B','\U556C','\U556D','\U556E','\U556F','\U5570','\U5571','\U5572','\U5573','\U5574','\U5575','\U5576','\U5577','\U5578','\U5579','\U557A','\U557B','\U557C','\U557D','\U557E','\U557F','\U5580','\U5581','\U5582','\U5583','\U5584','\U5585','\U5586','\U5587','\U5588','\U5589','\U558A','\U558B','\U558C','\U558D','\U558E','\U558F','\U5590','\U5591','\U5592','\U5593','\U5594','\U5595','\U5596','\U5597','\U5598','\U5599','\U559A','\U559B','\U559C','\U559D','\U559E','\U559F','\U55A0','\U55A1','\U55A2','\U55A3','\U55A4','\U55A5','\U55A6','\U55A7','\U55A8','\U55A9','\U55AA','\U55AB','\U55AC','\U55AD','\U55AE','\U55AF','\U55B0','\U55B1','\U55B2','\U55B3','\U55B4','\U55B5','\U55B6','\U55B7','\U55B8','\U55B9','\U55BA','\U55BB','\U55BC','\U55BD','\U55BE','\U55BF','\U55C0','\U55C1','\U55C2','\U55C3','\U55C4','\U55C5','\U55C6','\U55C7','\U55C8','\U55C9','\U55CA','\U55CB','\U55CC','\U55CD','\U55CE','\U55CF','\U55D0','\U55D1','\U55D2','\U55D3','\U55D4','\U55D5','\U55D6','\U55D7','\U55D8','\U55D9','\U55DA','\U55DB','\U55DC','\U55DD','\U55DE','\U55DF','\U55E0','\U55E1','\U55E2','\U55E3','\U55E4','\U55E5','\U55E6','\U55E7','\U55E8','\U55E9','\U55EA','\U55EB','\U55EC','\U55ED','\U55EE','\U55EF','\U55F0','\U55F1','\U55F2','\U55F3','\U55F4','\U55F5','\U55F6','\U55F7','\U55F8','\U55F9','\U55FA','\U55FB','\U55FC','\U55FD','\U55FE','\U55FF','\U5600','\U5601','\U5602','\U5603','\U5604','\U5605','\U5606','\U5607','\U5608','\U5609','\U560A','\U560B','\U560C','\U560D','\U560E','\U560F','\U5610','\U5611','\U5612','\U5613','\U5614','\U5615','\U5616','\U5617','\U5618','\U5619','\U561A','\U561B','\U561C','\U561D','\U561E','\U561F','\U5620','\U5621','\U5622','\U5623','\U5624','\U5625','\U5626','\U5627','\U5628','\U5629','\U562A','\U562B','\U562C','\U562D','\U562E','\U562F','\U5630','\U5631','\U5632','\U5633','\U5634','\U5635','\U5636','\U5637','\U5638','\U5639','\U563A','\U563B','\U563C','\U563D','\U563E','\U563F','\U5640','\U5641','\U5642','\U5643','\U5644','\U5645','\U5646','\U5647','\U5648','\U5649','\U564A','\U564B','\U564C','\U564D','\U564E','\U564F','\U5650','\U5651','\U5652','\U5653','\U5654','\U5655','\U5656','\U5657','\U5658','\U5659','\U565A','\U565B','\U565C','\U565D','\U565E','\U565F','\U5660','\U5661','\U5662','\U5663','\U5664','\U5665','\U5666','\U5667','\U5668','\U5669','\U566A','\U566B','\U566C','\U566D','\U566E','\U566F','\U5670','\U5671','\U5672','\U5673','\U5674','\U5675','\U5676','\U5677','\U5678','\U5679','\U567A','\U567B','\U567C','\U567D','\U567E','\U567F','\U5680','\U5681','\U5682','\U5683','\U5684','\U5685','\U5686','\U5687','\U5688','\U5689','\U568A','\U568B','\U568C','\U568D','\U568E','\U568F','\U5690','\U5691','\U5692','\U5693','\U5694','\U5695','\U5696','\U5697','\U5698','\U5699','\U569A','\U569B','\U569C','\U569D','\U569E','\U569F','\U56A0','\U56A1','\U56A2','\U56A3','\U56A4','\U56A5','\U56A6','\U56A7','\U56A8','\U56A9','\U56AA','\U56AB','\U56AC','\U56AD','\U56AE','\U56AF','\U56B0','\U56B1','\U56B2','\U56B3','\U56B4','\U56B5','\U56B6','\U56B7','\U56B8','\U56B9','\U56BA','\U56BB','\U56BC','\U56BD','\U56BE','\U56BF','\U56C0','\U56C1','\U56C2','\U56C3','\U56C4','\U56C5','\U56C6','\U56C7','\U56C8','\U56C9','\U56CA','\U56CB','\U56CC','\U56CD','\U56CE','\U56CF','\U56D0','\U56D1','\U56D2','\U56D3','\U56D4','\U56D5','\U56D6','\U56D7','\U56D8','\U56D9','\U56DA','\U56DB','\U56DC','\U56DD','\U56DE','\U56DF','\U56E0','\U56E1','\U56E2','\U56E3','\U56E4','\U56E5','\U56E6','\U56E7','\U56E8','\U56E9','\U56EA','\U56EB','\U56EC','\U56ED','\U56EE','\U56EF','\U56F0','\U56F1','\U56F2','\U56F3','\U56F4','\U56F5','\U56F6','\U56F7','\U56F8','\U56F9','\U56FA','\U56FB','\U56FC','\U56FD','\U56FE','\U56FF','\U5700','\U5701','\U5702','\U5703','\U5704','\U5705','\U5706','\U5707','\U5708','\U5709','\U570A','\U570B','\U570C','\U570D','\U570E','\U570F','\U5710','\U5711','\U5712','\U5713','\U5714','\U5715','\U5716','\U5717','\U5718','\U5719','\U571A','\U571B','\U571C','\U571D','\U571E','\U571F','\U5720','\U5721','\U5722','\U5723','\U5724','\U5725','\U5726','\U5727','\U5728','\U5729','\U572A','\U572B','\U572C','\U572D','\U572E','\U572F','\U5730','\U5731','\U5732','\U5733','\U5734','\U5735','\U5736','\U5737','\U5738','\U5739','\U573A','\U573B','\U573C','\U573D','\U573E','\U573F','\U5740','\U5741','\U5742','\U5743','\U5744','\U5745','\U5746','\U5747','\U5748','\U5749','\U574A','\U574B','\U574C','\U574D','\U574E','\U574F','\U5750','\U5751','\U5752','\U5753','\U5754','\U5755','\U5756','\U5757','\U5758','\U5759','\U575A','\U575B','\U575C','\U575D','\U575E','\U575F','\U5760','\U5761','\U5762','\U5763','\U5764','\U5765','\U5766','\U5767','\U5768','\U5769','\U576A','\U576B','\U576C','\U576D','\U576E','\U576F','\U5770','\U5771','\U5772','\U5773','\U5774','\U5775','\U5776','\U5777','\U5778','\U5779','\U577A','\U577B','\U577C','\U577D','\U577E','\U577F','\U5780','\U5781','\U5782','\U5783','\U5784','\U5785','\U5786','\U5787','\U5788','\U5789','\U578A','\U578B','\U578C','\U578D','\U578E','\U578F','\U5790','\U5791','\U5792','\U5793','\U5794','\U5795','\U5796','\U5797','\U5798','\U5799','\U579A','\U579B','\U579C','\U579D','\U579E','\U579F','\U57A0','\U57A1','\U57A2','\U57A3','\U57A4','\U57A5','\U57A6','\U57A7','\U57A8','\U57A9','\U57AA','\U57AB','\U57AC','\U57AD','\U57AE','\U57AF','\U57B0','\U57B1','\U57B2','\U57B3','\U57B4','\U57B5','\U57B6','\U57B7','\U57B8','\U57B9','\U57BA','\U57BB','\U57BC','\U57BD','\U57BE','\U57BF','\U57C0','\U57C1','\U57C2','\U57C3','\U57C4','\U57C5','\U57C6','\U57C7','\U57C8','\U57C9','\U57CA','\U57CB','\U57CC','\U57CD','\U57CE','\U57CF','\U57D0','\U57D1','\U57D2','\U57D3','\U57D4','\U57D5','\U57D6','\U57D7','\U57D8','\U57D9','\U57DA','\U57DB','\U57DC','\U57DD','\U57DE','\U57DF','\U57E0','\U57E1','\U57E2','\U57E3','\U57E4','\U57E5','\U57E6','\U57E7','\U57E8','\U57E9','\U57EA','\U57EB','\U57EC','\U57ED','\U57EE','\U57EF','\U57F0','\U57F1','\U57F2','\U57F3','\U57F4','\U57F5','\U57F6','\U57F7','\U57F8','\U57F9','\U57FA','\U57FB','\U57FC','\U57FD','\U57FE','\U57FF','\U5800','\U5801','\U5802','\U5803','\U5804','\U5805','\U5806','\U5807','\U5808','\U5809','\U580A','\U580B','\U580C','\U580D','\U580E','\U580F','\U5810','\U5811','\U5812','\U5813','\U5814','\U5815','\U5816','\U5817','\U5818','\U5819','\U581A','\U581B','\U581C','\U581D','\U581E','\U581F','\U5820','\U5821','\U5822','\U5823','\U5824','\U5825','\U5826','\U5827','\U5828','\U5829','\U582A','\U582B','\U582C','\U582D','\U582E','\U582F','\U5830','\U5831','\U5832','\U5833','\U5834','\U5835','\U5836','\U5837','\U5838','\U5839','\U583A','\U583B','\U583C','\U583D','\U583E','\U583F','\U5840','\U5841','\U5842','\U5843','\U5844','\U5845','\U5846','\U5847','\U5848','\U5849','\U584A','\U584B','\U584C','\U584D','\U584E','\U584F','\U5850','\U5851','\U5852','\U5853','\U5854','\U5855','\U5856','\U5857','\U5858','\U5859','\U585A','\U585B','\U585C','\U585D','\U585E','\U585F','\U5860','\U5861','\U5862','\U5863','\U5864','\U5865','\U5866','\U5867','\U5868','\U5869','\U586A','\U586B','\U586C','\U586D','\U586E','\U586F','\U5870','\U5871','\U5872','\U5873','\U5874','\U5875','\U5876','\U5877','\U5878','\U5879','\U587A','\U587B','\U587C','\U587D','\U587E','\U587F','\U5880','\U5881','\U5882','\U5883','\U5884','\U5885','\U5886','\U5887','\U5888','\U5889','\U588A','\U588B','\U588C','\U588D','\U588E','\U588F','\U5890','\U5891','\U5892','\U5893','\U5894','\U5895','\U5896','\U5897','\U5898','\U5899','\U589A','\U589B','\U589C','\U589D','\U589E','\U589F','\U58A0','\U58A1','\U58A2','\U58A3','\U58A4','\U58A5','\U58A6','\U58A7','\U58A8','\U58A9','\U58AA','\U58AB','\U58AC','\U58AD','\U58AE','\U58AF','\U58B0','\U58B1','\U58B2','\U58B3','\U58B4','\U58B5','\U58B6','\U58B7','\U58B8','\U58B9','\U58BA','\U58BB','\U58BC','\U58BD','\U58BE','\U58BF','\U58C0','\U58C1','\U58C2','\U58C3','\U58C4','\U58C5','\U58C6','\U58C7','\U58C8','\U58C9','\U58CA','\U58CB','\U58CC','\U58CD','\U58CE','\U58CF','\U58D0','\U58D1','\U58D2','\U58D3','\U58D4','\U58D5','\U58D6','\U58D7','\U58D8','\U58D9','\U58DA','\U58DB','\U58DC','\U58DD','\U58DE','\U58DF','\U58E0','\U58E1','\U58E2','\U58E3','\U58E4','\U58E5','\U58E6','\U58E7','\U58E8','\U58E9','\U58EA','\U58EB','\U58EC','\U58ED','\U58EE','\U58EF','\U58F0','\U58F1','\U58F2','\U58F3','\U58F4','\U58F5','\U58F6','\U58F7','\U58F8','\U58F9','\U58FA','\U58FB','\U58FC','\U58FD','\U58FE','\U58FF','\U5900','\U5901','\U5902','\U5903','\U5904','\U5905','\U5906','\U5907','\U5908','\U5909','\U590A','\U590B','\U590C','\U590D','\U590E','\U590F','\U5910','\U5911','\U5912','\U5913','\U5914','\U5915','\U5916','\U5917','\U5918','\U5919','\U591A','\U591B','\U591C','\U591D','\U591E','\U591F','\U5920','\U5921','\U5922','\U5923','\U5924','\U5925','\U5926','\U5927','\U5928','\U5929','\U592A','\U592B','\U592C','\U592D','\U592E','\U592F','\U5930','\U5931','\U5932','\U5933','\U5934','\U5935','\U5936','\U5937','\U5938','\U5939','\U593A','\U593B','\U593C','\U593D','\U593E','\U593F','\U5940','\U5941','\U5942','\U5943','\U5944','\U5945','\U5946','\U5947','\U5948','\U5949','\U594A','\U594B','\U594C','\U594D','\U594E','\U594F','\U5950','\U5951','\U5952','\U5953','\U5954','\U5955','\U5956','\U5957','\U5958','\U5959','\U595A','\U595B','\U595C','\U595D','\U595E','\U595F','\U5960','\U5961','\U5962','\U5963','\U5964','\U5965','\U5966','\U5967','\U5968','\U5969','\U596A','\U596B','\U596C','\U596D','\U596E','\U596F','\U5970','\U5971','\U5972','\U5973','\U5974','\U5975','\U5976','\U5977','\U5978','\U5979','\U597A','\U597B','\U597C','\U597D','\U597E','\U597F','\U5980','\U5981','\U5982','\U5983','\U5984','\U5985','\U5986','\U5987','\U5988','\U5989','\U598A','\U598B','\U598C','\U598D','\U598E','\U598F','\U5990','\U5991','\U5992','\U5993','\U5994','\U5995','\U5996','\U5997','\U5998','\U5999','\U599A','\U599B','\U599C','\U599D','\U599E','\U599F','\U59A0','\U59A1','\U59A2','\U59A3','\U59A4','\U59A5','\U59A6','\U59A7','\U59A8','\U59A9','\U59AA','\U59AB','\U59AC','\U59AD','\U59AE','\U59AF','\U59B0','\U59B1','\U59B2','\U59B3','\U59B4','\U59B5','\U59B6','\U59B7','\U59B8','\U59B9','\U59BA','\U59BB','\U59BC','\U59BD','\U59BE','\U59BF','\U59C0','\U59C1','\U59C2','\U59C3','\U59C4','\U59C5','\U59C6','\U59C7','\U59C8','\U59C9','\U59CA','\U59CB','\U59CC','\U59CD','\U59CE','\U59CF','\U59D0','\U59D1','\U59D2','\U59D3','\U59D4','\U59D5','\U59D6','\U59D7','\U59D8','\U59D9','\U59DA','\U59DB','\U59DC','\U59DD','\U59DE','\U59DF','\U59E0','\U59E1','\U59E2','\U59E3','\U59E4','\U59E5','\U59E6','\U59E7','\U59E8','\U59E9','\U59EA','\U59EB','\U59EC','\U59ED','\U59EE','\U59EF','\U59F0','\U59F1','\U59F2','\U59F3','\U59F4','\U59F5','\U59F6','\U59F7','\U59F8','\U59F9','\U59FA','\U59FB','\U59FC','\U59FD','\U59FE','\U59FF','\U5A00','\U5A01','\U5A02','\U5A03','\U5A04','\U5A05','\U5A06','\U5A07','\U5A08','\U5A09','\U5A0A','\U5A0B','\U5A0C','\U5A0D','\U5A0E','\U5A0F','\U5A10','\U5A11','\U5A12','\U5A13','\U5A14','\U5A15','\U5A16','\U5A17','\U5A18','\U5A19','\U5A1A','\U5A1B','\U5A1C','\U5A1D','\U5A1E','\U5A1F','\U5A20','\U5A21','\U5A22','\U5A23','\U5A24','\U5A25','\U5A26','\U5A27','\U5A28','\U5A29','\U5A2A','\U5A2B','\U5A2C','\U5A2D','\U5A2E','\U5A2F','\U5A30','\U5A31','\U5A32','\U5A33','\U5A34','\U5A35','\U5A36','\U5A37','\U5A38','\U5A39','\U5A3A','\U5A3B','\U5A3C','\U5A3D','\U5A3E','\U5A3F','\U5A40','\U5A41','\U5A42','\U5A43','\U5A44','\U5A45','\U5A46','\U5A47','\U5A48','\U5A49','\U5A4A','\U5A4B','\U5A4C','\U5A4D','\U5A4E','\U5A4F','\U5A50','\U5A51','\U5A52','\U5A53','\U5A54','\U5A55','\U5A56','\U5A57','\U5A58','\U5A59','\U5A5A','\U5A5B','\U5A5C','\U5A5D','\U5A5E','\U5A5F','\U5A60','\U5A61','\U5A62','\U5A63','\U5A64','\U5A65','\U5A66','\U5A67','\U5A68','\U5A69','\U5A6A','\U5A6B','\U5A6C','\U5A6D','\U5A6E','\U5A6F','\U5A70','\U5A71','\U5A72','\U5A73','\U5A74','\U5A75','\U5A76','\U5A77','\U5A78','\U5A79','\U5A7A','\U5A7B','\U5A7C','\U5A7D','\U5A7E','\U5A7F','\U5A80','\U5A81','\U5A82','\U5A83','\U5A84','\U5A85','\U5A86','\U5A87','\U5A88','\U5A89','\U5A8A','\U5A8B','\U5A8C','\U5A8D','\U5A8E','\U5A8F','\U5A90','\U5A91','\U5A92','\U5A93','\U5A94','\U5A95','\U5A96','\U5A97','\U5A98','\U5A99','\U5A9A','\U5A9B','\U5A9C','\U5A9D','\U5A9E','\U5A9F','\U5AA0','\U5AA1','\U5AA2','\U5AA3','\U5AA4','\U5AA5','\U5AA6','\U5AA7','\U5AA8','\U5AA9','\U5AAA','\U5AAB','\U5AAC','\U5AAD','\U5AAE','\U5AAF','\U5AB0','\U5AB1','\U5AB2','\U5AB3','\U5AB4','\U5AB5','\U5AB6','\U5AB7','\U5AB8','\U5AB9','\U5ABA','\U5ABB','\U5ABC','\U5ABD','\U5ABE','\U5ABF','\U5AC0','\U5AC1','\U5AC2','\U5AC3','\U5AC4','\U5AC5','\U5AC6','\U5AC7','\U5AC8','\U5AC9','\U5ACA','\U5ACB','\U5ACC','\U5ACD','\U5ACE','\U5ACF','\U5AD0','\U5AD1','\U5AD2','\U5AD3','\U5AD4','\U5AD5','\U5AD6','\U5AD7','\U5AD8','\U5AD9','\U5ADA','\U5ADB','\U5ADC','\U5ADD','\U5ADE','\U5ADF','\U5AE0','\U5AE1','\U5AE2','\U5AE3','\U5AE4','\U5AE5','\U5AE6','\U5AE7','\U5AE8','\U5AE9','\U5AEA','\U5AEB','\U5AEC','\U5AED','\U5AEE','\U5AEF','\U5AF0','\U5AF1','\U5AF2','\U5AF3','\U5AF4','\U5AF5','\U5AF6','\U5AF7','\U5AF8','\U5AF9','\U5AFA','\U5AFB','\U5AFC','\U5AFD','\U5AFE','\U5AFF','\U5B00','\U5B01','\U5B02','\U5B03','\U5B04','\U5B05','\U5B06','\U5B07','\U5B08','\U5B09','\U5B0A','\U5B0B','\U5B0C','\U5B0D','\U5B0E','\U5B0F','\U5B10','\U5B11','\U5B12','\U5B13','\U5B14','\U5B15','\U5B16','\U5B17','\U5B18','\U5B19','\U5B1A','\U5B1B','\U5B1C','\U5B1D','\U5B1E','\U5B1F','\U5B20','\U5B21','\U5B22','\U5B23','\U5B24','\U5B25','\U5B26','\U5B27','\U5B28','\U5B29','\U5B2A','\U5B2B','\U5B2C','\U5B2D','\U5B2E','\U5B2F','\U5B30','\U5B31','\U5B32','\U5B33','\U5B34','\U5B35','\U5B36','\U5B37','\U5B38','\U5B39','\U5B3A','\U5B3B','\U5B3C','\U5B3D','\U5B3E','\U5B3F','\U5B40','\U5B41','\U5B42','\U5B43','\U5B44','\U5B45','\U5B46','\U5B47','\U5B48','\U5B49','\U5B4A','\U5B4B','\U5B4C','\U5B4D','\U5B4E','\U5B4F','\U5B50','\U5B51','\U5B52','\U5B53','\U5B54','\U5B55','\U5B56','\U5B57','\U5B58','\U5B59','\U5B5A','\U5B5B','\U5B5C','\U5B5D','\U5B5E','\U5B5F','\U5B60','\U5B61','\U5B62','\U5B63','\U5B64','\U5B65','\U5B66','\U5B67','\U5B68','\U5B69','\U5B6A','\U5B6B','\U5B6C','\U5B6D','\U5B6E','\U5B6F','\U5B70','\U5B71','\U5B72','\U5B73','\U5B74','\U5B75','\U5B76','\U5B77','\U5B78','\U5B79','\U5B7A','\U5B7B','\U5B7C','\U5B7D','\U5B7E','\U5B7F','\U5B80','\U5B81','\U5B82','\U5B83','\U5B84','\U5B85','\U5B86','\U5B87','\U5B88','\U5B89','\U5B8A','\U5B8B','\U5B8C','\U5B8D','\U5B8E','\U5B8F','\U5B90','\U5B91','\U5B92','\U5B93','\U5B94','\U5B95','\U5B96','\U5B97','\U5B98','\U5B99','\U5B9A','\U5B9B','\U5B9C','\U5B9D','\U5B9E','\U5B9F','\U5BA0','\U5BA1','\U5BA2','\U5BA3','\U5BA4','\U5BA5','\U5BA6','\U5BA7','\U5BA8','\U5BA9','\U5BAA','\U5BAB','\U5BAC','\U5BAD','\U5BAE','\U5BAF','\U5BB0','\U5BB1','\U5BB2','\U5BB3','\U5BB4','\U5BB5','\U5BB6','\U5BB7','\U5BB8','\U5BB9','\U5BBA','\U5BBB','\U5BBC','\U5BBD','\U5BBE','\U5BBF','\U5BC0','\U5BC1','\U5BC2','\U5BC3','\U5BC4','\U5BC5','\U5BC6','\U5BC7','\U5BC8','\U5BC9','\U5BCA','\U5BCB','\U5BCC','\U5BCD','\U5BCE','\U5BCF','\U5BD0','\U5BD1','\U5BD2','\U5BD3','\U5BD4','\U5BD5','\U5BD6','\U5BD7','\U5BD8','\U5BD9','\U5BDA','\U5BDB','\U5BDC','\U5BDD','\U5BDE','\U5BDF','\U5BE0','\U5BE1','\U5BE2','\U5BE3','\U5BE4','\U5BE5','\U5BE6','\U5BE7','\U5BE8','\U5BE9','\U5BEA','\U5BEB','\U5BEC','\U5BED','\U5BEE','\U5BEF','\U5BF0','\U5BF1','\U5BF2','\U5BF3','\U5BF4','\U5BF5','\U5BF6','\U5BF7','\U5BF8','\U5BF9','\U5BFA','\U5BFB','\U5BFC','\U5BFD','\U5BFE','\U5BFF','\U5C00','\U5C01','\U5C02','\U5C03','\U5C04','\U5C05','\U5C06','\U5C07','\U5C08','\U5C09','\U5C0A','\U5C0B','\U5C0C','\U5C0D','\U5C0E','\U5C0F','\U5C10','\U5C11','\U5C12','\U5C13','\U5C14','\U5C15','\U5C16','\U5C17','\U5C18','\U5C19','\U5C1A','\U5C1B','\U5C1C','\U5C1D','\U5C1E','\U5C1F','\U5C20','\U5C21','\U5C22','\U5C23','\U5C24','\U5C25','\U5C26','\U5C27','\U5C28','\U5C29','\U5C2A','\U5C2B','\U5C2C','\U5C2D','\U5C2E','\U5C2F','\U5C30','\U5C31','\U5C32','\U5C33','\U5C34','\U5C35','\U5C36','\U5C37','\U5C38','\U5C39','\U5C3A','\U5C3B','\U5C3C','\U5C3D','\U5C3E','\U5C3F','\U5C40','\U5C41','\U5C42','\U5C43','\U5C44','\U5C45','\U5C46','\U5C47','\U5C48','\U5C49','\U5C4A','\U5C4B','\U5C4C','\U5C4D','\U5C4E','\U5C4F','\U5C50','\U5C51','\U5C52','\U5C53','\U5C54','\U5C55','\U5C56','\U5C57','\U5C58','\U5C59','\U5C5A','\U5C5B','\U5C5C','\U5C5D','\U5C5E','\U5C5F','\U5C60','\U5C61','\U5C62','\U5C63','\U5C64','\U5C65','\U5C66','\U5C67','\U5C68','\U5C69','\U5C6A','\U5C6B','\U5C6C','\U5C6D','\U5C6E','\U5C6F','\U5C70','\U5C71','\U5C72','\U5C73','\U5C74','\U5C75','\U5C76','\U5C77','\U5C78','\U5C79','\U5C7A','\U5C7B','\U5C7C','\U5C7D','\U5C7E','\U5C7F','\U5C80','\U5C81','\U5C82','\U5C83','\U5C84','\U5C85','\U5C86','\U5C87','\U5C88','\U5C89','\U5C8A','\U5C8B','\U5C8C','\U5C8D','\U5C8E','\U5C8F','\U5C90','\U5C91','\U5C92','\U5C93','\U5C94','\U5C95','\U5C96','\U5C97','\U5C98','\U5C99','\U5C9A','\U5C9B','\U5C9C','\U5C9D','\U5C9E','\U5C9F','\U5CA0','\U5CA1','\U5CA2','\U5CA3','\U5CA4','\U5CA5','\U5CA6','\U5CA7','\U5CA8','\U5CA9','\U5CAA','\U5CAB','\U5CAC','\U5CAD','\U5CAE','\U5CAF','\U5CB0','\U5CB1','\U5CB2','\U5CB3','\U5CB4','\U5CB5','\U5CB6','\U5CB7','\U5CB8','\U5CB9','\U5CBA','\U5CBB','\U5CBC','\U5CBD','\U5CBE','\U5CBF','\U5CC0','\U5CC1','\U5CC2','\U5CC3','\U5CC4','\U5CC5','\U5CC6','\U5CC7','\U5CC8','\U5CC9','\U5CCA','\U5CCB','\U5CCC','\U5CCD','\U5CCE','\U5CCF','\U5CD0','\U5CD1','\U5CD2','\U5CD3','\U5CD4','\U5CD5','\U5CD6','\U5CD7','\U5CD8','\U5CD9','\U5CDA','\U5CDB','\U5CDC','\U5CDD','\U5CDE','\U5CDF','\U5CE0','\U5CE1','\U5CE2','\U5CE3','\U5CE4','\U5CE5','\U5CE6','\U5CE7','\U5CE8','\U5CE9','\U5CEA','\U5CEB','\U5CEC','\U5CED','\U5CEE','\U5CEF','\U5CF0','\U5CF1','\U5CF2','\U5CF3','\U5CF4','\U5CF5','\U5CF6','\U5CF7','\U5CF8','\U5CF9','\U5CFA','\U5CFB','\U5CFC','\U5CFD','\U5CFE','\U5CFF','\U5D00','\U5D01','\U5D02','\U5D03','\U5D04','\U5D05','\U5D06','\U5D07','\U5D08','\U5D09','\U5D0A','\U5D0B','\U5D0C','\U5D0D','\U5D0E','\U5D0F','\U5D10','\U5D11','\U5D12','\U5D13','\U5D14','\U5D15','\U5D16','\U5D17','\U5D18','\U5D19','\U5D1A','\U5D1B','\U5D1C','\U5D1D','\U5D1E','\U5D1F','\U5D20','\U5D21','\U5D22','\U5D23','\U5D24','\U5D25','\U5D26','\U5D27','\U5D28','\U5D29','\U5D2A','\U5D2B','\U5D2C','\U5D2D','\U5D2E','\U5D2F','\U5D30','\U5D31','\U5D32','\U5D33','\U5D34','\U5D35','\U5D36','\U5D37','\U5D38','\U5D39','\U5D3A','\U5D3B','\U5D3C','\U5D3D','\U5D3E','\U5D3F','\U5D40','\U5D41','\U5D42','\U5D43','\U5D44','\U5D45','\U5D46','\U5D47','\U5D48','\U5D49','\U5D4A','\U5D4B','\U5D4C','\U5D4D','\U5D4E','\U5D4F','\U5D50','\U5D51','\U5D52','\U5D53','\U5D54','\U5D55','\U5D56','\U5D57','\U5D58','\U5D59','\U5D5A','\U5D5B','\U5D5C','\U5D5D','\U5D5E','\U5D5F','\U5D60','\U5D61','\U5D62','\U5D63','\U5D64','\U5D65','\U5D66','\U5D67','\U5D68','\U5D69','\U5D6A','\U5D6B','\U5D6C','\U5D6D','\U5D6E','\U5D6F','\U5D70','\U5D71','\U5D72','\U5D73','\U5D74','\U5D75','\U5D76','\U5D77','\U5D78','\U5D79','\U5D7A','\U5D7B','\U5D7C','\U5D7D','\U5D7E','\U5D7F','\U5D80','\U5D81','\U5D82','\U5D83','\U5D84','\U5D85','\U5D86','\U5D87','\U5D88','\U5D89','\U5D8A','\U5D8B','\U5D8C','\U5D8D','\U5D8E','\U5D8F','\U5D90','\U5D91','\U5D92','\U5D93','\U5D94','\U5D95','\U5D96','\U5D97','\U5D98','\U5D99','\U5D9A','\U5D9B','\U5D9C','\U5D9D','\U5D9E','\U5D9F','\U5DA0','\U5DA1','\U5DA2','\U5DA3','\U5DA4','\U5DA5','\U5DA6','\U5DA7','\U5DA8','\U5DA9','\U5DAA','\U5DAB','\U5DAC','\U5DAD','\U5DAE','\U5DAF','\U5DB0','\U5DB1','\U5DB2','\U5DB3','\U5DB4','\U5DB5','\U5DB6','\U5DB7','\U5DB8','\U5DB9','\U5DBA','\U5DBB','\U5DBC','\U5DBD','\U5DBE','\U5DBF','\U5DC0','\U5DC1','\U5DC2','\U5DC3','\U5DC4','\U5DC5','\U5DC6','\U5DC7','\U5DC8','\U5DC9','\U5DCA','\U5DCB','\U5DCC','\U5DCD','\U5DCE','\U5DCF','\U5DD0','\U5DD1','\U5DD2','\U5DD3','\U5DD4','\U5DD5','\U5DD6','\U5DD7','\U5DD8','\U5DD9','\U5DDA','\U5DDB','\U5DDC','\U5DDD','\U5DDE','\U5DDF','\U5DE0','\U5DE1','\U5DE2','\U5DE3','\U5DE4','\U5DE5','\U5DE6','\U5DE7','\U5DE8','\U5DE9','\U5DEA','\U5DEB','\U5DEC','\U5DED','\U5DEE','\U5DEF','\U5DF0','\U5DF1','\U5DF2','\U5DF3','\U5DF4','\U5DF5','\U5DF6','\U5DF7','\U5DF8','\U5DF9','\U5DFA','\U5DFB','\U5DFC','\U5DFD','\U5DFE','\U5DFF','\U5E00','\U5E01','\U5E02','\U5E03','\U5E04','\U5E05','\U5E06','\U5E07','\U5E08','\U5E09','\U5E0A','\U5E0B','\U5E0C','\U5E0D','\U5E0E','\U5E0F','\U5E10','\U5E11','\U5E12','\U5E13','\U5E14','\U5E15','\U5E16','\U5E17','\U5E18','\U5E19','\U5E1A','\U5E1B','\U5E1C','\U5E1D','\U5E1E','\U5E1F','\U5E20','\U5E21','\U5E22','\U5E23','\U5E24','\U5E25','\U5E26','\U5E27','\U5E28','\U5E29','\U5E2A','\U5E2B','\U5E2C','\U5E2D','\U5E2E','\U5E2F','\U5E30','\U5E31','\U5E32','\U5E33','\U5E34','\U5E35','\U5E36','\U5E37','\U5E38','\U5E39','\U5E3A','\U5E3B','\U5E3C','\U5E3D','\U5E3E','\U5E3F','\U5E40','\U5E41','\U5E42','\U5E43','\U5E44','\U5E45','\U5E46','\U5E47','\U5E48','\U5E49','\U5E4A','\U5E4B','\U5E4C','\U5E4D','\U5E4E','\U5E4F','\U5E50','\U5E51','\U5E52','\U5E53','\U5E54','\U5E55','\U5E56','\U5E57','\U5E58','\U5E59','\U5E5A','\U5E5B','\U5E5C','\U5E5D','\U5E5E','\U5E5F','\U5E60','\U5E61','\U5E62','\U5E63','\U5E64','\U5E65','\U5E66','\U5E67','\U5E68','\U5E69','\U5E6A','\U5E6B','\U5E6C','\U5E6D','\U5E6E','\U5E6F','\U5E70','\U5E71','\U5E72','\U5E73','\U5E74','\U5E75','\U5E76','\U5E77','\U5E78','\U5E79','\U5E7A','\U5E7B','\U5E7C','\U5E7D','\U5E7E','\U5E7F','\U5E80','\U5E81','\U5E82','\U5E83','\U5E84','\U5E85','\U5E86','\U5E87','\U5E88','\U5E89','\U5E8A','\U5E8B','\U5E8C','\U5E8D','\U5E8E','\U5E8F','\U5E90','\U5E91','\U5E92','\U5E93','\U5E94','\U5E95','\U5E96','\U5E97','\U5E98','\U5E99','\U5E9A','\U5E9B','\U5E9C','\U5E9D','\U5E9E','\U5E9F','\U5EA0','\U5EA1','\U5EA2','\U5EA3','\U5EA4','\U5EA5','\U5EA6','\U5EA7','\U5EA8','\U5EA9','\U5EAA','\U5EAB','\U5EAC','\U5EAD','\U5EAE','\U5EAF','\U5EB0','\U5EB1','\U5EB2','\U5EB3','\U5EB4','\U5EB5','\U5EB6','\U5EB7','\U5EB8','\U5EB9','\U5EBA','\U5EBB','\U5EBC','\U5EBD','\U5EBE','\U5EBF','\U5EC0','\U5EC1','\U5EC2','\U5EC3','\U5EC4','\U5EC5','\U5EC6','\U5EC7','\U5EC8','\U5EC9','\U5ECA','\U5ECB','\U5ECC','\U5ECD','\U5ECE','\U5ECF','\U5ED0','\U5ED1','\U5ED2','\U5ED3','\U5ED4','\U5ED5','\U5ED6','\U5ED7','\U5ED8','\U5ED9','\U5EDA','\U5EDB','\U5EDC','\U5EDD','\U5EDE','\U5EDF','\U5EE0','\U5EE1','\U5EE2','\U5EE3','\U5EE4','\U5EE5','\U5EE6','\U5EE7','\U5EE8','\U5EE9','\U5EEA','\U5EEB','\U5EEC','\U5EED','\U5EEE','\U5EEF','\U5EF0','\U5EF1','\U5EF2','\U5EF3','\U5EF4','\U5EF5','\U5EF6','\U5EF7','\U5EF8','\U5EF9','\U5EFA','\U5EFB','\U5EFC','\U5EFD','\U5EFE','\U5EFF','\U5F00','\U5F01','\U5F02','\U5F03','\U5F04','\U5F05','\U5F06','\U5F07','\U5F08','\U5F09','\U5F0A','\U5F0B','\U5F0C','\U5F0D','\U5F0E','\U5F0F','\U5F10','\U5F11','\U5F12','\U5F13','\U5F14','\U5F15','\U5F16','\U5F17','\U5F18','\U5F19','\U5F1A','\U5F1B','\U5F1C','\U5F1D','\U5F1E','\U5F1F','\U5F20','\U5F21','\U5F22','\U5F23','\U5F24','\U5F25','\U5F26','\U5F27','\U5F28','\U5F29','\U5F2A','\U5F2B','\U5F2C','\U5F2D','\U5F2E','\U5F2F','\U5F30','\U5F31','\U5F32','\U5F33','\U5F34','\U5F35','\U5F36','\U5F37','\U5F38','\U5F39','\U5F3A','\U5F3B','\U5F3C','\U5F3D','\U5F3E','\U5F3F','\U5F40','\U5F41','\U5F42','\U5F43','\U5F44','\U5F45','\U5F46','\U5F47','\U5F48','\U5F49','\U5F4A','\U5F4B','\U5F4C','\U5F4D','\U5F4E','\U5F4F','\U5F50','\U5F51','\U5F52','\U5F53','\U5F54','\U5F55','\U5F56','\U5F57','\U5F58','\U5F59','\U5F5A','\U5F5B','\U5F5C','\U5F5D','\U5F5E','\U5F5F','\U5F60','\U5F61','\U5F62','\U5F63','\U5F64','\U5F65','\U5F66','\U5F67','\U5F68','\U5F69','\U5F6A','\U5F6B','\U5F6C','\U5F6D','\U5F6E','\U5F6F','\U5F70','\U5F71','\U5F72','\U5F73','\U5F74','\U5F75','\U5F76','\U5F77','\U5F78','\U5F79','\U5F7A','\U5F7B','\U5F7C','\U5F7D','\U5F7E','\U5F7F','\U5F80','\U5F81','\U5F82','\U5F83','\U5F84','\U5F85','\U5F86','\U5F87','\U5F88','\U5F89','\U5F8A','\U5F8B','\U5F8C','\U5F8D','\U5F8E','\U5F8F','\U5F90','\U5F91','\U5F92','\U5F93','\U5F94','\U5F95','\U5F96','\U5F97','\U5F98','\U5F99','\U5F9A','\U5F9B','\U5F9C','\U5F9D','\U5F9E','\U5F9F','\U5FA0','\U5FA1','\U5FA2','\U5FA3','\U5FA4','\U5FA5','\U5FA6','\U5FA7','\U5FA8','\U5FA9','\U5FAA','\U5FAB','\U5FAC','\U5FAD','\U5FAE','\U5FAF','\U5FB0','\U5FB1','\U5FB2','\U5FB3','\U5FB4','\U5FB5','\U5FB6','\U5FB7','\U5FB8','\U5FB9','\U5FBA','\U5FBB','\U5FBC','\U5FBD','\U5FBE','\U5FBF','\U5FC0','\U5FC1','\U5FC2','\U5FC3','\U5FC4','\U5FC5','\U5FC6','\U5FC7','\U5FC8','\U5FC9','\U5FCA','\U5FCB','\U5FCC','\U5FCD','\U5FCE','\U5FCF','\U5FD0','\U5FD1','\U5FD2','\U5FD3','\U5FD4','\U5FD5','\U5FD6','\U5FD7','\U5FD8','\U5FD9','\U5FDA','\U5FDB','\U5FDC','\U5FDD','\U5FDE','\U5FDF','\U5FE0','\U5FE1','\U5FE2','\U5FE3','\U5FE4','\U5FE5','\U5FE6','\U5FE7','\U5FE8','\U5FE9','\U5FEA','\U5FEB','\U5FEC','\U5FED','\U5FEE','\U5FEF','\U5FF0','\U5FF1','\U5FF2','\U5FF3','\U5FF4','\U5FF5','\U5FF6','\U5FF7','\U5FF8','\U5FF9','\U5FFA','\U5FFB','\U5FFC','\U5FFD','\U5FFE','\U5FFF','\U6000','\U6001','\U6002','\U6003','\U6004','\U6005','\U6006','\U6007','\U6008','\U6009','\U600A','\U600B','\U600C','\U600D','\U600E','\U600F','\U6010','\U6011','\U6012','\U6013','\U6014','\U6015','\U6016','\U6017','\U6018','\U6019','\U601A','\U601B','\U601C','\U601D','\U601E','\U601F','\U6020','\U6021','\U6022','\U6023','\U6024','\U6025','\U6026','\U6027','\U6028','\U6029','\U602A','\U602B','\U602C','\U602D','\U602E','\U602F','\U6030','\U6031','\U6032','\U6033','\U6034','\U6035','\U6036','\U6037','\U6038','\U6039','\U603A','\U603B','\U603C','\U603D','\U603E','\U603F','\U6040','\U6041','\U6042','\U6043','\U6044','\U6045','\U6046','\U6047','\U6048','\U6049','\U604A','\U604B','\U604C','\U604D','\U604E','\U604F','\U6050','\U6051','\U6052','\U6053','\U6054','\U6055','\U6056','\U6057','\U6058','\U6059','\U605A','\U605B','\U605C','\U605D','\U605E','\U605F','\U6060','\U6061','\U6062','\U6063','\U6064','\U6065','\U6066','\U6067','\U6068','\U6069','\U606A','\U606B','\U606C','\U606D','\U606E','\U606F','\U6070','\U6071','\U6072','\U6073','\U6074','\U6075','\U6076','\U6077','\U6078','\U6079','\U607A','\U607B','\U607C','\U607D','\U607E','\U607F','\U6080','\U6081','\U6082','\U6083','\U6084','\U6085','\U6086','\U6087','\U6088','\U6089','\U608A','\U608B','\U608C','\U608D','\U608E','\U608F','\U6090','\U6091','\U6092','\U6093','\U6094','\U6095','\U6096','\U6097','\U6098','\U6099','\U609A','\U609B','\U609C','\U609D','\U609E','\U609F','\U60A0','\U60A1','\U60A2','\U60A3','\U60A4','\U60A5','\U60A6','\U60A7','\U60A8','\U60A9','\U60AA','\U60AB','\U60AC','\U60AD','\U60AE','\U60AF','\U60B0','\U60B1','\U60B2','\U60B3','\U60B4','\U60B5','\U60B6','\U60B7','\U60B8','\U60B9','\U60BA','\U60BB','\U60BC','\U60BD','\U60BE','\U60BF','\U60C0','\U60C1','\U60C2','\U60C3','\U60C4','\U60C5','\U60C6','\U60C7','\U60C8','\U60C9','\U60CA','\U60CB','\U60CC','\U60CD','\U60CE','\U60CF','\U60D0','\U60D1','\U60D2','\U60D3','\U60D4','\U60D5','\U60D6','\U60D7','\U60D8','\U60D9','\U60DA','\U60DB','\U60DC','\U60DD','\U60DE','\U60DF','\U60E0','\U60E1','\U60E2','\U60E3','\U60E4','\U60E5','\U60E6','\U60E7','\U60E8','\U60E9','\U60EA','\U60EB','\U60EC','\U60ED','\U60EE','\U60EF','\U60F0','\U60F1','\U60F2','\U60F3','\U60F4','\U60F5','\U60F6','\U60F7','\U60F8','\U60F9','\U60FA','\U60FB','\U60FC','\U60FD','\U60FE','\U60FF','\U6100','\U6101','\U6102','\U6103','\U6104','\U6105','\U6106','\U6107','\U6108','\U6109','\U610A','\U610B','\U610C','\U610D','\U610E','\U610F','\U6110','\U6111','\U6112','\U6113','\U6114','\U6115','\U6116','\U6117','\U6118','\U6119','\U611A','\U611B','\U611C','\U611D','\U611E','\U611F','\U6120','\U6121','\U6122','\U6123','\U6124','\U6125','\U6126','\U6127','\U6128','\U6129','\U612A','\U612B','\U612C','\U612D','\U612E','\U612F','\U6130','\U6131','\U6132','\U6133','\U6134','\U6135','\U6136','\U6137','\U6138','\U6139','\U613A','\U613B','\U613C','\U613D','\U613E','\U613F','\U6140','\U6141','\U6142','\U6143','\U6144','\U6145','\U6146','\U6147','\U6148','\U6149','\U614A','\U614B','\U614C','\U614D','\U614E','\U614F','\U6150','\U6151','\U6152','\U6153','\U6154','\U6155','\U6156','\U6157','\U6158','\U6159','\U615A','\U615B','\U615C','\U615D','\U615E','\U615F','\U6160','\U6161','\U6162','\U6163','\U6164','\U6165','\U6166','\U6167','\U6168','\U6169','\U616A','\U616B','\U616C','\U616D','\U616E','\U616F','\U6170','\U6171','\U6172','\U6173','\U6174','\U6175','\U6176','\U6177','\U6178','\U6179','\U617A','\U617B','\U617C','\U617D','\U617E','\U617F','\U6180','\U6181','\U6182','\U6183','\U6184','\U6185','\U6186','\U6187','\U6188','\U6189','\U618A','\U618B','\U618C','\U618D','\U618E','\U618F','\U6190','\U6191','\U6192','\U6193','\U6194','\U6195','\U6196','\U6197','\U6198','\U6199','\U619A','\U619B','\U619C','\U619D','\U619E','\U619F','\U61A0','\U61A1','\U61A2','\U61A3','\U61A4','\U61A5','\U61A6','\U61A7','\U61A8','\U61A9','\U61AA','\U61AB','\U61AC','\U61AD','\U61AE','\U61AF','\U61B0','\U61B1','\U61B2','\U61B3','\U61B4','\U61B5','\U61B6','\U61B7','\U61B8','\U61B9','\U61BA','\U61BB','\U61BC','\U61BD','\U61BE','\U61BF','\U61C0','\U61C1','\U61C2','\U61C3','\U61C4','\U61C5','\U61C6','\U61C7','\U61C8','\U61C9','\U61CA','\U61CB','\U61CC','\U61CD','\U61CE','\U61CF','\U61D0','\U61D1','\U61D2','\U61D3','\U61D4','\U61D5','\U61D6','\U61D7','\U61D8','\U61D9','\U61DA','\U61DB','\U61DC','\U61DD','\U61DE','\U61DF','\U61E0','\U61E1','\U61E2','\U61E3','\U61E4','\U61E5','\U61E6','\U61E7','\U61E8','\U61E9','\U61EA','\U61EB','\U61EC','\U61ED','\U61EE','\U61EF','\U61F0','\U61F1','\U61F2','\U61F3','\U61F4','\U61F5','\U61F6','\U61F7','\U61F8','\U61F9','\U61FA','\U61FB','\U61FC','\U61FD','\U61FE','\U61FF','\U6200','\U6201','\U6202','\U6203','\U6204','\U6205','\U6206','\U6207','\U6208','\U6209','\U620A','\U620B','\U620C','\U620D','\U620E','\U620F','\U6210','\U6211','\U6212','\U6213','\U6214','\U6215','\U6216','\U6217','\U6218','\U6219','\U621A','\U621B','\U621C','\U621D','\U621E','\U621F','\U6220','\U6221','\U6222','\U6223','\U6224','\U6225','\U6226','\U6227','\U6228','\U6229','\U622A','\U622B','\U622C','\U622D','\U622E','\U622F','\U6230','\U6231','\U6232','\U6233','\U6234','\U6235','\U6236','\U6237','\U6238','\U6239','\U623A','\U623B','\U623C','\U623D','\U623E','\U623F','\U6240','\U6241','\U6242','\U6243','\U6244','\U6245','\U6246','\U6247','\U6248','\U6249','\U624A','\U624B','\U624C','\U624D','\U624E','\U624F','\U6250','\U6251','\U6252','\U6253','\U6254','\U6255','\U6256','\U6257','\U6258','\U6259','\U625A','\U625B','\U625C','\U625D','\U625E','\U625F','\U6260','\U6261','\U6262','\U6263','\U6264','\U6265','\U6266','\U6267','\U6268','\U6269','\U626A','\U626B','\U626C','\U626D','\U626E','\U626F','\U6270','\U6271','\U6272','\U6273','\U6274','\U6275','\U6276','\U6277','\U6278','\U6279','\U627A','\U627B','\U627C','\U627D','\U627E','\U627F','\U6280','\U6281','\U6282','\U6283','\U6284','\U6285','\U6286','\U6287','\U6288','\U6289','\U628A','\U628B','\U628C','\U628D','\U628E','\U628F','\U6290','\U6291','\U6292','\U6293','\U6294','\U6295','\U6296','\U6297','\U6298','\U6299','\U629A','\U629B','\U629C','\U629D','\U629E','\U629F','\U62A0','\U62A1','\U62A2','\U62A3','\U62A4','\U62A5','\U62A6','\U62A7','\U62A8','\U62A9','\U62AA','\U62AB','\U62AC','\U62AD','\U62AE','\U62AF','\U62B0','\U62B1','\U62B2','\U62B3','\U62B4','\U62B5','\U62B6','\U62B7','\U62B8','\U62B9','\U62BA','\U62BB','\U62BC','\U62BD','\U62BE','\U62BF','\U62C0','\U62C1','\U62C2','\U62C3','\U62C4','\U62C5','\U62C6','\U62C7','\U62C8','\U62C9','\U62CA','\U62CB','\U62CC','\U62CD','\U62CE','\U62CF','\U62D0','\U62D1','\U62D2','\U62D3','\U62D4','\U62D5','\U62D6','\U62D7','\U62D8','\U62D9','\U62DA','\U62DB','\U62DC','\U62DD','\U62DE','\U62DF','\U62E0','\U62E1','\U62E2','\U62E3','\U62E4','\U62E5','\U62E6','\U62E7','\U62E8','\U62E9','\U62EA','\U62EB','\U62EC','\U62ED','\U62EE','\U62EF','\U62F0','\U62F1','\U62F2','\U62F3','\U62F4','\U62F5','\U62F6','\U62F7','\U62F8','\U62F9','\U62FA','\U62FB','\U62FC','\U62FD','\U62FE','\U62FF','\U6300','\U6301','\U6302','\U6303','\U6304','\U6305','\U6306','\U6307','\U6308','\U6309','\U630A','\U630B','\U630C','\U630D','\U630E','\U630F','\U6310','\U6311','\U6312','\U6313','\U6314','\U6315','\U6316','\U6317','\U6318','\U6319','\U631A','\U631B','\U631C','\U631D','\U631E','\U631F','\U6320','\U6321','\U6322','\U6323','\U6324','\U6325','\U6326','\U6327','\U6328','\U6329','\U632A','\U632B','\U632C','\U632D','\U632E','\U632F','\U6330','\U6331','\U6332','\U6333','\U6334','\U6335','\U6336','\U6337','\U6338','\U6339','\U633A','\U633B','\U633C','\U633D','\U633E','\U633F','\U6340','\U6341','\U6342','\U6343','\U6344','\U6345','\U6346','\U6347','\U6348','\U6349','\U634A','\U634B','\U634C','\U634D','\U634E','\U634F','\U6350','\U6351','\U6352','\U6353','\U6354','\U6355','\U6356','\U6357','\U6358','\U6359','\U635A','\U635B','\U635C','\U635D','\U635E','\U635F','\U6360','\U6361','\U6362','\U6363','\U6364','\U6365','\U6366','\U6367','\U6368','\U6369','\U636A','\U636B','\U636C','\U636D','\U636E','\U636F','\U6370','\U6371','\U6372','\U6373','\U6374','\U6375','\U6376','\U6377','\U6378','\U6379','\U637A','\U637B','\U637C','\U637D','\U637E','\U637F','\U6380','\U6381','\U6382','\U6383','\U6384','\U6385','\U6386','\U6387','\U6388','\U6389','\U638A','\U638B','\U638C','\U638D','\U638E','\U638F','\U6390','\U6391','\U6392','\U6393','\U6394','\U6395','\U6396','\U6397','\U6398','\U6399','\U639A','\U639B','\U639C','\U639D','\U639E','\U639F','\U63A0','\U63A1','\U63A2','\U63A3','\U63A4','\U63A5','\U63A6','\U63A7','\U63A8','\U63A9','\U63AA','\U63AB','\U63AC','\U63AD','\U63AE','\U63AF','\U63B0','\U63B1','\U63B2','\U63B3','\U63B4','\U63B5','\U63B6','\U63B7','\U63B8','\U63B9','\U63BA','\U63BB','\U63BC','\U63BD','\U63BE','\U63BF','\U63C0','\U63C1','\U63C2','\U63C3','\U63C4','\U63C5','\U63C6','\U63C7','\U63C8','\U63C9','\U63CA','\U63CB','\U63CC','\U63CD','\U63CE','\U63CF','\U63D0','\U63D1','\U63D2','\U63D3','\U63D4','\U63D5','\U63D6','\U63D7','\U63D8','\U63D9','\U63DA','\U63DB','\U63DC','\U63DD','\U63DE','\U63DF','\U63E0','\U63E1','\U63E2','\U63E3','\U63E4','\U63E5','\U63E6','\U63E7','\U63E8','\U63E9','\U63EA','\U63EB','\U63EC','\U63ED','\U63EE','\U63EF','\U63F0','\U63F1','\U63F2','\U63F3','\U63F4','\U63F5','\U63F6','\U63F7','\U63F8','\U63F9','\U63FA','\U63FB','\U63FC','\U63FD','\U63FE','\U63FF','\U6400','\U6401','\U6402','\U6403','\U6404','\U6405','\U6406','\U6407','\U6408','\U6409','\U640A','\U640B','\U640C','\U640D','\U640E','\U640F','\U6410','\U6411','\U6412','\U6413','\U6414','\U6415','\U6416','\U6417','\U6418','\U6419','\U641A','\U641B','\U641C','\U641D','\U641E','\U641F','\U6420','\U6421','\U6422','\U6423','\U6424','\U6425','\U6426','\U6427','\U6428','\U6429','\U642A','\U642B','\U642C','\U642D','\U642E','\U642F','\U6430','\U6431','\U6432','\U6433','\U6434','\U6435','\U6436','\U6437','\U6438','\U6439','\U643A','\U643B','\U643C','\U643D','\U643E','\U643F','\U6440','\U6441','\U6442','\U6443','\U6444','\U6445','\U6446','\U6447','\U6448','\U6449','\U644A','\U644B','\U644C','\U644D','\U644E','\U644F','\U6450','\U6451','\U6452','\U6453','\U6454','\U6455','\U6456','\U6457','\U6458','\U6459','\U645A','\U645B','\U645C','\U645D','\U645E','\U645F','\U6460','\U6461','\U6462','\U6463','\U6464','\U6465','\U6466','\U6467','\U6468','\U6469','\U646A','\U646B','\U646C','\U646D','\U646E','\U646F','\U6470','\U6471','\U6472','\U6473','\U6474','\U6475','\U6476','\U6477','\U6478','\U6479','\U647A','\U647B','\U647C','\U647D','\U647E','\U647F','\U6480','\U6481','\U6482','\U6483','\U6484','\U6485','\U6486','\U6487','\U6488','\U6489','\U648A','\U648B','\U648C','\U648D','\U648E','\U648F','\U6490','\U6491','\U6492','\U6493','\U6494','\U6495','\U6496','\U6497','\U6498','\U6499','\U649A','\U649B','\U649C','\U649D','\U649E','\U649F','\U64A0','\U64A1','\U64A2','\U64A3','\U64A4','\U64A5','\U64A6','\U64A7','\U64A8','\U64A9','\U64AA','\U64AB','\U64AC','\U64AD','\U64AE','\U64AF','\U64B0','\U64B1','\U64B2','\U64B3','\U64B4','\U64B5','\U64B6','\U64B7','\U64B8','\U64B9','\U64BA','\U64BB','\U64BC','\U64BD','\U64BE','\U64BF','\U64C0','\U64C1','\U64C2','\U64C3','\U64C4','\U64C5','\U64C6','\U64C7','\U64C8','\U64C9','\U64CA','\U64CB','\U64CC','\U64CD','\U64CE','\U64CF','\U64D0','\U64D1','\U64D2','\U64D3','\U64D4','\U64D5','\U64D6','\U64D7','\U64D8','\U64D9','\U64DA','\U64DB','\U64DC','\U64DD','\U64DE','\U64DF','\U64E0','\U64E1','\U64E2','\U64E3','\U64E4','\U64E5','\U64E6','\U64E7','\U64E8','\U64E9','\U64EA','\U64EB','\U64EC','\U64ED','\U64EE','\U64EF','\U64F0','\U64F1','\U64F2','\U64F3','\U64F4','\U64F5','\U64F6','\U64F7','\U64F8','\U64F9','\U64FA','\U64FB','\U64FC','\U64FD','\U64FE','\U64FF','\U6500','\U6501','\U6502','\U6503','\U6504','\U6505','\U6506','\U6507','\U6508','\U6509','\U650A','\U650B','\U650C','\U650D','\U650E','\U650F','\U6510','\U6511','\U6512','\U6513','\U6514','\U6515','\U6516','\U6517','\U6518','\U6519','\U651A','\U651B','\U651C','\U651D','\U651E','\U651F','\U6520','\U6521','\U6522','\U6523','\U6524','\U6525','\U6526','\U6527','\U6528','\U6529','\U652A','\U652B','\U652C','\U652D','\U652E','\U652F','\U6530','\U6531','\U6532','\U6533','\U6534','\U6535','\U6536','\U6537','\U6538','\U6539','\U653A','\U653B','\U653C','\U653D','\U653E','\U653F','\U6540','\U6541','\U6542','\U6543','\U6544','\U6545','\U6546','\U6547','\U6548','\U6549','\U654A','\U654B','\U654C','\U654D','\U654E','\U654F','\U6550','\U6551','\U6552','\U6553','\U6554','\U6555','\U6556','\U6557','\U6558','\U6559','\U655A','\U655B','\U655C','\U655D','\U655E','\U655F','\U6560','\U6561','\U6562','\U6563','\U6564','\U6565','\U6566','\U6567','\U6568','\U6569','\U656A','\U656B','\U656C','\U656D','\U656E','\U656F','\U6570','\U6571','\U6572','\U6573','\U6574','\U6575','\U6576','\U6577','\U6578','\U6579','\U657A','\U657B','\U657C','\U657D','\U657E','\U657F','\U6580','\U6581','\U6582','\U6583','\U6584','\U6585','\U6586','\U6587','\U6588','\U6589','\U658A','\U658B','\U658C','\U658D','\U658E','\U658F','\U6590','\U6591','\U6592','\U6593','\U6594','\U6595','\U6596','\U6597','\U6598','\U6599','\U659A','\U659B','\U659C','\U659D','\U659E','\U659F','\U65A0','\U65A1','\U65A2','\U65A3','\U65A4','\U65A5','\U65A6','\U65A7','\U65A8','\U65A9','\U65AA','\U65AB','\U65AC','\U65AD','\U65AE','\U65AF','\U65B0','\U65B1','\U65B2','\U65B3','\U65B4','\U65B5','\U65B6','\U65B7','\U65B8','\U65B9','\U65BA','\U65BB','\U65BC','\U65BD','\U65BE','\U65BF','\U65C0','\U65C1','\U65C2','\U65C3','\U65C4','\U65C5','\U65C6','\U65C7','\U65C8','\U65C9','\U65CA','\U65CB','\U65CC','\U65CD','\U65CE','\U65CF','\U65D0','\U65D1','\U65D2','\U65D3','\U65D4','\U65D5','\U65D6','\U65D7','\U65D8','\U65D9','\U65DA','\U65DB','\U65DC','\U65DD','\U65DE','\U65DF','\U65E0','\U65E1','\U65E2','\U65E3','\U65E4','\U65E5','\U65E6','\U65E7','\U65E8','\U65E9','\U65EA','\U65EB','\U65EC','\U65ED','\U65EE','\U65EF','\U65F0','\U65F1','\U65F2','\U65F3','\U65F4','\U65F5','\U65F6','\U65F7','\U65F8','\U65F9','\U65FA','\U65FB','\U65FC','\U65FD','\U65FE','\U65FF','\U6600','\U6601','\U6602','\U6603','\U6604','\U6605','\U6606','\U6607','\U6608','\U6609','\U660A','\U660B','\U660C','\U660D','\U660E','\U660F','\U6610','\U6611','\U6612','\U6613','\U6614','\U6615','\U6616','\U6617','\U6618','\U6619','\U661A','\U661B','\U661C','\U661D','\U661E','\U661F','\U6620','\U6621','\U6622','\U6623','\U6624','\U6625','\U6626','\U6627','\U6628','\U6629','\U662A','\U662B','\U662C','\U662D','\U662E','\U662F','\U6630','\U6631','\U6632','\U6633','\U6634','\U6635','\U6636','\U6637','\U6638','\U6639','\U663A','\U663B','\U663C','\U663D','\U663E','\U663F','\U6640','\U6641','\U6642','\U6643','\U6644','\U6645','\U6646','\U6647','\U6648','\U6649','\U664A','\U664B','\U664C','\U664D','\U664E','\U664F','\U6650','\U6651','\U6652','\U6653','\U6654','\U6655','\U6656','\U6657','\U6658','\U6659','\U665A','\U665B','\U665C','\U665D','\U665E','\U665F','\U6660','\U6661','\U6662','\U6663','\U6664','\U6665','\U6666','\U6667','\U6668','\U6669','\U666A','\U666B','\U666C','\U666D','\U666E','\U666F','\U6670','\U6671','\U6672','\U6673','\U6674','\U6675','\U6676','\U6677','\U6678','\U6679','\U667A','\U667B','\U667C','\U667D','\U667E','\U667F','\U6680','\U6681','\U6682','\U6683','\U6684','\U6685','\U6686','\U6687','\U6688','\U6689','\U668A','\U668B','\U668C','\U668D','\U668E','\U668F','\U6690','\U6691','\U6692','\U6693','\U6694','\U6695','\U6696','\U6697','\U6698','\U6699','\U669A','\U669B','\U669C','\U669D','\U669E','\U669F','\U66A0','\U66A1','\U66A2','\U66A3','\U66A4','\U66A5','\U66A6','\U66A7','\U66A8','\U66A9','\U66AA','\U66AB','\U66AC','\U66AD','\U66AE','\U66AF','\U66B0','\U66B1','\U66B2','\U66B3','\U66B4','\U66B5','\U66B6','\U66B7','\U66B8','\U66B9','\U66BA','\U66BB','\U66BC','\U66BD','\U66BE','\U66BF','\U66C0','\U66C1','\U66C2','\U66C3','\U66C4','\U66C5','\U66C6','\U66C7','\U66C8','\U66C9','\U66CA','\U66CB','\U66CC','\U66CD','\U66CE','\U66CF','\U66D0','\U66D1','\U66D2','\U66D3','\U66D4','\U66D5','\U66D6','\U66D7','\U66D8','\U66D9','\U66DA','\U66DB','\U66DC','\U66DD','\U66DE','\U66DF','\U66E0','\U66E1','\U66E2','\U66E3','\U66E4','\U66E5','\U66E6','\U66E7','\U66E8','\U66E9','\U66EA','\U66EB','\U66EC','\U66ED','\U66EE','\U66EF','\U66F0','\U66F1','\U66F2','\U66F3','\U66F4','\U66F5','\U66F6','\U66F7','\U66F8','\U66F9','\U66FA','\U66FB','\U66FC','\U66FD','\U66FE','\U66FF','\U6700','\U6701','\U6702','\U6703','\U6704','\U6705','\U6706','\U6707','\U6708','\U6709','\U670A','\U670B','\U670C','\U670D','\U670E','\U670F','\U6710','\U6711','\U6712','\U6713','\U6714','\U6715','\U6716','\U6717','\U6718','\U6719','\U671A','\U671B','\U671C','\U671D','\U671E','\U671F','\U6720','\U6721','\U6722','\U6723','\U6724','\U6725','\U6726','\U6727','\U6728','\U6729','\U672A','\U672B','\U672C','\U672D','\U672E','\U672F','\U6730','\U6731','\U6732','\U6733','\U6734','\U6735','\U6736','\U6737','\U6738','\U6739','\U673A','\U673B','\U673C','\U673D','\U673E','\U673F','\U6740','\U6741','\U6742','\U6743','\U6744','\U6745','\U6746','\U6747','\U6748','\U6749','\U674A','\U674B','\U674C','\U674D','\U674E','\U674F','\U6750','\U6751','\U6752','\U6753','\U6754','\U6755','\U6756','\U6757','\U6758','\U6759','\U675A','\U675B','\U675C','\U675D','\U675E','\U675F','\U6760','\U6761','\U6762','\U6763','\U6764','\U6765','\U6766','\U6767','\U6768','\U6769','\U676A','\U676B','\U676C','\U676D','\U676E','\U676F','\U6770','\U6771','\U6772','\U6773','\U6774','\U6775','\U6776','\U6777','\U6778','\U6779','\U677A','\U677B','\U677C','\U677D','\U677E','\U677F','\U6780','\U6781','\U6782','\U6783','\U6784','\U6785','\U6786','\U6787','\U6788','\U6789','\U678A','\U678B','\U678C','\U678D','\U678E','\U678F','\U6790','\U6791','\U6792','\U6793','\U6794','\U6795','\U6796','\U6797','\U6798','\U6799','\U679A','\U679B','\U679C','\U679D','\U679E','\U679F','\U67A0','\U67A1','\U67A2','\U67A3','\U67A4','\U67A5','\U67A6','\U67A7','\U67A8','\U67A9','\U67AA','\U67AB','\U67AC','\U67AD','\U67AE','\U67AF','\U67B0','\U67B1','\U67B2','\U67B3','\U67B4','\U67B5','\U67B6','\U67B7','\U67B8','\U67B9','\U67BA','\U67BB','\U67BC','\U67BD','\U67BE','\U67BF','\U67C0','\U67C1','\U67C2','\U67C3','\U67C4','\U67C5','\U67C6','\U67C7','\U67C8','\U67C9','\U67CA','\U67CB','\U67CC','\U67CD','\U67CE','\U67CF','\U67D0','\U67D1','\U67D2','\U67D3','\U67D4','\U67D5','\U67D6','\U67D7','\U67D8','\U67D9','\U67DA','\U67DB','\U67DC','\U67DD','\U67DE','\U67DF','\U67E0','\U67E1','\U67E2','\U67E3','\U67E4','\U67E5','\U67E6','\U67E7','\U67E8','\U67E9','\U67EA','\U67EB','\U67EC','\U67ED','\U67EE','\U67EF','\U67F0','\U67F1','\U67F2','\U67F3','\U67F4','\U67F5','\U67F6','\U67F7','\U67F8','\U67F9','\U67FA','\U67FB','\U67FC','\U67FD','\U67FE','\U67FF','\U6800','\U6801','\U6802','\U6803','\U6804','\U6805','\U6806','\U6807','\U6808','\U6809','\U680A','\U680B','\U680C','\U680D','\U680E','\U680F','\U6810','\U6811','\U6812','\U6813','\U6814','\U6815','\U6816','\U6817','\U6818','\U6819','\U681A','\U681B','\U681C','\U681D','\U681E','\U681F','\U6820','\U6821','\U6822','\U6823','\U6824','\U6825','\U6826','\U6827','\U6828','\U6829','\U682A','\U682B','\U682C','\U682D','\U682E','\U682F','\U6830','\U6831','\U6832','\U6833','\U6834','\U6835','\U6836','\U6837','\U6838','\U6839','\U683A','\U683B','\U683C','\U683D','\U683E','\U683F','\U6840','\U6841','\U6842','\U6843','\U6844','\U6845','\U6846','\U6847','\U6848','\U6849','\U684A','\U684B','\U684C','\U684D','\U684E','\U684F','\U6850','\U6851','\U6852','\U6853','\U6854','\U6855','\U6856','\U6857','\U6858','\U6859','\U685A','\U685B','\U685C','\U685D','\U685E','\U685F','\U6860','\U6861','\U6862','\U6863','\U6864','\U6865','\U6866','\U6867','\U6868','\U6869','\U686A','\U686B','\U686C','\U686D','\U686E','\U686F','\U6870','\U6871','\U6872','\U6873','\U6874','\U6875','\U6876','\U6877','\U6878','\U6879','\U687A','\U687B','\U687C','\U687D','\U687E','\U687F','\U6880','\U6881','\U6882','\U6883','\U6884','\U6885','\U6886','\U6887','\U6888','\U6889','\U688A','\U688B','\U688C','\U688D','\U688E','\U688F','\U6890','\U6891','\U6892','\U6893','\U6894','\U6895','\U6896','\U6897','\U6898','\U6899','\U689A','\U689B','\U689C','\U689D','\U689E','\U689F','\U68A0','\U68A1','\U68A2','\U68A3','\U68A4','\U68A5','\U68A6','\U68A7','\U68A8','\U68A9','\U68AA','\U68AB','\U68AC','\U68AD','\U68AE','\U68AF','\U68B0','\U68B1','\U68B2','\U68B3','\U68B4','\U68B5','\U68B6','\U68B7','\U68B8','\U68B9','\U68BA','\U68BB','\U68BC','\U68BD','\U68BE','\U68BF','\U68C0','\U68C1','\U68C2','\U68C3','\U68C4','\U68C5','\U68C6','\U68C7','\U68C8','\U68C9','\U68CA','\U68CB','\U68CC','\U68CD','\U68CE','\U68CF','\U68D0','\U68D1','\U68D2','\U68D3','\U68D4','\U68D5','\U68D6','\U68D7','\U68D8','\U68D9','\U68DA','\U68DB','\U68DC','\U68DD','\U68DE','\U68DF','\U68E0','\U68E1','\U68E2','\U68E3','\U68E4','\U68E5','\U68E6','\U68E7','\U68E8','\U68E9','\U68EA','\U68EB','\U68EC','\U68ED','\U68EE','\U68EF','\U68F0','\U68F1','\U68F2','\U68F3','\U68F4','\U68F5','\U68F6','\U68F7','\U68F8','\U68F9','\U68FA','\U68FB','\U68FC','\U68FD','\U68FE','\U68FF','\U6900','\U6901','\U6902','\U6903','\U6904','\U6905','\U6906','\U6907','\U6908','\U6909','\U690A','\U690B','\U690C','\U690D','\U690E','\U690F','\U6910','\U6911','\U6912','\U6913','\U6914','\U6915','\U6916','\U6917','\U6918','\U6919','\U691A','\U691B','\U691C','\U691D','\U691E','\U691F','\U6920','\U6921','\U6922','\U6923','\U6924','\U6925','\U6926','\U6927','\U6928','\U6929','\U692A','\U692B','\U692C','\U692D','\U692E','\U692F','\U6930','\U6931','\U6932','\U6933','\U6934','\U6935','\U6936','\U6937','\U6938','\U6939','\U693A','\U693B','\U693C','\U693D','\U693E','\U693F','\U6940','\U6941','\U6942','\U6943','\U6944','\U6945','\U6946','\U6947','\U6948','\U6949','\U694A','\U694B','\U694C','\U694D','\U694E','\U694F','\U6950','\U6951','\U6952','\U6953','\U6954','\U6955','\U6956','\U6957','\U6958','\U6959','\U695A','\U695B','\U695C','\U695D','\U695E','\U695F','\U6960','\U6961','\U6962','\U6963','\U6964','\U6965','\U6966','\U6967','\U6968','\U6969','\U696A','\U696B','\U696C','\U696D','\U696E','\U696F','\U6970','\U6971','\U6972','\U6973','\U6974','\U6975','\U6976','\U6977','\U6978','\U6979','\U697A','\U697B','\U697C','\U697D','\U697E','\U697F','\U6980','\U6981','\U6982','\U6983','\U6984','\U6985','\U6986','\U6987','\U6988','\U6989','\U698A','\U698B','\U698C','\U698D','\U698E','\U698F','\U6990','\U6991','\U6992','\U6993','\U6994','\U6995','\U6996','\U6997','\U6998','\U6999','\U699A','\U699B','\U699C','\U699D','\U699E','\U699F','\U69A0','\U69A1','\U69A2','\U69A3','\U69A4','\U69A5','\U69A6','\U69A7','\U69A8','\U69A9','\U69AA','\U69AB','\U69AC','\U69AD','\U69AE','\U69AF','\U69B0','\U69B1','\U69B2','\U69B3','\U69B4','\U69B5','\U69B6','\U69B7','\U69B8','\U69B9','\U69BA','\U69BB','\U69BC','\U69BD','\U69BE','\U69BF','\U69C0','\U69C1','\U69C2','\U69C3','\U69C4','\U69C5','\U69C6','\U69C7','\U69C8','\U69C9','\U69CA','\U69CB','\U69CC','\U69CD','\U69CE','\U69CF','\U69D0','\U69D1','\U69D2','\U69D3','\U69D4','\U69D5','\U69D6','\U69D7','\U69D8','\U69D9','\U69DA','\U69DB','\U69DC','\U69DD','\U69DE','\U69DF','\U69E0','\U69E1','\U69E2','\U69E3','\U69E4','\U69E5','\U69E6','\U69E7','\U69E8','\U69E9','\U69EA','\U69EB','\U69EC','\U69ED','\U69EE','\U69EF','\U69F0','\U69F1','\U69F2','\U69F3','\U69F4','\U69F5','\U69F6','\U69F7','\U69F8','\U69F9','\U69FA','\U69FB','\U69FC','\U69FD','\U69FE','\U69FF','\U6A00','\U6A01','\U6A02','\U6A03','\U6A04','\U6A05','\U6A06','\U6A07','\U6A08','\U6A09','\U6A0A','\U6A0B','\U6A0C','\U6A0D','\U6A0E','\U6A0F','\U6A10','\U6A11','\U6A12','\U6A13','\U6A14','\U6A15','\U6A16','\U6A17','\U6A18','\U6A19','\U6A1A','\U6A1B','\U6A1C','\U6A1D','\U6A1E','\U6A1F','\U6A20','\U6A21','\U6A22','\U6A23','\U6A24','\U6A25','\U6A26','\U6A27','\U6A28','\U6A29','\U6A2A','\U6A2B','\U6A2C','\U6A2D','\U6A2E','\U6A2F','\U6A30','\U6A31','\U6A32','\U6A33','\U6A34','\U6A35','\U6A36','\U6A37','\U6A38','\U6A39','\U6A3A','\U6A3B','\U6A3C','\U6A3D','\U6A3E','\U6A3F','\U6A40','\U6A41','\U6A42','\U6A43','\U6A44','\U6A45','\U6A46','\U6A47','\U6A48','\U6A49','\U6A4A','\U6A4B','\U6A4C','\U6A4D','\U6A4E','\U6A4F','\U6A50','\U6A51','\U6A52','\U6A53','\U6A54','\U6A55','\U6A56','\U6A57','\U6A58','\U6A59','\U6A5A','\U6A5B','\U6A5C','\U6A5D','\U6A5E','\U6A5F','\U6A60','\U6A61','\U6A62','\U6A63','\U6A64','\U6A65','\U6A66','\U6A67','\U6A68','\U6A69','\U6A6A','\U6A6B','\U6A6C','\U6A6D','\U6A6E','\U6A6F','\U6A70','\U6A71','\U6A72','\U6A73','\U6A74','\U6A75','\U6A76','\U6A77','\U6A78','\U6A79','\U6A7A','\U6A7B','\U6A7C','\U6A7D','\U6A7E','\U6A7F','\U6A80','\U6A81','\U6A82','\U6A83','\U6A84','\U6A85','\U6A86','\U6A87','\U6A88','\U6A89','\U6A8A','\U6A8B','\U6A8C','\U6A8D','\U6A8E','\U6A8F','\U6A90','\U6A91','\U6A92','\U6A93','\U6A94','\U6A95','\U6A96','\U6A97','\U6A98','\U6A99','\U6A9A','\U6A9B','\U6A9C','\U6A9D','\U6A9E','\U6A9F','\U6AA0','\U6AA1','\U6AA2','\U6AA3','\U6AA4','\U6AA5','\U6AA6','\U6AA7','\U6AA8','\U6AA9','\U6AAA','\U6AAB','\U6AAC','\U6AAD','\U6AAE','\U6AAF','\U6AB0','\U6AB1','\U6AB2','\U6AB3','\U6AB4','\U6AB5','\U6AB6','\U6AB7','\U6AB8','\U6AB9','\U6ABA','\U6ABB','\U6ABC','\U6ABD','\U6ABE','\U6ABF','\U6AC0','\U6AC1','\U6AC2','\U6AC3','\U6AC4','\U6AC5','\U6AC6','\U6AC7','\U6AC8','\U6AC9','\U6ACA','\U6ACB','\U6ACC','\U6ACD','\U6ACE','\U6ACF','\U6AD0','\U6AD1','\U6AD2','\U6AD3','\U6AD4','\U6AD5','\U6AD6','\U6AD7','\U6AD8','\U6AD9','\U6ADA','\U6ADB','\U6ADC','\U6ADD','\U6ADE','\U6ADF','\U6AE0','\U6AE1','\U6AE2','\U6AE3','\U6AE4','\U6AE5','\U6AE6','\U6AE7','\U6AE8','\U6AE9','\U6AEA','\U6AEB','\U6AEC','\U6AED','\U6AEE','\U6AEF','\U6AF0','\U6AF1','\U6AF2','\U6AF3','\U6AF4','\U6AF5','\U6AF6','\U6AF7','\U6AF8','\U6AF9','\U6AFA','\U6AFB','\U6AFC','\U6AFD','\U6AFE','\U6AFF','\U6B00','\U6B01','\U6B02','\U6B03','\U6B04','\U6B05','\U6B06','\U6B07','\U6B08','\U6B09','\U6B0A','\U6B0B','\U6B0C','\U6B0D','\U6B0E','\U6B0F','\U6B10','\U6B11','\U6B12','\U6B13','\U6B14','\U6B15','\U6B16','\U6B17','\U6B18','\U6B19','\U6B1A','\U6B1B','\U6B1C','\U6B1D','\U6B1E','\U6B1F','\U6B20','\U6B21','\U6B22','\U6B23','\U6B24','\U6B25','\U6B26','\U6B27','\U6B28','\U6B29','\U6B2A','\U6B2B','\U6B2C','\U6B2D','\U6B2E','\U6B2F','\U6B30','\U6B31','\U6B32','\U6B33','\U6B34','\U6B35','\U6B36','\U6B37','\U6B38','\U6B39','\U6B3A','\U6B3B','\U6B3C','\U6B3D','\U6B3E','\U6B3F','\U6B40','\U6B41','\U6B42','\U6B43','\U6B44','\U6B45','\U6B46','\U6B47','\U6B48','\U6B49','\U6B4A','\U6B4B','\U6B4C','\U6B4D','\U6B4E','\U6B4F','\U6B50','\U6B51','\U6B52','\U6B53','\U6B54','\U6B55','\U6B56','\U6B57','\U6B58','\U6B59','\U6B5A','\U6B5B','\U6B5C','\U6B5D','\U6B5E','\U6B5F','\U6B60','\U6B61','\U6B62','\U6B63','\U6B64','\U6B65','\U6B66','\U6B67','\U6B68','\U6B69','\U6B6A','\U6B6B','\U6B6C','\U6B6D','\U6B6E','\U6B6F','\U6B70','\U6B71','\U6B72','\U6B73','\U6B74','\U6B75','\U6B76','\U6B77','\U6B78','\U6B79','\U6B7A','\U6B7B','\U6B7C','\U6B7D','\U6B7E','\U6B7F','\U6B80','\U6B81','\U6B82','\U6B83','\U6B84','\U6B85','\U6B86','\U6B87','\U6B88','\U6B89','\U6B8A','\U6B8B','\U6B8C','\U6B8D','\U6B8E','\U6B8F','\U6B90','\U6B91','\U6B92','\U6B93','\U6B94','\U6B95','\U6B96','\U6B97','\U6B98','\U6B99','\U6B9A','\U6B9B','\U6B9C','\U6B9D','\U6B9E','\U6B9F','\U6BA0','\U6BA1','\U6BA2','\U6BA3','\U6BA4','\U6BA5','\U6BA6','\U6BA7','\U6BA8','\U6BA9','\U6BAA','\U6BAB','\U6BAC','\U6BAD','\U6BAE','\U6BAF','\U6BB0','\U6BB1','\U6BB2','\U6BB3','\U6BB4','\U6BB5','\U6BB6','\U6BB7','\U6BB8','\U6BB9','\U6BBA','\U6BBB','\U6BBC','\U6BBD','\U6BBE','\U6BBF','\U6BC0','\U6BC1','\U6BC2','\U6BC3','\U6BC4','\U6BC5','\U6BC6','\U6BC7','\U6BC8','\U6BC9','\U6BCA','\U6BCB','\U6BCC','\U6BCD','\U6BCE','\U6BCF','\U6BD0','\U6BD1','\U6BD2','\U6BD3','\U6BD4','\U6BD5','\U6BD6','\U6BD7','\U6BD8','\U6BD9','\U6BDA','\U6BDB','\U6BDC','\U6BDD','\U6BDE','\U6BDF','\U6BE0','\U6BE1','\U6BE2','\U6BE3','\U6BE4','\U6BE5','\U6BE6','\U6BE7','\U6BE8','\U6BE9','\U6BEA','\U6BEB','\U6BEC','\U6BED','\U6BEE','\U6BEF','\U6BF0','\U6BF1','\U6BF2','\U6BF3','\U6BF4','\U6BF5','\U6BF6','\U6BF7','\U6BF8','\U6BF9','\U6BFA','\U6BFB','\U6BFC','\U6BFD','\U6BFE','\U6BFF','\U6C00','\U6C01','\U6C02','\U6C03','\U6C04','\U6C05','\U6C06','\U6C07','\U6C08','\U6C09','\U6C0A','\U6C0B','\U6C0C','\U6C0D','\U6C0E','\U6C0F','\U6C10','\U6C11','\U6C12','\U6C13','\U6C14','\U6C15','\U6C16','\U6C17','\U6C18','\U6C19','\U6C1A','\U6C1B','\U6C1C','\U6C1D','\U6C1E','\U6C1F','\U6C20','\U6C21','\U6C22','\U6C23','\U6C24','\U6C25','\U6C26','\U6C27','\U6C28','\U6C29','\U6C2A','\U6C2B','\U6C2C','\U6C2D','\U6C2E','\U6C2F','\U6C30','\U6C31','\U6C32','\U6C33','\U6C34','\U6C35','\U6C36','\U6C37','\U6C38','\U6C39','\U6C3A','\U6C3B','\U6C3C','\U6C3D','\U6C3E','\U6C3F','\U6C40','\U6C41','\U6C42','\U6C43','\U6C44','\U6C45','\U6C46','\U6C47','\U6C48','\U6C49','\U6C4A','\U6C4B','\U6C4C','\U6C4D','\U6C4E','\U6C4F','\U6C50','\U6C51','\U6C52','\U6C53','\U6C54','\U6C55','\U6C56','\U6C57','\U6C58','\U6C59','\U6C5A','\U6C5B','\U6C5C','\U6C5D','\U6C5E','\U6C5F','\U6C60','\U6C61','\U6C62','\U6C63','\U6C64','\U6C65','\U6C66','\U6C67','\U6C68','\U6C69','\U6C6A','\U6C6B','\U6C6C','\U6C6D','\U6C6E','\U6C6F','\U6C70','\U6C71','\U6C72','\U6C73','\U6C74','\U6C75','\U6C76','\U6C77','\U6C78','\U6C79','\U6C7A','\U6C7B','\U6C7C','\U6C7D','\U6C7E','\U6C7F','\U6C80','\U6C81','\U6C82','\U6C83','\U6C84','\U6C85','\U6C86','\U6C87','\U6C88','\U6C89','\U6C8A','\U6C8B','\U6C8C','\U6C8D','\U6C8E','\U6C8F','\U6C90','\U6C91','\U6C92','\U6C93','\U6C94','\U6C95','\U6C96','\U6C97','\U6C98','\U6C99','\U6C9A','\U6C9B','\U6C9C','\U6C9D','\U6C9E','\U6C9F','\U6CA0','\U6CA1','\U6CA2','\U6CA3','\U6CA4','\U6CA5','\U6CA6','\U6CA7','\U6CA8','\U6CA9','\U6CAA','\U6CAB','\U6CAC','\U6CAD','\U6CAE','\U6CAF','\U6CB0','\U6CB1','\U6CB2','\U6CB3','\U6CB4','\U6CB5','\U6CB6','\U6CB7','\U6CB8','\U6CB9','\U6CBA','\U6CBB','\U6CBC','\U6CBD','\U6CBE','\U6CBF','\U6CC0','\U6CC1','\U6CC2','\U6CC3','\U6CC4','\U6CC5','\U6CC6','\U6CC7','\U6CC8','\U6CC9','\U6CCA','\U6CCB','\U6CCC','\U6CCD','\U6CCE','\U6CCF','\U6CD0','\U6CD1','\U6CD2','\U6CD3','\U6CD4','\U6CD5','\U6CD6','\U6CD7','\U6CD8','\U6CD9','\U6CDA','\U6CDB','\U6CDC','\U6CDD','\U6CDE','\U6CDF','\U6CE0','\U6CE1','\U6CE2','\U6CE3','\U6CE4','\U6CE5','\U6CE6','\U6CE7','\U6CE8','\U6CE9','\U6CEA','\U6CEB','\U6CEC','\U6CED','\U6CEE','\U6CEF','\U6CF0','\U6CF1','\U6CF2','\U6CF3','\U6CF4','\U6CF5','\U6CF6','\U6CF7','\U6CF8','\U6CF9','\U6CFA','\U6CFB','\U6CFC','\U6CFD','\U6CFE','\U6CFF','\U6D00','\U6D01','\U6D02','\U6D03','\U6D04','\U6D05','\U6D06','\U6D07','\U6D08','\U6D09','\U6D0A','\U6D0B','\U6D0C','\U6D0D','\U6D0E','\U6D0F','\U6D10','\U6D11','\U6D12','\U6D13','\U6D14','\U6D15','\U6D16','\U6D17','\U6D18','\U6D19','\U6D1A','\U6D1B','\U6D1C','\U6D1D','\U6D1E','\U6D1F','\U6D20','\U6D21','\U6D22','\U6D23','\U6D24','\U6D25','\U6D26','\U6D27','\U6D28','\U6D29','\U6D2A','\U6D2B','\U6D2C','\U6D2D','\U6D2E','\U6D2F','\U6D30','\U6D31','\U6D32','\U6D33','\U6D34','\U6D35','\U6D36','\U6D37','\U6D38','\U6D39','\U6D3A','\U6D3B','\U6D3C','\U6D3D','\U6D3E','\U6D3F','\U6D40','\U6D41','\U6D42','\U6D43','\U6D44','\U6D45','\U6D46','\U6D47','\U6D48','\U6D49','\U6D4A','\U6D4B','\U6D4C','\U6D4D','\U6D4E','\U6D4F','\U6D50','\U6D51','\U6D52','\U6D53','\U6D54','\U6D55','\U6D56','\U6D57','\U6D58','\U6D59','\U6D5A','\U6D5B','\U6D5C','\U6D5D','\U6D5E','\U6D5F','\U6D60','\U6D61','\U6D62','\U6D63','\U6D64','\U6D65','\U6D66','\U6D67','\U6D68','\U6D69','\U6D6A','\U6D6B','\U6D6C','\U6D6D','\U6D6E','\U6D6F','\U6D70','\U6D71','\U6D72','\U6D73','\U6D74','\U6D75','\U6D76','\U6D77','\U6D78','\U6D79','\U6D7A','\U6D7B','\U6D7C','\U6D7D','\U6D7E','\U6D7F','\U6D80','\U6D81','\U6D82','\U6D83','\U6D84','\U6D85','\U6D86','\U6D87','\U6D88','\U6D89','\U6D8A','\U6D8B','\U6D8C','\U6D8D','\U6D8E','\U6D8F','\U6D90','\U6D91','\U6D92','\U6D93','\U6D94','\U6D95','\U6D96','\U6D97','\U6D98','\U6D99','\U6D9A','\U6D9B','\U6D9C','\U6D9D','\U6D9E','\U6D9F','\U6DA0','\U6DA1','\U6DA2','\U6DA3','\U6DA4','\U6DA5','\U6DA6','\U6DA7','\U6DA8','\U6DA9','\U6DAA','\U6DAB','\U6DAC','\U6DAD','\U6DAE','\U6DAF','\U6DB0','\U6DB1','\U6DB2','\U6DB3','\U6DB4','\U6DB5','\U6DB6','\U6DB7','\U6DB8','\U6DB9','\U6DBA','\U6DBB','\U6DBC','\U6DBD','\U6DBE','\U6DBF','\U6DC0','\U6DC1','\U6DC2','\U6DC3','\U6DC4','\U6DC5','\U6DC6','\U6DC7','\U6DC8','\U6DC9','\U6DCA','\U6DCB','\U6DCC','\U6DCD','\U6DCE','\U6DCF','\U6DD0','\U6DD1','\U6DD2','\U6DD3','\U6DD4','\U6DD5','\U6DD6','\U6DD7','\U6DD8','\U6DD9','\U6DDA','\U6DDB','\U6DDC','\U6DDD','\U6DDE','\U6DDF','\U6DE0','\U6DE1','\U6DE2','\U6DE3','\U6DE4','\U6DE5','\U6DE6','\U6DE7','\U6DE8','\U6DE9','\U6DEA','\U6DEB','\U6DEC','\U6DED','\U6DEE','\U6DEF','\U6DF0','\U6DF1','\U6DF2','\U6DF3','\U6DF4','\U6DF5','\U6DF6','\U6DF7','\U6DF8','\U6DF9','\U6DFA','\U6DFB','\U6DFC','\U6DFD','\U6DFE','\U6DFF','\U6E00','\U6E01','\U6E02','\U6E03','\U6E04','\U6E05','\U6E06','\U6E07','\U6E08','\U6E09','\U6E0A','\U6E0B','\U6E0C','\U6E0D','\U6E0E','\U6E0F','\U6E10','\U6E11','\U6E12','\U6E13','\U6E14','\U6E15','\U6E16','\U6E17','\U6E18','\U6E19','\U6E1A','\U6E1B','\U6E1C','\U6E1D','\U6E1E','\U6E1F','\U6E20','\U6E21','\U6E22','\U6E23','\U6E24','\U6E25','\U6E26','\U6E27','\U6E28','\U6E29','\U6E2A','\U6E2B','\U6E2C','\U6E2D','\U6E2E','\U6E2F','\U6E30','\U6E31','\U6E32','\U6E33','\U6E34','\U6E35','\U6E36','\U6E37','\U6E38','\U6E39','\U6E3A','\U6E3B','\U6E3C','\U6E3D','\U6E3E','\U6E3F','\U6E40','\U6E41','\U6E42','\U6E43','\U6E44','\U6E45','\U6E46','\U6E47','\U6E48','\U6E49','\U6E4A','\U6E4B','\U6E4C','\U6E4D','\U6E4E','\U6E4F','\U6E50','\U6E51','\U6E52','\U6E53','\U6E54','\U6E55','\U6E56','\U6E57','\U6E58','\U6E59','\U6E5A','\U6E5B','\U6E5C','\U6E5D','\U6E5E','\U6E5F','\U6E60','\U6E61','\U6E62','\U6E63','\U6E64','\U6E65','\U6E66','\U6E67','\U6E68','\U6E69','\U6E6A','\U6E6B','\U6E6C','\U6E6D','\U6E6E','\U6E6F','\U6E70','\U6E71','\U6E72','\U6E73','\U6E74','\U6E75','\U6E76','\U6E77','\U6E78','\U6E79','\U6E7A','\U6E7B','\U6E7C','\U6E7D','\U6E7E','\U6E7F','\U6E80','\U6E81','\U6E82','\U6E83','\U6E84','\U6E85','\U6E86','\U6E87','\U6E88','\U6E89','\U6E8A','\U6E8B','\U6E8C','\U6E8D','\U6E8E','\U6E8F','\U6E90','\U6E91','\U6E92','\U6E93','\U6E94','\U6E95','\U6E96','\U6E97','\U6E98','\U6E99','\U6E9A','\U6E9B','\U6E9C','\U6E9D','\U6E9E','\U6E9F','\U6EA0','\U6EA1','\U6EA2','\U6EA3','\U6EA4','\U6EA5','\U6EA6','\U6EA7','\U6EA8','\U6EA9','\U6EAA','\U6EAB','\U6EAC','\U6EAD','\U6EAE','\U6EAF','\U6EB0','\U6EB1','\U6EB2','\U6EB3','\U6EB4','\U6EB5','\U6EB6','\U6EB7','\U6EB8','\U6EB9','\U6EBA','\U6EBB','\U6EBC','\U6EBD','\U6EBE','\U6EBF','\U6EC0','\U6EC1','\U6EC2','\U6EC3','\U6EC4','\U6EC5','\U6EC6','\U6EC7','\U6EC8','\U6EC9','\U6ECA','\U6ECB','\U6ECC','\U6ECD','\U6ECE','\U6ECF','\U6ED0','\U6ED1','\U6ED2','\U6ED3','\U6ED4','\U6ED5','\U6ED6','\U6ED7','\U6ED8','\U6ED9','\U6EDA','\U6EDB','\U6EDC','\U6EDD','\U6EDE','\U6EDF','\U6EE0','\U6EE1','\U6EE2','\U6EE3','\U6EE4','\U6EE5','\U6EE6','\U6EE7','\U6EE8','\U6EE9','\U6EEA','\U6EEB','\U6EEC','\U6EED','\U6EEE','\U6EEF','\U6EF0','\U6EF1','\U6EF2','\U6EF3','\U6EF4','\U6EF5','\U6EF6','\U6EF7','\U6EF8','\U6EF9','\U6EFA','\U6EFB','\U6EFC','\U6EFD','\U6EFE','\U6EFF','\U6F00','\U6F01','\U6F02','\U6F03','\U6F04','\U6F05','\U6F06','\U6F07','\U6F08','\U6F09','\U6F0A','\U6F0B','\U6F0C','\U6F0D','\U6F0E','\U6F0F','\U6F10','\U6F11','\U6F12','\U6F13','\U6F14','\U6F15','\U6F16','\U6F17','\U6F18','\U6F19','\U6F1A','\U6F1B','\U6F1C','\U6F1D','\U6F1E','\U6F1F','\U6F20','\U6F21','\U6F22','\U6F23','\U6F24','\U6F25','\U6F26','\U6F27','\U6F28','\U6F29','\U6F2A','\U6F2B','\U6F2C','\U6F2D','\U6F2E','\U6F2F','\U6F30','\U6F31','\U6F32','\U6F33','\U6F34','\U6F35','\U6F36','\U6F37','\U6F38','\U6F39','\U6F3A','\U6F3B','\U6F3C','\U6F3D','\U6F3E','\U6F3F','\U6F40','\U6F41','\U6F42','\U6F43','\U6F44','\U6F45','\U6F46','\U6F47','\U6F48','\U6F49','\U6F4A','\U6F4B','\U6F4C','\U6F4D','\U6F4E','\U6F4F','\U6F50','\U6F51','\U6F52','\U6F53','\U6F54','\U6F55','\U6F56','\U6F57','\U6F58','\U6F59','\U6F5A','\U6F5B','\U6F5C','\U6F5D','\U6F5E','\U6F5F','\U6F60','\U6F61','\U6F62','\U6F63','\U6F64','\U6F65','\U6F66','\U6F67','\U6F68','\U6F69','\U6F6A','\U6F6B','\U6F6C','\U6F6D','\U6F6E','\U6F6F','\U6F70','\U6F71','\U6F72','\U6F73','\U6F74','\U6F75','\U6F76','\U6F77','\U6F78','\U6F79','\U6F7A','\U6F7B','\U6F7C','\U6F7D','\U6F7E','\U6F7F','\U6F80','\U6F81','\U6F82','\U6F83','\U6F84','\U6F85','\U6F86','\U6F87','\U6F88','\U6F89','\U6F8A','\U6F8B','\U6F8C','\U6F8D','\U6F8E','\U6F8F','\U6F90','\U6F91','\U6F92','\U6F93','\U6F94','\U6F95','\U6F96','\U6F97','\U6F98','\U6F99','\U6F9A','\U6F9B','\U6F9C','\U6F9D','\U6F9E','\U6F9F','\U6FA0','\U6FA1','\U6FA2','\U6FA3','\U6FA4','\U6FA5','\U6FA6','\U6FA7','\U6FA8','\U6FA9','\U6FAA','\U6FAB','\U6FAC','\U6FAD','\U6FAE','\U6FAF','\U6FB0','\U6FB1','\U6FB2','\U6FB3','\U6FB4','\U6FB5','\U6FB6','\U6FB7','\U6FB8','\U6FB9','\U6FBA','\U6FBB','\U6FBC','\U6FBD','\U6FBE','\U6FBF','\U6FC0','\U6FC1','\U6FC2','\U6FC3','\U6FC4','\U6FC5','\U6FC6','\U6FC7','\U6FC8','\U6FC9','\U6FCA','\U6FCB','\U6FCC','\U6FCD','\U6FCE','\U6FCF','\U6FD0','\U6FD1','\U6FD2','\U6FD3','\U6FD4','\U6FD5','\U6FD6','\U6FD7','\U6FD8','\U6FD9','\U6FDA','\U6FDB','\U6FDC','\U6FDD','\U6FDE','\U6FDF','\U6FE0','\U6FE1','\U6FE2','\U6FE3','\U6FE4','\U6FE5','\U6FE6','\U6FE7','\U6FE8','\U6FE9','\U6FEA','\U6FEB','\U6FEC','\U6FED','\U6FEE','\U6FEF','\U6FF0','\U6FF1','\U6FF2','\U6FF3','\U6FF4','\U6FF5','\U6FF6','\U6FF7','\U6FF8','\U6FF9','\U6FFA','\U6FFB','\U6FFC','\U6FFD','\U6FFE','\U6FFF','\U7000','\U7001','\U7002','\U7003','\U7004','\U7005','\U7006','\U7007','\U7008','\U7009','\U700A','\U700B','\U700C','\U700D','\U700E','\U700F','\U7010','\U7011','\U7012','\U7013','\U7014','\U7015','\U7016','\U7017','\U7018','\U7019','\U701A','\U701B','\U701C','\U701D','\U701E','\U701F','\U7020','\U7021','\U7022','\U7023','\U7024','\U7025','\U7026','\U7027','\U7028','\U7029','\U702A','\U702B','\U702C','\U702D','\U702E','\U702F','\U7030','\U7031','\U7032','\U7033','\U7034','\U7035','\U7036','\U7037','\U7038','\U7039','\U703A','\U703B','\U703C','\U703D','\U703E','\U703F','\U7040','\U7041','\U7042','\U7043','\U7044','\U7045','\U7046','\U7047','\U7048','\U7049','\U704A','\U704B','\U704C','\U704D','\U704E','\U704F','\U7050','\U7051','\U7052','\U7053','\U7054','\U7055','\U7056','\U7057','\U7058','\U7059','\U705A','\U705B','\U705C','\U705D','\U705E','\U705F','\U7060','\U7061','\U7062','\U7063','\U7064','\U7065','\U7066','\U7067','\U7068','\U7069','\U706A','\U706B','\U706C','\U706D','\U706E','\U706F','\U7070','\U7071','\U7072','\U7073','\U7074','\U7075','\U7076','\U7077','\U7078','\U7079','\U707A','\U707B','\U707C','\U707D','\U707E','\U707F','\U7080','\U7081','\U7082','\U7083','\U7084','\U7085','\U7086','\U7087','\U7088','\U7089','\U708A','\U708B','\U708C','\U708D','\U708E','\U708F','\U7090','\U7091','\U7092','\U7093','\U7094','\U7095','\U7096','\U7097','\U7098','\U7099','\U709A','\U709B','\U709C','\U709D','\U709E','\U709F','\U70A0','\U70A1','\U70A2','\U70A3','\U70A4','\U70A5','\U70A6','\U70A7','\U70A8','\U70A9','\U70AA','\U70AB','\U70AC','\U70AD','\U70AE','\U70AF','\U70B0','\U70B1','\U70B2','\U70B3','\U70B4','\U70B5','\U70B6','\U70B7','\U70B8','\U70B9','\U70BA','\U70BB','\U70BC','\U70BD','\U70BE','\U70BF','\U70C0','\U70C1','\U70C2','\U70C3','\U70C4','\U70C5','\U70C6','\U70C7','\U70C8','\U70C9','\U70CA','\U70CB','\U70CC','\U70CD','\U70CE','\U70CF','\U70D0','\U70D1','\U70D2','\U70D3','\U70D4','\U70D5','\U70D6','\U70D7','\U70D8','\U70D9','\U70DA','\U70DB','\U70DC','\U70DD','\U70DE','\U70DF','\U70E0','\U70E1','\U70E2','\U70E3','\U70E4','\U70E5','\U70E6','\U70E7','\U70E8','\U70E9','\U70EA','\U70EB','\U70EC','\U70ED','\U70EE','\U70EF','\U70F0','\U70F1','\U70F2','\U70F3','\U70F4','\U70F5','\U70F6','\U70F7','\U70F8','\U70F9','\U70FA','\U70FB','\U70FC','\U70FD','\U70FE','\U70FF','\U7100','\U7101','\U7102','\U7103','\U7104','\U7105','\U7106','\U7107','\U7108','\U7109','\U710A','\U710B','\U710C','\U710D','\U710E','\U710F','\U7110','\U7111','\U7112','\U7113','\U7114','\U7115','\U7116','\U7117','\U7118','\U7119','\U711A','\U711B','\U711C','\U711D','\U711E','\U711F','\U7120','\U7121','\U7122','\U7123','\U7124','\U7125','\U7126','\U7127','\U7128','\U7129','\U712A','\U712B','\U712C','\U712D','\U712E','\U712F','\U7130','\U7131','\U7132','\U7133','\U7134','\U7135','\U7136','\U7137','\U7138','\U7139','\U713A','\U713B','\U713C','\U713D','\U713E','\U713F','\U7140','\U7141','\U7142','\U7143','\U7144','\U7145','\U7146','\U7147','\U7148','\U7149','\U714A','\U714B','\U714C','\U714D','\U714E','\U714F','\U7150','\U7151','\U7152','\U7153','\U7154','\U7155','\U7156','\U7157','\U7158','\U7159','\U715A','\U715B','\U715C','\U715D','\U715E','\U715F','\U7160','\U7161','\U7162','\U7163','\U7164','\U7165','\U7166','\U7167','\U7168','\U7169','\U716A','\U716B','\U716C','\U716D','\U716E','\U716F','\U7170','\U7171','\U7172','\U7173','\U7174','\U7175','\U7176','\U7177','\U7178','\U7179','\U717A','\U717B','\U717C','\U717D','\U717E','\U717F','\U7180','\U7181','\U7182','\U7183','\U7184','\U7185','\U7186','\U7187','\U7188','\U7189','\U718A','\U718B','\U718C','\U718D','\U718E','\U718F','\U7190','\U7191','\U7192','\U7193','\U7194','\U7195','\U7196','\U7197','\U7198','\U7199','\U719A','\U719B','\U719C','\U719D','\U719E','\U719F','\U71A0','\U71A1','\U71A2','\U71A3','\U71A4','\U71A5','\U71A6','\U71A7','\U71A8','\U71A9','\U71AA','\U71AB','\U71AC','\U71AD','\U71AE','\U71AF','\U71B0','\U71B1','\U71B2','\U71B3','\U71B4','\U71B5','\U71B6','\U71B7','\U71B8','\U71B9','\U71BA','\U71BB','\U71BC','\U71BD','\U71BE','\U71BF','\U71C0','\U71C1','\U71C2','\U71C3','\U71C4','\U71C5','\U71C6','\U71C7','\U71C8','\U71C9','\U71CA','\U71CB','\U71CC','\U71CD','\U71CE','\U71CF','\U71D0','\U71D1','\U71D2','\U71D3','\U71D4','\U71D5','\U71D6','\U71D7','\U71D8','\U71D9','\U71DA','\U71DB','\U71DC','\U71DD','\U71DE','\U71DF','\U71E0','\U71E1','\U71E2','\U71E3','\U71E4','\U71E5','\U71E6','\U71E7','\U71E8','\U71E9','\U71EA','\U71EB','\U71EC','\U71ED','\U71EE','\U71EF','\U71F0','\U71F1','\U71F2','\U71F3','\U71F4','\U71F5','\U71F6','\U71F7','\U71F8','\U71F9','\U71FA','\U71FB','\U71FC','\U71FD','\U71FE','\U71FF','\U7200','\U7201','\U7202','\U7203','\U7204','\U7205','\U7206','\U7207','\U7208','\U7209','\U720A','\U720B','\U720C','\U720D','\U720E','\U720F','\U7210','\U7211','\U7212','\U7213','\U7214','\U7215','\U7216','\U7217','\U7218','\U7219','\U721A','\U721B','\U721C','\U721D','\U721E','\U721F','\U7220','\U7221','\U7222','\U7223','\U7224','\U7225','\U7226','\U7227','\U7228','\U7229','\U722A','\U722B','\U722C','\U722D','\U722E','\U722F','\U7230','\U7231','\U7232','\U7233','\U7234','\U7235','\U7236','\U7237','\U7238','\U7239','\U723A','\U723B','\U723C','\U723D','\U723E','\U723F','\U7240','\U7241','\U7242','\U7243','\U7244','\U7245','\U7246','\U7247','\U7248','\U7249','\U724A','\U724B','\U724C','\U724D','\U724E','\U724F','\U7250','\U7251','\U7252','\U7253','\U7254','\U7255','\U7256','\U7257','\U7258','\U7259','\U725A','\U725B','\U725C','\U725D','\U725E','\U725F','\U7260','\U7261','\U7262','\U7263','\U7264','\U7265','\U7266','\U7267','\U7268','\U7269','\U726A','\U726B','\U726C','\U726D','\U726E','\U726F','\U7270','\U7271','\U7272','\U7273','\U7274','\U7275','\U7276','\U7277','\U7278','\U7279','\U727A','\U727B','\U727C','\U727D','\U727E','\U727F','\U7280','\U7281','\U7282','\U7283','\U7284','\U7285','\U7286','\U7287','\U7288','\U7289','\U728A','\U728B','\U728C','\U728D','\U728E','\U728F','\U7290','\U7291','\U7292','\U7293','\U7294','\U7295','\U7296','\U7297','\U7298','\U7299','\U729A','\U729B','\U729C','\U729D','\U729E','\U729F','\U72A0','\U72A1','\U72A2','\U72A3','\U72A4','\U72A5','\U72A6','\U72A7','\U72A8','\U72A9','\U72AA','\U72AB','\U72AC','\U72AD','\U72AE','\U72AF','\U72B0','\U72B1','\U72B2','\U72B3','\U72B4','\U72B5','\U72B6','\U72B7','\U72B8','\U72B9','\U72BA','\U72BB','\U72BC','\U72BD','\U72BE','\U72BF','\U72C0','\U72C1','\U72C2','\U72C3','\U72C4','\U72C5','\U72C6','\U72C7','\U72C8','\U72C9','\U72CA','\U72CB','\U72CC','\U72CD','\U72CE','\U72CF','\U72D0','\U72D1','\U72D2','\U72D3','\U72D4','\U72D5','\U72D6','\U72D7','\U72D8','\U72D9','\U72DA','\U72DB','\U72DC','\U72DD','\U72DE','\U72DF','\U72E0','\U72E1','\U72E2','\U72E3','\U72E4','\U72E5','\U72E6','\U72E7','\U72E8','\U72E9','\U72EA','\U72EB','\U72EC','\U72ED','\U72EE','\U72EF','\U72F0','\U72F1','\U72F2','\U72F3','\U72F4','\U72F5','\U72F6','\U72F7','\U72F8','\U72F9','\U72FA','\U72FB','\U72FC','\U72FD','\U72FE','\U72FF','\U7300','\U7301','\U7302','\U7303','\U7304','\U7305','\U7306','\U7307','\U7308','\U7309','\U730A','\U730B','\U730C','\U730D','\U730E','\U730F','\U7310','\U7311','\U7312','\U7313','\U7314','\U7315','\U7316','\U7317','\U7318','\U7319','\U731A','\U731B','\U731C','\U731D','\U731E','\U731F','\U7320','\U7321','\U7322','\U7323','\U7324','\U7325','\U7326','\U7327','\U7328','\U7329','\U732A','\U732B','\U732C','\U732D','\U732E','\U732F','\U7330','\U7331','\U7332','\U7333','\U7334','\U7335','\U7336','\U7337','\U7338','\U7339','\U733A','\U733B','\U733C','\U733D','\U733E','\U733F','\U7340','\U7341','\U7342','\U7343','\U7344','\U7345','\U7346','\U7347','\U7348','\U7349','\U734A','\U734B','\U734C','\U734D','\U734E','\U734F','\U7350','\U7351','\U7352','\U7353','\U7354','\U7355','\U7356','\U7357','\U7358','\U7359','\U735A','\U735B','\U735C','\U735D','\U735E','\U735F','\U7360','\U7361','\U7362','\U7363','\U7364','\U7365','\U7366','\U7367','\U7368','\U7369','\U736A','\U736B','\U736C','\U736D','\U736E','\U736F','\U7370','\U7371','\U7372','\U7373','\U7374','\U7375','\U7376','\U7377','\U7378','\U7379','\U737A','\U737B','\U737C','\U737D','\U737E','\U737F','\U7380','\U7381','\U7382','\U7383','\U7384','\U7385','\U7386','\U7387','\U7388','\U7389','\U738A','\U738B','\U738C','\U738D','\U738E','\U738F','\U7390','\U7391','\U7392','\U7393','\U7394','\U7395','\U7396','\U7397','\U7398','\U7399','\U739A','\U739B','\U739C','\U739D','\U739E','\U739F','\U73A0','\U73A1','\U73A2','\U73A3','\U73A4','\U73A5','\U73A6','\U73A7','\U73A8','\U73A9','\U73AA','\U73AB','\U73AC','\U73AD','\U73AE','\U73AF','\U73B0','\U73B1','\U73B2','\U73B3','\U73B4','\U73B5','\U73B6','\U73B7','\U73B8','\U73B9','\U73BA','\U73BB','\U73BC','\U73BD','\U73BE','\U73BF','\U73C0','\U73C1','\U73C2','\U73C3','\U73C4','\U73C5','\U73C6','\U73C7','\U73C8','\U73C9','\U73CA','\U73CB','\U73CC','\U73CD','\U73CE','\U73CF','\U73D0','\U73D1','\U73D2','\U73D3','\U73D4','\U73D5','\U73D6','\U73D7','\U73D8','\U73D9','\U73DA','\U73DB','\U73DC','\U73DD','\U73DE','\U73DF','\U73E0','\U73E1','\U73E2','\U73E3','\U73E4','\U73E5','\U73E6','\U73E7','\U73E8','\U73E9','\U73EA','\U73EB','\U73EC','\U73ED','\U73EE','\U73EF','\U73F0','\U73F1','\U73F2','\U73F3','\U73F4','\U73F5','\U73F6','\U73F7','\U73F8','\U73F9','\U73FA','\U73FB','\U73FC','\U73FD','\U73FE','\U73FF','\U7400','\U7401','\U7402','\U7403','\U7404','\U7405','\U7406','\U7407','\U7408','\U7409','\U740A','\U740B','\U740C','\U740D','\U740E','\U740F','\U7410','\U7411','\U7412','\U7413','\U7414','\U7415','\U7416','\U7417','\U7418','\U7419','\U741A','\U741B','\U741C','\U741D','\U741E','\U741F','\U7420','\U7421','\U7422','\U7423','\U7424','\U7425','\U7426','\U7427','\U7428','\U7429','\U742A','\U742B','\U742C','\U742D','\U742E','\U742F','\U7430','\U7431','\U7432','\U7433','\U7434','\U7435','\U7436','\U7437','\U7438','\U7439','\U743A','\U743B','\U743C','\U743D','\U743E','\U743F','\U7440','\U7441','\U7442','\U7443','\U7444','\U7445','\U7446','\U7447','\U7448','\U7449','\U744A','\U744B','\U744C','\U744D','\U744E','\U744F','\U7450','\U7451','\U7452','\U7453','\U7454','\U7455','\U7456','\U7457','\U7458','\U7459','\U745A','\U745B','\U745C','\U745D','\U745E','\U745F','\U7460','\U7461','\U7462','\U7463','\U7464','\U7465','\U7466','\U7467','\U7468','\U7469','\U746A','\U746B','\U746C','\U746D','\U746E','\U746F','\U7470','\U7471','\U7472','\U7473','\U7474','\U7475','\U7476','\U7477','\U7478','\U7479','\U747A','\U747B','\U747C','\U747D','\U747E','\U747F','\U7480','\U7481','\U7482','\U7483','\U7484','\U7485','\U7486','\U7487','\U7488','\U7489','\U748A','\U748B','\U748C','\U748D','\U748E','\U748F','\U7490','\U7491','\U7492','\U7493','\U7494','\U7495','\U7496','\U7497','\U7498','\U7499','\U749A','\U749B','\U749C','\U749D','\U749E','\U749F','\U74A0','\U74A1','\U74A2','\U74A3','\U74A4','\U74A5','\U74A6','\U74A7','\U74A8','\U74A9','\U74AA','\U74AB','\U74AC','\U74AD','\U74AE','\U74AF','\U74B0','\U74B1','\U74B2','\U74B3','\U74B4','\U74B5','\U74B6','\U74B7','\U74B8','\U74B9','\U74BA','\U74BB','\U74BC','\U74BD','\U74BE','\U74BF','\U74C0','\U74C1','\U74C2','\U74C3','\U74C4','\U74C5','\U74C6','\U74C7','\U74C8','\U74C9','\U74CA','\U74CB','\U74CC','\U74CD','\U74CE','\U74CF','\U74D0','\U74D1','\U74D2','\U74D3','\U74D4','\U74D5','\U74D6','\U74D7','\U74D8','\U74D9','\U74DA','\U74DB','\U74DC','\U74DD','\U74DE','\U74DF','\U74E0','\U74E1','\U74E2','\U74E3','\U74E4','\U74E5','\U74E6','\U74E7','\U74E8','\U74E9','\U74EA','\U74EB','\U74EC','\U74ED','\U74EE','\U74EF','\U74F0','\U74F1','\U74F2','\U74F3','\U74F4','\U74F5','\U74F6','\U74F7','\U74F8','\U74F9','\U74FA','\U74FB','\U74FC','\U74FD','\U74FE','\U74FF','\U7500','\U7501','\U7502','\U7503','\U7504','\U7505','\U7506','\U7507','\U7508','\U7509','\U750A','\U750B','\U750C','\U750D','\U750E','\U750F','\U7510','\U7511','\U7512','\U7513','\U7514','\U7515','\U7516','\U7517','\U7518','\U7519','\U751A','\U751B','\U751C','\U751D','\U751E','\U751F','\U7520','\U7521','\U7522','\U7523','\U7524','\U7525','\U7526','\U7527','\U7528','\U7529','\U752A','\U752B','\U752C','\U752D','\U752E','\U752F','\U7530','\U7531','\U7532','\U7533','\U7534','\U7535','\U7536','\U7537','\U7538','\U7539','\U753A','\U753B','\U753C','\U753D','\U753E','\U753F','\U7540','\U7541','\U7542','\U7543','\U7544','\U7545','\U7546','\U7547','\U7548','\U7549','\U754A','\U754B','\U754C','\U754D','\U754E','\U754F','\U7550','\U7551','\U7552','\U7553','\U7554','\U7555','\U7556','\U7557','\U7558','\U7559','\U755A','\U755B','\U755C','\U755D','\U755E','\U755F','\U7560','\U7561','\U7562','\U7563','\U7564','\U7565','\U7566','\U7567','\U7568','\U7569','\U756A','\U756B','\U756C','\U756D','\U756E','\U756F','\U7570','\U7571','\U7572','\U7573','\U7574','\U7575','\U7576','\U7577','\U7578','\U7579','\U757A','\U757B','\U757C','\U757D','\U757E','\U757F','\U7580','\U7581','\U7582','\U7583','\U7584','\U7585','\U7586','\U7587','\U7588','\U7589','\U758A','\U758B','\U758C','\U758D','\U758E','\U758F','\U7590','\U7591','\U7592','\U7593','\U7594','\U7595','\U7596','\U7597','\U7598','\U7599','\U759A','\U759B','\U759C','\U759D','\U759E','\U759F','\U75A0','\U75A1','\U75A2','\U75A3','\U75A4','\U75A5','\U75A6','\U75A7','\U75A8','\U75A9','\U75AA','\U75AB','\U75AC','\U75AD','\U75AE','\U75AF','\U75B0','\U75B1','\U75B2','\U75B3','\U75B4','\U75B5','\U75B6','\U75B7','\U75B8','\U75B9','\U75BA','\U75BB','\U75BC','\U75BD','\U75BE','\U75BF','\U75C0','\U75C1','\U75C2','\U75C3','\U75C4','\U75C5','\U75C6','\U75C7','\U75C8','\U75C9','\U75CA','\U75CB','\U75CC','\U75CD','\U75CE','\U75CF','\U75D0','\U75D1','\U75D2','\U75D3','\U75D4','\U75D5','\U75D6','\U75D7','\U75D8','\U75D9','\U75DA','\U75DB','\U75DC','\U75DD','\U75DE','\U75DF','\U75E0','\U75E1','\U75E2','\U75E3','\U75E4','\U75E5','\U75E6','\U75E7','\U75E8','\U75E9','\U75EA','\U75EB','\U75EC','\U75ED','\U75EE','\U75EF','\U75F0','\U75F1','\U75F2','\U75F3','\U75F4','\U75F5','\U75F6','\U75F7','\U75F8','\U75F9','\U75FA','\U75FB','\U75FC','\U75FD','\U75FE','\U75FF','\U7600','\U7601','\U7602','\U7603','\U7604','\U7605','\U7606','\U7607','\U7608','\U7609','\U760A','\U760B','\U760C','\U760D','\U760E','\U760F','\U7610','\U7611','\U7612','\U7613','\U7614','\U7615','\U7616','\U7617','\U7618','\U7619','\U761A','\U761B','\U761C','\U761D','\U761E','\U761F','\U7620','\U7621','\U7622','\U7623','\U7624','\U7625','\U7626','\U7627','\U7628','\U7629','\U762A','\U762B','\U762C','\U762D','\U762E','\U762F','\U7630','\U7631','\U7632','\U7633','\U7634','\U7635','\U7636','\U7637','\U7638','\U7639','\U763A','\U763B','\U763C','\U763D','\U763E','\U763F','\U7640','\U7641','\U7642','\U7643','\U7644','\U7645','\U7646','\U7647','\U7648','\U7649','\U764A','\U764B','\U764C','\U764D','\U764E','\U764F','\U7650','\U7651','\U7652','\U7653','\U7654','\U7655','\U7656','\U7657','\U7658','\U7659','\U765A','\U765B','\U765C','\U765D','\U765E','\U765F','\U7660','\U7661','\U7662','\U7663','\U7664','\U7665','\U7666','\U7667','\U7668','\U7669','\U766A','\U766B','\U766C','\U766D','\U766E','\U766F','\U7670','\U7671','\U7672','\U7673','\U7674','\U7675','\U7676','\U7677','\U7678','\U7679','\U767A','\U767B','\U767C','\U767D','\U767E','\U767F','\U7680','\U7681','\U7682','\U7683','\U7684','\U7685','\U7686','\U7687','\U7688','\U7689','\U768A','\U768B','\U768C','\U768D','\U768E','\U768F','\U7690','\U7691','\U7692','\U7693','\U7694','\U7695','\U7696','\U7697','\U7698','\U7699','\U769A','\U769B','\U769C','\U769D','\U769E','\U769F','\U76A0','\U76A1','\U76A2','\U76A3','\U76A4','\U76A5','\U76A6','\U76A7','\U76A8','\U76A9','\U76AA','\U76AB','\U76AC','\U76AD','\U76AE','\U76AF','\U76B0','\U76B1','\U76B2','\U76B3','\U76B4','\U76B5','\U76B6','\U76B7','\U76B8','\U76B9','\U76BA','\U76BB','\U76BC','\U76BD','\U76BE','\U76BF','\U76C0','\U76C1','\U76C2','\U76C3','\U76C4','\U76C5','\U76C6','\U76C7','\U76C8','\U76C9','\U76CA','\U76CB','\U76CC','\U76CD','\U76CE','\U76CF','\U76D0','\U76D1','\U76D2','\U76D3','\U76D4','\U76D5','\U76D6','\U76D7','\U76D8','\U76D9','\U76DA','\U76DB','\U76DC','\U76DD','\U76DE','\U76DF','\U76E0','\U76E1','\U76E2','\U76E3','\U76E4','\U76E5','\U76E6','\U76E7','\U76E8','\U76E9','\U76EA','\U76EB','\U76EC','\U76ED','\U76EE','\U76EF','\U76F0','\U76F1','\U76F2','\U76F3','\U76F4','\U76F5','\U76F6','\U76F7','\U76F8','\U76F9','\U76FA','\U76FB','\U76FC','\U76FD','\U76FE','\U76FF','\U7700','\U7701','\U7702','\U7703','\U7704','\U7705','\U7706','\U7707','\U7708','\U7709','\U770A','\U770B','\U770C','\U770D','\U770E','\U770F','\U7710','\U7711','\U7712','\U7713','\U7714','\U7715','\U7716','\U7717','\U7718','\U7719','\U771A','\U771B','\U771C','\U771D','\U771E','\U771F','\U7720','\U7721','\U7722','\U7723','\U7724','\U7725','\U7726','\U7727','\U7728','\U7729','\U772A','\U772B','\U772C','\U772D','\U772E','\U772F','\U7730','\U7731','\U7732','\U7733','\U7734','\U7735','\U7736','\U7737','\U7738','\U7739','\U773A','\U773B','\U773C','\U773D','\U773E','\U773F','\U7740','\U7741','\U7742','\U7743','\U7744','\U7745','\U7746','\U7747','\U7748','\U7749','\U774A','\U774B','\U774C','\U774D','\U774E','\U774F','\U7750','\U7751','\U7752','\U7753','\U7754','\U7755','\U7756','\U7757','\U7758','\U7759','\U775A','\U775B','\U775C','\U775D','\U775E','\U775F','\U7760','\U7761','\U7762','\U7763','\U7764','\U7765','\U7766','\U7767','\U7768','\U7769','\U776A','\U776B','\U776C','\U776D','\U776E','\U776F','\U7770','\U7771','\U7772','\U7773','\U7774','\U7775','\U7776','\U7777','\U7778','\U7779','\U777A','\U777B','\U777C','\U777D','\U777E','\U777F','\U7780','\U7781','\U7782','\U7783','\U7784','\U7785','\U7786','\U7787','\U7788','\U7789','\U778A','\U778B','\U778C','\U778D','\U778E','\U778F','\U7790','\U7791','\U7792','\U7793','\U7794','\U7795','\U7796','\U7797','\U7798','\U7799','\U779A','\U779B','\U779C','\U779D','\U779E','\U779F','\U77A0','\U77A1','\U77A2','\U77A3','\U77A4','\U77A5','\U77A6','\U77A7','\U77A8','\U77A9','\U77AA','\U77AB','\U77AC','\U77AD','\U77AE','\U77AF','\U77B0','\U77B1','\U77B2','\U77B3','\U77B4','\U77B5','\U77B6','\U77B7','\U77B8','\U77B9','\U77BA','\U77BB','\U77BC','\U77BD','\U77BE','\U77BF','\U77C0','\U77C1','\U77C2','\U77C3','\U77C4','\U77C5','\U77C6','\U77C7','\U77C8','\U77C9','\U77CA','\U77CB','\U77CC','\U77CD','\U77CE','\U77CF','\U77D0','\U77D1','\U77D2','\U77D3','\U77D4','\U77D5','\U77D6','\U77D7','\U77D8','\U77D9','\U77DA','\U77DB','\U77DC','\U77DD','\U77DE','\U77DF','\U77E0','\U77E1','\U77E2','\U77E3','\U77E4','\U77E5','\U77E6','\U77E7','\U77E8','\U77E9','\U77EA','\U77EB','\U77EC','\U77ED','\U77EE','\U77EF','\U77F0','\U77F1','\U77F2','\U77F3','\U77F4','\U77F5','\U77F6','\U77F7','\U77F8','\U77F9','\U77FA','\U77FB','\U77FC','\U77FD','\U77FE','\U77FF','\U7800','\U7801','\U7802','\U7803','\U7804','\U7805','\U7806','\U7807','\U7808','\U7809','\U780A','\U780B','\U780C','\U780D','\U780E','\U780F','\U7810','\U7811','\U7812','\U7813','\U7814','\U7815','\U7816','\U7817','\U7818','\U7819','\U781A','\U781B','\U781C','\U781D','\U781E','\U781F','\U7820','\U7821','\U7822','\U7823','\U7824','\U7825','\U7826','\U7827','\U7828','\U7829','\U782A','\U782B','\U782C','\U782D','\U782E','\U782F','\U7830','\U7831','\U7832','\U7833','\U7834','\U7835','\U7836','\U7837','\U7838','\U7839','\U783A','\U783B','\U783C','\U783D','\U783E','\U783F','\U7840','\U7841','\U7842','\U7843','\U7844','\U7845','\U7846','\U7847','\U7848','\U7849','\U784A','\U784B','\U784C','\U784D','\U784E','\U784F','\U7850','\U7851','\U7852','\U7853','\U7854','\U7855','\U7856','\U7857','\U7858','\U7859','\U785A','\U785B','\U785C','\U785D','\U785E','\U785F','\U7860','\U7861','\U7862','\U7863','\U7864','\U7865','\U7866','\U7867','\U7868','\U7869','\U786A','\U786B','\U786C','\U786D','\U786E','\U786F','\U7870','\U7871','\U7872','\U7873','\U7874','\U7875','\U7876','\U7877','\U7878','\U7879','\U787A','\U787B','\U787C','\U787D','\U787E','\U787F','\U7880','\U7881','\U7882','\U7883','\U7884','\U7885','\U7886','\U7887','\U7888','\U7889','\U788A','\U788B','\U788C','\U788D','\U788E','\U788F','\U7890','\U7891','\U7892','\U7893','\U7894','\U7895','\U7896','\U7897','\U7898','\U7899','\U789A','\U789B','\U789C','\U789D','\U789E','\U789F','\U78A0','\U78A1','\U78A2','\U78A3','\U78A4','\U78A5','\U78A6','\U78A7','\U78A8','\U78A9','\U78AA','\U78AB','\U78AC','\U78AD','\U78AE','\U78AF','\U78B0','\U78B1','\U78B2','\U78B3','\U78B4','\U78B5','\U78B6','\U78B7','\U78B8','\U78B9','\U78BA','\U78BB','\U78BC','\U78BD','\U78BE','\U78BF','\U78C0','\U78C1','\U78C2','\U78C3','\U78C4','\U78C5','\U78C6','\U78C7','\U78C8','\U78C9','\U78CA','\U78CB','\U78CC','\U78CD','\U78CE','\U78CF','\U78D0','\U78D1','\U78D2','\U78D3','\U78D4','\U78D5','\U78D6','\U78D7','\U78D8','\U78D9','\U78DA','\U78DB','\U78DC','\U78DD','\U78DE','\U78DF','\U78E0','\U78E1','\U78E2','\U78E3','\U78E4','\U78E5','\U78E6','\U78E7','\U78E8','\U78E9','\U78EA','\U78EB','\U78EC','\U78ED','\U78EE','\U78EF','\U78F0','\U78F1','\U78F2','\U78F3','\U78F4','\U78F5','\U78F6','\U78F7','\U78F8','\U78F9','\U78FA','\U78FB','\U78FC','\U78FD','\U78FE','\U78FF','\U7900','\U7901','\U7902','\U7903','\U7904','\U7905','\U7906','\U7907','\U7908','\U7909','\U790A','\U790B','\U790C','\U790D','\U790E','\U790F','\U7910','\U7911','\U7912','\U7913','\U7914','\U7915','\U7916','\U7917','\U7918','\U7919','\U791A','\U791B','\U791C','\U791D','\U791E','\U791F','\U7920','\U7921','\U7922','\U7923','\U7924','\U7925','\U7926','\U7927','\U7928','\U7929','\U792A','\U792B','\U792C','\U792D','\U792E','\U792F','\U7930','\U7931','\U7932','\U7933','\U7934','\U7935','\U7936','\U7937','\U7938','\U7939','\U793A','\U793B','\U793C','\U793D','\U793E','\U793F','\U7940','\U7941','\U7942','\U7943','\U7944','\U7945','\U7946','\U7947','\U7948','\U7949','\U794A','\U794B','\U794C','\U794D','\U794E','\U794F','\U7950','\U7951','\U7952','\U7953','\U7954','\U7955','\U7956','\U7957','\U7958','\U7959','\U795A','\U795B','\U795C','\U795D','\U795E','\U795F','\U7960','\U7961','\U7962','\U7963','\U7964','\U7965','\U7966','\U7967','\U7968','\U7969','\U796A','\U796B','\U796C','\U796D','\U796E','\U796F','\U7970','\U7971','\U7972','\U7973','\U7974','\U7975','\U7976','\U7977','\U7978','\U7979','\U797A','\U797B','\U797C','\U797D','\U797E','\U797F','\U7980','\U7981','\U7982','\U7983','\U7984','\U7985','\U7986','\U7987','\U7988','\U7989','\U798A','\U798B','\U798C','\U798D','\U798E','\U798F','\U7990','\U7991','\U7992','\U7993','\U7994','\U7995','\U7996','\U7997','\U7998','\U7999','\U799A','\U799B','\U799C','\U799D','\U799E','\U799F','\U79A0','\U79A1','\U79A2','\U79A3','\U79A4','\U79A5','\U79A6','\U79A7','\U79A8','\U79A9','\U79AA','\U79AB','\U79AC','\U79AD','\U79AE','\U79AF','\U79B0','\U79B1','\U79B2','\U79B3','\U79B4','\U79B5','\U79B6','\U79B7','\U79B8','\U79B9','\U79BA','\U79BB','\U79BC','\U79BD','\U79BE','\U79BF','\U79C0','\U79C1','\U79C2','\U79C3','\U79C4','\U79C5','\U79C6','\U79C7','\U79C8','\U79C9','\U79CA','\U79CB','\U79CC','\U79CD','\U79CE','\U79CF','\U79D0','\U79D1','\U79D2','\U79D3','\U79D4','\U79D5','\U79D6','\U79D7','\U79D8','\U79D9','\U79DA','\U79DB','\U79DC','\U79DD','\U79DE','\U79DF','\U79E0','\U79E1','\U79E2','\U79E3','\U79E4','\U79E5','\U79E6','\U79E7','\U79E8','\U79E9','\U79EA','\U79EB','\U79EC','\U79ED','\U79EE','\U79EF','\U79F0','\U79F1','\U79F2','\U79F3','\U79F4','\U79F5','\U79F6','\U79F7','\U79F8','\U79F9','\U79FA','\U79FB','\U79FC','\U79FD','\U79FE','\U79FF','\U7A00','\U7A01','\U7A02','\U7A03','\U7A04','\U7A05','\U7A06','\U7A07','\U7A08','\U7A09','\U7A0A','\U7A0B','\U7A0C','\U7A0D','\U7A0E','\U7A0F','\U7A10','\U7A11','\U7A12','\U7A13','\U7A14','\U7A15','\U7A16','\U7A17','\U7A18','\U7A19','\U7A1A','\U7A1B','\U7A1C','\U7A1D','\U7A1E','\U7A1F','\U7A20','\U7A21','\U7A22','\U7A23','\U7A24','\U7A25','\U7A26','\U7A27','\U7A28','\U7A29','\U7A2A','\U7A2B','\U7A2C','\U7A2D','\U7A2E','\U7A2F','\U7A30','\U7A31','\U7A32','\U7A33','\U7A34','\U7A35','\U7A36','\U7A37','\U7A38','\U7A39','\U7A3A','\U7A3B','\U7A3C','\U7A3D','\U7A3E','\U7A3F','\U7A40','\U7A41','\U7A42','\U7A43','\U7A44','\U7A45','\U7A46','\U7A47','\U7A48','\U7A49','\U7A4A','\U7A4B','\U7A4C','\U7A4D','\U7A4E','\U7A4F','\U7A50','\U7A51','\U7A52','\U7A53','\U7A54','\U7A55','\U7A56','\U7A57','\U7A58','\U7A59','\U7A5A','\U7A5B','\U7A5C','\U7A5D','\U7A5E','\U7A5F','\U7A60','\U7A61','\U7A62','\U7A63','\U7A64','\U7A65','\U7A66','\U7A67','\U7A68','\U7A69','\U7A6A','\U7A6B','\U7A6C','\U7A6D','\U7A6E','\U7A6F','\U7A70','\U7A71','\U7A72','\U7A73','\U7A74','\U7A75','\U7A76','\U7A77','\U7A78','\U7A79','\U7A7A','\U7A7B','\U7A7C','\U7A7D','\U7A7E','\U7A7F','\U7A80','\U7A81','\U7A82','\U7A83','\U7A84','\U7A85','\U7A86','\U7A87','\U7A88','\U7A89','\U7A8A','\U7A8B','\U7A8C','\U7A8D','\U7A8E','\U7A8F','\U7A90','\U7A91','\U7A92','\U7A93','\U7A94','\U7A95','\U7A96','\U7A97','\U7A98','\U7A99','\U7A9A','\U7A9B','\U7A9C','\U7A9D','\U7A9E','\U7A9F','\U7AA0','\U7AA1','\U7AA2','\U7AA3','\U7AA4','\U7AA5','\U7AA6','\U7AA7','\U7AA8','\U7AA9','\U7AAA','\U7AAB','\U7AAC','\U7AAD','\U7AAE','\U7AAF','\U7AB0','\U7AB1','\U7AB2','\U7AB3','\U7AB4','\U7AB5','\U7AB6','\U7AB7','\U7AB8','\U7AB9','\U7ABA','\U7ABB','\U7ABC','\U7ABD','\U7ABE','\U7ABF','\U7AC0','\U7AC1','\U7AC2','\U7AC3','\U7AC4','\U7AC5','\U7AC6','\U7AC7','\U7AC8','\U7AC9','\U7ACA','\U7ACB','\U7ACC','\U7ACD','\U7ACE','\U7ACF','\U7AD0','\U7AD1','\U7AD2','\U7AD3','\U7AD4','\U7AD5','\U7AD6','\U7AD7','\U7AD8','\U7AD9','\U7ADA','\U7ADB','\U7ADC','\U7ADD','\U7ADE','\U7ADF','\U7AE0','\U7AE1','\U7AE2','\U7AE3','\U7AE4','\U7AE5','\U7AE6','\U7AE7','\U7AE8','\U7AE9','\U7AEA','\U7AEB','\U7AEC','\U7AED','\U7AEE','\U7AEF','\U7AF0','\U7AF1','\U7AF2','\U7AF3','\U7AF4','\U7AF5','\U7AF6','\U7AF7','\U7AF8','\U7AF9','\U7AFA','\U7AFB','\U7AFC','\U7AFD','\U7AFE','\U7AFF','\U7B00','\U7B01','\U7B02','\U7B03','\U7B04','\U7B05','\U7B06','\U7B07','\U7B08','\U7B09','\U7B0A','\U7B0B','\U7B0C','\U7B0D','\U7B0E','\U7B0F','\U7B10','\U7B11','\U7B12','\U7B13','\U7B14','\U7B15','\U7B16','\U7B17','\U7B18','\U7B19','\U7B1A','\U7B1B','\U7B1C','\U7B1D','\U7B1E','\U7B1F','\U7B20','\U7B21','\U7B22','\U7B23','\U7B24','\U7B25','\U7B26','\U7B27','\U7B28','\U7B29','\U7B2A','\U7B2B','\U7B2C','\U7B2D','\U7B2E','\U7B2F','\U7B30','\U7B31','\U7B32','\U7B33','\U7B34','\U7B35','\U7B36','\U7B37','\U7B38','\U7B39','\U7B3A','\U7B3B','\U7B3C','\U7B3D','\U7B3E','\U7B3F','\U7B40','\U7B41','\U7B42','\U7B43','\U7B44','\U7B45','\U7B46','\U7B47','\U7B48','\U7B49','\U7B4A','\U7B4B','\U7B4C','\U7B4D','\U7B4E','\U7B4F','\U7B50','\U7B51','\U7B52','\U7B53','\U7B54','\U7B55','\U7B56','\U7B57','\U7B58','\U7B59','\U7B5A','\U7B5B','\U7B5C','\U7B5D','\U7B5E','\U7B5F','\U7B60','\U7B61','\U7B62','\U7B63','\U7B64','\U7B65','\U7B66','\U7B67','\U7B68','\U7B69','\U7B6A','\U7B6B','\U7B6C','\U7B6D','\U7B6E','\U7B6F','\U7B70','\U7B71','\U7B72','\U7B73','\U7B74','\U7B75','\U7B76','\U7B77','\U7B78','\U7B79','\U7B7A','\U7B7B','\U7B7C','\U7B7D','\U7B7E','\U7B7F','\U7B80','\U7B81','\U7B82','\U7B83','\U7B84','\U7B85','\U7B86','\U7B87','\U7B88','\U7B89','\U7B8A','\U7B8B','\U7B8C','\U7B8D','\U7B8E','\U7B8F','\U7B90','\U7B91','\U7B92','\U7B93','\U7B94','\U7B95','\U7B96','\U7B97','\U7B98','\U7B99','\U7B9A','\U7B9B','\U7B9C','\U7B9D','\U7B9E','\U7B9F','\U7BA0','\U7BA1','\U7BA2','\U7BA3','\U7BA4','\U7BA5','\U7BA6','\U7BA7','\U7BA8','\U7BA9','\U7BAA','\U7BAB','\U7BAC','\U7BAD','\U7BAE','\U7BAF','\U7BB0','\U7BB1','\U7BB2','\U7BB3','\U7BB4','\U7BB5','\U7BB6','\U7BB7','\U7BB8','\U7BB9','\U7BBA','\U7BBB','\U7BBC','\U7BBD','\U7BBE','\U7BBF','\U7BC0','\U7BC1','\U7BC2','\U7BC3','\U7BC4','\U7BC5','\U7BC6','\U7BC7','\U7BC8','\U7BC9','\U7BCA','\U7BCB','\U7BCC','\U7BCD','\U7BCE','\U7BCF','\U7BD0','\U7BD1','\U7BD2','\U7BD3','\U7BD4','\U7BD5','\U7BD6','\U7BD7','\U7BD8','\U7BD9','\U7BDA','\U7BDB','\U7BDC','\U7BDD','\U7BDE','\U7BDF','\U7BE0','\U7BE1','\U7BE2','\U7BE3','\U7BE4','\U7BE5','\U7BE6','\U7BE7','\U7BE8','\U7BE9','\U7BEA','\U7BEB','\U7BEC','\U7BED','\U7BEE','\U7BEF','\U7BF0','\U7BF1','\U7BF2','\U7BF3','\U7BF4','\U7BF5','\U7BF6','\U7BF7','\U7BF8','\U7BF9','\U7BFA','\U7BFB','\U7BFC','\U7BFD','\U7BFE','\U7BFF','\U7C00','\U7C01','\U7C02','\U7C03','\U7C04','\U7C05','\U7C06','\U7C07','\U7C08','\U7C09','\U7C0A','\U7C0B','\U7C0C','\U7C0D','\U7C0E','\U7C0F','\U7C10','\U7C11','\U7C12','\U7C13','\U7C14','\U7C15','\U7C16','\U7C17','\U7C18','\U7C19','\U7C1A','\U7C1B','\U7C1C','\U7C1D','\U7C1E','\U7C1F','\U7C20','\U7C21','\U7C22','\U7C23','\U7C24','\U7C25','\U7C26','\U7C27','\U7C28','\U7C29','\U7C2A','\U7C2B','\U7C2C','\U7C2D','\U7C2E','\U7C2F','\U7C30','\U7C31','\U7C32','\U7C33','\U7C34','\U7C35','\U7C36','\U7C37','\U7C38','\U7C39','\U7C3A','\U7C3B','\U7C3C','\U7C3D','\U7C3E','\U7C3F','\U7C40','\U7C41','\U7C42','\U7C43','\U7C44','\U7C45','\U7C46','\U7C47','\U7C48','\U7C49','\U7C4A','\U7C4B','\U7C4C','\U7C4D','\U7C4E','\U7C4F','\U7C50','\U7C51','\U7C52','\U7C53','\U7C54','\U7C55','\U7C56','\U7C57','\U7C58','\U7C59','\U7C5A','\U7C5B','\U7C5C','\U7C5D','\U7C5E','\U7C5F','\U7C60','\U7C61','\U7C62','\U7C63','\U7C64','\U7C65','\U7C66','\U7C67','\U7C68','\U7C69','\U7C6A','\U7C6B','\U7C6C','\U7C6D','\U7C6E','\U7C6F','\U7C70','\U7C71','\U7C72','\U7C73','\U7C74','\U7C75','\U7C76','\U7C77','\U7C78','\U7C79','\U7C7A','\U7C7B','\U7C7C','\U7C7D','\U7C7E','\U7C7F','\U7C80','\U7C81','\U7C82','\U7C83','\U7C84','\U7C85','\U7C86','\U7C87','\U7C88','\U7C89','\U7C8A','\U7C8B','\U7C8C','\U7C8D','\U7C8E','\U7C8F','\U7C90','\U7C91','\U7C92','\U7C93','\U7C94','\U7C95','\U7C96','\U7C97','\U7C98','\U7C99','\U7C9A','\U7C9B','\U7C9C','\U7C9D','\U7C9E','\U7C9F','\U7CA0','\U7CA1','\U7CA2','\U7CA3','\U7CA4','\U7CA5','\U7CA6','\U7CA7','\U7CA8','\U7CA9','\U7CAA','\U7CAB','\U7CAC','\U7CAD','\U7CAE','\U7CAF','\U7CB0','\U7CB1','\U7CB2','\U7CB3','\U7CB4','\U7CB5','\U7CB6','\U7CB7','\U7CB8','\U7CB9','\U7CBA','\U7CBB','\U7CBC','\U7CBD','\U7CBE','\U7CBF','\U7CC0','\U7CC1','\U7CC2','\U7CC3','\U7CC4','\U7CC5','\U7CC6','\U7CC7','\U7CC8','\U7CC9','\U7CCA','\U7CCB','\U7CCC','\U7CCD','\U7CCE','\U7CCF','\U7CD0','\U7CD1','\U7CD2','\U7CD3','\U7CD4','\U7CD5','\U7CD6','\U7CD7','\U7CD8','\U7CD9','\U7CDA','\U7CDB','\U7CDC','\U7CDD','\U7CDE','\U7CDF','\U7CE0','\U7CE1','\U7CE2','\U7CE3','\U7CE4','\U7CE5','\U7CE6','\U7CE7','\U7CE8','\U7CE9','\U7CEA','\U7CEB','\U7CEC','\U7CED','\U7CEE','\U7CEF','\U7CF0','\U7CF1','\U7CF2','\U7CF3','\U7CF4','\U7CF5','\U7CF6','\U7CF7','\U7CF8','\U7CF9','\U7CFA','\U7CFB','\U7CFC','\U7CFD','\U7CFE','\U7CFF','\U7D00','\U7D01','\U7D02','\U7D03','\U7D04','\U7D05','\U7D06','\U7D07','\U7D08','\U7D09','\U7D0A','\U7D0B','\U7D0C','\U7D0D','\U7D0E','\U7D0F','\U7D10','\U7D11','\U7D12','\U7D13','\U7D14','\U7D15','\U7D16','\U7D17','\U7D18','\U7D19','\U7D1A','\U7D1B','\U7D1C','\U7D1D','\U7D1E','\U7D1F','\U7D20','\U7D21','\U7D22','\U7D23','\U7D24','\U7D25','\U7D26','\U7D27','\U7D28','\U7D29','\U7D2A','\U7D2B','\U7D2C','\U7D2D','\U7D2E','\U7D2F','\U7D30','\U7D31','\U7D32','\U7D33','\U7D34','\U7D35','\U7D36','\U7D37','\U7D38','\U7D39','\U7D3A','\U7D3B','\U7D3C','\U7D3D','\U7D3E','\U7D3F','\U7D40','\U7D41','\U7D42','\U7D43','\U7D44','\U7D45','\U7D46','\U7D47','\U7D48','\U7D49','\U7D4A','\U7D4B','\U7D4C','\U7D4D','\U7D4E','\U7D4F','\U7D50','\U7D51','\U7D52','\U7D53','\U7D54','\U7D55','\U7D56','\U7D57','\U7D58','\U7D59','\U7D5A','\U7D5B','\U7D5C','\U7D5D','\U7D5E','\U7D5F','\U7D60','\U7D61','\U7D62','\U7D63','\U7D64','\U7D65','\U7D66','\U7D67','\U7D68','\U7D69','\U7D6A','\U7D6B','\U7D6C','\U7D6D','\U7D6E','\U7D6F','\U7D70','\U7D71','\U7D72','\U7D73','\U7D74','\U7D75','\U7D76','\U7D77','\U7D78','\U7D79','\U7D7A','\U7D7B','\U7D7C','\U7D7D','\U7D7E','\U7D7F','\U7D80','\U7D81','\U7D82','\U7D83','\U7D84','\U7D85','\U7D86','\U7D87','\U7D88','\U7D89','\U7D8A','\U7D8B','\U7D8C','\U7D8D','\U7D8E','\U7D8F','\U7D90','\U7D91','\U7D92','\U7D93','\U7D94','\U7D95','\U7D96','\U7D97','\U7D98','\U7D99','\U7D9A','\U7D9B','\U7D9C','\U7D9D','\U7D9E','\U7D9F','\U7DA0','\U7DA1','\U7DA2','\U7DA3','\U7DA4','\U7DA5','\U7DA6','\U7DA7','\U7DA8','\U7DA9','\U7DAA','\U7DAB','\U7DAC','\U7DAD','\U7DAE','\U7DAF','\U7DB0','\U7DB1','\U7DB2','\U7DB3','\U7DB4','\U7DB5','\U7DB6','\U7DB7','\U7DB8','\U7DB9','\U7DBA','\U7DBB','\U7DBC','\U7DBD','\U7DBE','\U7DBF','\U7DC0','\U7DC1','\U7DC2','\U7DC3','\U7DC4','\U7DC5','\U7DC6','\U7DC7','\U7DC8','\U7DC9','\U7DCA','\U7DCB','\U7DCC','\U7DCD','\U7DCE','\U7DCF','\U7DD0','\U7DD1','\U7DD2','\U7DD3','\U7DD4','\U7DD5','\U7DD6','\U7DD7','\U7DD8','\U7DD9','\U7DDA','\U7DDB','\U7DDC','\U7DDD','\U7DDE','\U7DDF','\U7DE0','\U7DE1','\U7DE2','\U7DE3','\U7DE4','\U7DE5','\U7DE6','\U7DE7','\U7DE8','\U7DE9','\U7DEA','\U7DEB','\U7DEC','\U7DED','\U7DEE','\U7DEF','\U7DF0','\U7DF1','\U7DF2','\U7DF3','\U7DF4','\U7DF5','\U7DF6','\U7DF7','\U7DF8','\U7DF9','\U7DFA','\U7DFB','\U7DFC','\U7DFD','\U7DFE','\U7DFF','\U7E00','\U7E01','\U7E02','\U7E03','\U7E04','\U7E05','\U7E06','\U7E07','\U7E08','\U7E09','\U7E0A','\U7E0B','\U7E0C','\U7E0D','\U7E0E','\U7E0F','\U7E10','\U7E11','\U7E12','\U7E13','\U7E14','\U7E15','\U7E16','\U7E17','\U7E18','\U7E19','\U7E1A','\U7E1B','\U7E1C','\U7E1D','\U7E1E','\U7E1F','\U7E20','\U7E21','\U7E22','\U7E23','\U7E24','\U7E25','\U7E26','\U7E27','\U7E28','\U7E29','\U7E2A','\U7E2B','\U7E2C','\U7E2D','\U7E2E','\U7E2F','\U7E30','\U7E31','\U7E32','\U7E33','\U7E34','\U7E35','\U7E36','\U7E37','\U7E38','\U7E39','\U7E3A','\U7E3B','\U7E3C','\U7E3D','\U7E3E','\U7E3F','\U7E40','\U7E41','\U7E42','\U7E43','\U7E44','\U7E45','\U7E46','\U7E47','\U7E48','\U7E49','\U7E4A','\U7E4B','\U7E4C','\U7E4D','\U7E4E','\U7E4F','\U7E50','\U7E51','\U7E52','\U7E53','\U7E54','\U7E55','\U7E56','\U7E57','\U7E58','\U7E59','\U7E5A','\U7E5B','\U7E5C','\U7E5D','\U7E5E','\U7E5F','\U7E60','\U7E61','\U7E62','\U7E63','\U7E64','\U7E65','\U7E66','\U7E67','\U7E68','\U7E69','\U7E6A','\U7E6B','\U7E6C','\U7E6D','\U7E6E','\U7E6F','\U7E70','\U7E71','\U7E72','\U7E73','\U7E74','\U7E75','\U7E76','\U7E77','\U7E78','\U7E79','\U7E7A','\U7E7B','\U7E7C','\U7E7D','\U7E7E','\U7E7F','\U7E80','\U7E81','\U7E82','\U7E83','\U7E84','\U7E85','\U7E86','\U7E87','\U7E88','\U7E89','\U7E8A','\U7E8B','\U7E8C','\U7E8D','\U7E8E','\U7E8F','\U7E90','\U7E91','\U7E92','\U7E93','\U7E94','\U7E95','\U7E96','\U7E97','\U7E98','\U7E99','\U7E9A','\U7E9B','\U7E9C','\U7E9D','\U7E9E','\U7E9F','\U7EA0','\U7EA1','\U7EA2','\U7EA3','\U7EA4','\U7EA5','\U7EA6','\U7EA7','\U7EA8','\U7EA9','\U7EAA','\U7EAB','\U7EAC','\U7EAD','\U7EAE','\U7EAF','\U7EB0','\U7EB1','\U7EB2','\U7EB3','\U7EB4','\U7EB5','\U7EB6','\U7EB7','\U7EB8','\U7EB9','\U7EBA','\U7EBB','\U7EBC','\U7EBD','\U7EBE','\U7EBF','\U7EC0','\U7EC1','\U7EC2','\U7EC3','\U7EC4','\U7EC5','\U7EC6','\U7EC7','\U7EC8','\U7EC9','\U7ECA','\U7ECB','\U7ECC','\U7ECD','\U7ECE','\U7ECF','\U7ED0','\U7ED1','\U7ED2','\U7ED3','\U7ED4','\U7ED5','\U7ED6','\U7ED7','\U7ED8','\U7ED9','\U7EDA','\U7EDB','\U7EDC','\U7EDD','\U7EDE','\U7EDF','\U7EE0','\U7EE1','\U7EE2','\U7EE3','\U7EE4','\U7EE5','\U7EE6','\U7EE7','\U7EE8','\U7EE9','\U7EEA','\U7EEB','\U7EEC','\U7EED','\U7EEE','\U7EEF','\U7EF0','\U7EF1','\U7EF2','\U7EF3','\U7EF4','\U7EF5','\U7EF6','\U7EF7','\U7EF8','\U7EF9','\U7EFA','\U7EFB','\U7EFC','\U7EFD','\U7EFE','\U7EFF','\U7F00','\U7F01','\U7F02','\U7F03','\U7F04','\U7F05','\U7F06','\U7F07','\U7F08','\U7F09','\U7F0A','\U7F0B','\U7F0C','\U7F0D','\U7F0E','\U7F0F','\U7F10','\U7F11','\U7F12','\U7F13','\U7F14','\U7F15','\U7F16','\U7F17','\U7F18','\U7F19','\U7F1A','\U7F1B','\U7F1C','\U7F1D','\U7F1E','\U7F1F','\U7F20','\U7F21','\U7F22','\U7F23','\U7F24','\U7F25','\U7F26','\U7F27','\U7F28','\U7F29','\U7F2A','\U7F2B','\U7F2C','\U7F2D','\U7F2E','\U7F2F','\U7F30','\U7F31','\U7F32','\U7F33','\U7F34','\U7F35','\U7F36','\U7F37','\U7F38','\U7F39','\U7F3A','\U7F3B','\U7F3C','\U7F3D','\U7F3E','\U7F3F','\U7F40','\U7F41','\U7F42','\U7F43','\U7F44','\U7F45','\U7F46','\U7F47','\U7F48','\U7F49','\U7F4A','\U7F4B','\U7F4C','\U7F4D','\U7F4E','\U7F4F','\U7F50','\U7F51','\U7F52','\U7F53','\U7F54','\U7F55','\U7F56','\U7F57','\U7F58','\U7F59','\U7F5A','\U7F5B','\U7F5C','\U7F5D','\U7F5E','\U7F5F','\U7F60','\U7F61','\U7F62','\U7F63','\U7F64','\U7F65','\U7F66','\U7F67','\U7F68','\U7F69','\U7F6A','\U7F6B','\U7F6C','\U7F6D','\U7F6E','\U7F6F','\U7F70','\U7F71','\U7F72','\U7F73','\U7F74','\U7F75','\U7F76','\U7F77','\U7F78','\U7F79','\U7F7A','\U7F7B','\U7F7C','\U7F7D','\U7F7E','\U7F7F','\U7F80','\U7F81','\U7F82','\U7F83','\U7F84','\U7F85','\U7F86','\U7F87','\U7F88','\U7F89','\U7F8A','\U7F8B','\U7F8C','\U7F8D','\U7F8E','\U7F8F','\U7F90','\U7F91','\U7F92','\U7F93','\U7F94','\U7F95','\U7F96','\U7F97','\U7F98','\U7F99','\U7F9A','\U7F9B','\U7F9C','\U7F9D','\U7F9E','\U7F9F','\U7FA0','\U7FA1','\U7FA2','\U7FA3','\U7FA4','\U7FA5','\U7FA6','\U7FA7','\U7FA8','\U7FA9','\U7FAA','\U7FAB','\U7FAC','\U7FAD','\U7FAE','\U7FAF','\U7FB0','\U7FB1','\U7FB2','\U7FB3','\U7FB4','\U7FB5','\U7FB6','\U7FB7','\U7FB8','\U7FB9','\U7FBA','\U7FBB','\U7FBC','\U7FBD','\U7FBE','\U7FBF','\U7FC0','\U7FC1','\U7FC2','\U7FC3','\U7FC4','\U7FC5','\U7FC6','\U7FC7','\U7FC8','\U7FC9','\U7FCA','\U7FCB','\U7FCC','\U7FCD','\U7FCE','\U7FCF','\U7FD0','\U7FD1','\U7FD2','\U7FD3','\U7FD4','\U7FD5','\U7FD6','\U7FD7','\U7FD8','\U7FD9','\U7FDA','\U7FDB','\U7FDC','\U7FDD','\U7FDE','\U7FDF','\U7FE0','\U7FE1','\U7FE2','\U7FE3','\U7FE4','\U7FE5','\U7FE6','\U7FE7','\U7FE8','\U7FE9','\U7FEA','\U7FEB','\U7FEC','\U7FED','\U7FEE','\U7FEF','\U7FF0','\U7FF1','\U7FF2','\U7FF3','\U7FF4','\U7FF5','\U7FF6','\U7FF7','\U7FF8','\U7FF9','\U7FFA','\U7FFB','\U7FFC','\U7FFD','\U7FFE','\U7FFF','\U8000','\U8001','\U8002','\U8003','\U8004','\U8005','\U8006','\U8007','\U8008','\U8009','\U800A','\U800B','\U800C','\U800D','\U800E','\U800F','\U8010','\U8011','\U8012','\U8013','\U8014','\U8015','\U8016','\U8017','\U8018','\U8019','\U801A','\U801B','\U801C','\U801D','\U801E','\U801F','\U8020','\U8021','\U8022','\U8023','\U8024','\U8025','\U8026','\U8027','\U8028','\U8029','\U802A','\U802B','\U802C','\U802D','\U802E','\U802F','\U8030','\U8031','\U8032','\U8033','\U8034','\U8035','\U8036','\U8037','\U8038','\U8039','\U803A','\U803B','\U803C','\U803D','\U803E','\U803F','\U8040','\U8041','\U8042','\U8043','\U8044','\U8045','\U8046','\U8047','\U8048','\U8049','\U804A','\U804B','\U804C','\U804D','\U804E','\U804F','\U8050','\U8051','\U8052','\U8053','\U8054','\U8055','\U8056','\U8057','\U8058','\U8059','\U805A','\U805B','\U805C','\U805D','\U805E','\U805F','\U8060','\U8061','\U8062','\U8063','\U8064','\U8065','\U8066','\U8067','\U8068','\U8069','\U806A','\U806B','\U806C','\U806D','\U806E','\U806F','\U8070','\U8071','\U8072','\U8073','\U8074','\U8075','\U8076','\U8077','\U8078','\U8079','\U807A','\U807B','\U807C','\U807D','\U807E','\U807F','\U8080','\U8081','\U8082','\U8083','\U8084','\U8085','\U8086','\U8087','\U8088','\U8089','\U808A','\U808B','\U808C','\U808D','\U808E','\U808F','\U8090','\U8091','\U8092','\U8093','\U8094','\U8095','\U8096','\U8097','\U8098','\U8099','\U809A','\U809B','\U809C','\U809D','\U809E','\U809F','\U80A0','\U80A1','\U80A2','\U80A3','\U80A4','\U80A5','\U80A6','\U80A7','\U80A8','\U80A9','\U80AA','\U80AB','\U80AC','\U80AD','\U80AE','\U80AF','\U80B0','\U80B1','\U80B2','\U80B3','\U80B4','\U80B5','\U80B6','\U80B7','\U80B8','\U80B9','\U80BA','\U80BB','\U80BC','\U80BD','\U80BE','\U80BF','\U80C0','\U80C1','\U80C2','\U80C3','\U80C4','\U80C5','\U80C6','\U80C7','\U80C8','\U80C9','\U80CA','\U80CB','\U80CC','\U80CD','\U80CE','\U80CF','\U80D0','\U80D1','\U80D2','\U80D3','\U80D4','\U80D5','\U80D6','\U80D7','\U80D8','\U80D9','\U80DA','\U80DB','\U80DC','\U80DD','\U80DE','\U80DF','\U80E0','\U80E1','\U80E2','\U80E3','\U80E4','\U80E5','\U80E6','\U80E7','\U80E8','\U80E9','\U80EA','\U80EB','\U80EC','\U80ED','\U80EE','\U80EF','\U80F0','\U80F1','\U80F2','\U80F3','\U80F4','\U80F5','\U80F6','\U80F7','\U80F8','\U80F9','\U80FA','\U80FB','\U80FC','\U80FD','\U80FE','\U80FF','\U8100','\U8101','\U8102','\U8103','\U8104','\U8105','\U8106','\U8107','\U8108','\U8109','\U810A','\U810B','\U810C','\U810D','\U810E','\U810F','\U8110','\U8111','\U8112','\U8113','\U8114','\U8115','\U8116','\U8117','\U8118','\U8119','\U811A','\U811B','\U811C','\U811D','\U811E','\U811F','\U8120','\U8121','\U8122','\U8123','\U8124','\U8125','\U8126','\U8127','\U8128','\U8129','\U812A','\U812B','\U812C','\U812D','\U812E','\U812F','\U8130','\U8131','\U8132','\U8133','\U8134','\U8135','\U8136','\U8137','\U8138','\U8139','\U813A','\U813B','\U813C','\U813D','\U813E','\U813F','\U8140','\U8141','\U8142','\U8143','\U8144','\U8145','\U8146','\U8147','\U8148','\U8149','\U814A','\U814B','\U814C','\U814D','\U814E','\U814F','\U8150','\U8151','\U8152','\U8153','\U8154','\U8155','\U8156','\U8157','\U8158','\U8159','\U815A','\U815B','\U815C','\U815D','\U815E','\U815F','\U8160','\U8161','\U8162','\U8163','\U8164','\U8165','\U8166','\U8167','\U8168','\U8169','\U816A','\U816B','\U816C','\U816D','\U816E','\U816F','\U8170','\U8171','\U8172','\U8173','\U8174','\U8175','\U8176','\U8177','\U8178','\U8179','\U817A','\U817B','\U817C','\U817D','\U817E','\U817F','\U8180','\U8181','\U8182','\U8183','\U8184','\U8185','\U8186','\U8187','\U8188','\U8189','\U818A','\U818B','\U818C','\U818D','\U818E','\U818F','\U8190','\U8191','\U8192','\U8193','\U8194','\U8195','\U8196','\U8197','\U8198','\U8199','\U819A','\U819B','\U819C','\U819D','\U819E','\U819F','\U81A0','\U81A1','\U81A2','\U81A3','\U81A4','\U81A5','\U81A6','\U81A7','\U81A8','\U81A9','\U81AA','\U81AB','\U81AC','\U81AD','\U81AE','\U81AF','\U81B0','\U81B1','\U81B2','\U81B3','\U81B4','\U81B5','\U81B6','\U81B7','\U81B8','\U81B9','\U81BA','\U81BB','\U81BC','\U81BD','\U81BE','\U81BF','\U81C0','\U81C1','\U81C2','\U81C3','\U81C4','\U81C5','\U81C6','\U81C7','\U81C8','\U81C9','\U81CA','\U81CB','\U81CC','\U81CD','\U81CE','\U81CF','\U81D0','\U81D1','\U81D2','\U81D3','\U81D4','\U81D5','\U81D6','\U81D7','\U81D8','\U81D9','\U81DA','\U81DB','\U81DC','\U81DD','\U81DE','\U81DF','\U81E0','\U81E1','\U81E2','\U81E3','\U81E4','\U81E5','\U81E6','\U81E7','\U81E8','\U81E9','\U81EA','\U81EB','\U81EC','\U81ED','\U81EE','\U81EF','\U81F0','\U81F1','\U81F2','\U81F3','\U81F4','\U81F5','\U81F6','\U81F7','\U81F8','\U81F9','\U81FA','\U81FB','\U81FC','\U81FD','\U81FE','\U81FF','\U8200','\U8201','\U8202','\U8203','\U8204','\U8205','\U8206','\U8207','\U8208','\U8209','\U820A','\U820B','\U820C','\U820D','\U820E','\U820F','\U8210','\U8211','\U8212','\U8213','\U8214','\U8215','\U8216','\U8217','\U8218','\U8219','\U821A','\U821B','\U821C','\U821D','\U821E','\U821F','\U8220','\U8221','\U8222','\U8223','\U8224','\U8225','\U8226','\U8227','\U8228','\U8229','\U822A','\U822B','\U822C','\U822D','\U822E','\U822F','\U8230','\U8231','\U8232','\U8233','\U8234','\U8235','\U8236','\U8237','\U8238','\U8239','\U823A','\U823B','\U823C','\U823D','\U823E','\U823F','\U8240','\U8241','\U8242','\U8243','\U8244','\U8245','\U8246','\U8247','\U8248','\U8249','\U824A','\U824B','\U824C','\U824D','\U824E','\U824F','\U8250','\U8251','\U8252','\U8253','\U8254','\U8255','\U8256','\U8257','\U8258','\U8259','\U825A','\U825B','\U825C','\U825D','\U825E','\U825F','\U8260','\U8261','\U8262','\U8263','\U8264','\U8265','\U8266','\U8267','\U8268','\U8269','\U826A','\U826B','\U826C','\U826D','\U826E','\U826F','\U8270','\U8271','\U8272','\U8273','\U8274','\U8275','\U8276','\U8277','\U8278','\U8279','\U827A','\U827B','\U827C','\U827D','\U827E','\U827F','\U8280','\U8281','\U8282','\U8283','\U8284','\U8285','\U8286','\U8287','\U8288','\U8289','\U828A','\U828B','\U828C','\U828D','\U828E','\U828F','\U8290','\U8291','\U8292','\U8293','\U8294','\U8295','\U8296','\U8297','\U8298','\U8299','\U829A','\U829B','\U829C','\U829D','\U829E','\U829F','\U82A0','\U82A1','\U82A2','\U82A3','\U82A4','\U82A5','\U82A6','\U82A7','\U82A8','\U82A9','\U82AA','\U82AB','\U82AC','\U82AD','\U82AE','\U82AF','\U82B0','\U82B1','\U82B2','\U82B3','\U82B4','\U82B5','\U82B6','\U82B7','\U82B8','\U82B9','\U82BA','\U82BB','\U82BC','\U82BD','\U82BE','\U82BF','\U82C0','\U82C1','\U82C2','\U82C3','\U82C4','\U82C5','\U82C6','\U82C7','\U82C8','\U82C9','\U82CA','\U82CB','\U82CC','\U82CD','\U82CE','\U82CF','\U82D0','\U82D1','\U82D2','\U82D3','\U82D4','\U82D5','\U82D6','\U82D7','\U82D8','\U82D9','\U82DA','\U82DB','\U82DC','\U82DD','\U82DE','\U82DF','\U82E0','\U82E1','\U82E2','\U82E3','\U82E4','\U82E5','\U82E6','\U82E7','\U82E8','\U82E9','\U82EA','\U82EB','\U82EC','\U82ED','\U82EE','\U82EF','\U82F0','\U82F1','\U82F2','\U82F3','\U82F4','\U82F5','\U82F6','\U82F7','\U82F8','\U82F9','\U82FA','\U82FB','\U82FC','\U82FD','\U82FE','\U82FF','\U8300','\U8301','\U8302','\U8303','\U8304','\U8305','\U8306','\U8307','\U8308','\U8309','\U830A','\U830B','\U830C','\U830D','\U830E','\U830F','\U8310','\U8311','\U8312','\U8313','\U8314','\U8315','\U8316','\U8317','\U8318','\U8319','\U831A','\U831B','\U831C','\U831D','\U831E','\U831F','\U8320','\U8321','\U8322','\U8323','\U8324','\U8325','\U8326','\U8327','\U8328','\U8329','\U832A','\U832B','\U832C','\U832D','\U832E','\U832F','\U8330','\U8331','\U8332','\U8333','\U8334','\U8335','\U8336','\U8337','\U8338','\U8339','\U833A','\U833B','\U833C','\U833D','\U833E','\U833F','\U8340','\U8341','\U8342','\U8343','\U8344','\U8345','\U8346','\U8347','\U8348','\U8349','\U834A','\U834B','\U834C','\U834D','\U834E','\U834F','\U8350','\U8351','\U8352','\U8353','\U8354','\U8355','\U8356','\U8357','\U8358','\U8359','\U835A','\U835B','\U835C','\U835D','\U835E','\U835F','\U8360','\U8361','\U8362','\U8363','\U8364','\U8365','\U8366','\U8367','\U8368','\U8369','\U836A','\U836B','\U836C','\U836D','\U836E','\U836F','\U8370','\U8371','\U8372','\U8373','\U8374','\U8375','\U8376','\U8377','\U8378','\U8379','\U837A','\U837B','\U837C','\U837D','\U837E','\U837F','\U8380','\U8381','\U8382','\U8383','\U8384','\U8385','\U8386','\U8387','\U8388','\U8389','\U838A','\U838B','\U838C','\U838D','\U838E','\U838F','\U8390','\U8391','\U8392','\U8393','\U8394','\U8395','\U8396','\U8397','\U8398','\U8399','\U839A','\U839B','\U839C','\U839D','\U839E','\U839F','\U83A0','\U83A1','\U83A2','\U83A3','\U83A4','\U83A5','\U83A6','\U83A7','\U83A8','\U83A9','\U83AA','\U83AB','\U83AC','\U83AD','\U83AE','\U83AF','\U83B0','\U83B1','\U83B2','\U83B3','\U83B4','\U83B5','\U83B6','\U83B7','\U83B8','\U83B9','\U83BA','\U83BB','\U83BC','\U83BD','\U83BE','\U83BF','\U83C0','\U83C1','\U83C2','\U83C3','\U83C4','\U83C5','\U83C6','\U83C7','\U83C8','\U83C9','\U83CA','\U83CB','\U83CC','\U83CD','\U83CE','\U83CF','\U83D0','\U83D1','\U83D2','\U83D3','\U83D4','\U83D5','\U83D6','\U83D7','\U83D8','\U83D9','\U83DA','\U83DB','\U83DC','\U83DD','\U83DE','\U83DF','\U83E0','\U83E1','\U83E2','\U83E3','\U83E4','\U83E5','\U83E6','\U83E7','\U83E8','\U83E9','\U83EA','\U83EB','\U83EC','\U83ED','\U83EE','\U83EF','\U83F0','\U83F1','\U83F2','\U83F3','\U83F4','\U83F5','\U83F6','\U83F7','\U83F8','\U83F9','\U83FA','\U83FB','\U83FC','\U83FD','\U83FE','\U83FF','\U8400','\U8401','\U8402','\U8403','\U8404','\U8405','\U8406','\U8407','\U8408','\U8409','\U840A','\U840B','\U840C','\U840D','\U840E','\U840F','\U8410','\U8411','\U8412','\U8413','\U8414','\U8415','\U8416','\U8417','\U8418','\U8419','\U841A','\U841B','\U841C','\U841D','\U841E','\U841F','\U8420','\U8421','\U8422','\U8423','\U8424','\U8425','\U8426','\U8427','\U8428','\U8429','\U842A','\U842B','\U842C','\U842D','\U842E','\U842F','\U8430','\U8431','\U8432','\U8433','\U8434','\U8435','\U8436','\U8437','\U8438','\U8439','\U843A','\U843B','\U843C','\U843D','\U843E','\U843F','\U8440','\U8441','\U8442','\U8443','\U8444','\U8445','\U8446','\U8447','\U8448','\U8449','\U844A','\U844B','\U844C','\U844D','\U844E','\U844F','\U8450','\U8451','\U8452','\U8453','\U8454','\U8455','\U8456','\U8457','\U8458','\U8459','\U845A','\U845B','\U845C','\U845D','\U845E','\U845F','\U8460','\U8461','\U8462','\U8463','\U8464','\U8465','\U8466','\U8467','\U8468','\U8469','\U846A','\U846B','\U846C','\U846D','\U846E','\U846F','\U8470','\U8471','\U8472','\U8473','\U8474','\U8475','\U8476','\U8477','\U8478','\U8479','\U847A','\U847B','\U847C','\U847D','\U847E','\U847F','\U8480','\U8481','\U8482','\U8483','\U8484','\U8485','\U8486','\U8487','\U8488','\U8489','\U848A','\U848B','\U848C','\U848D','\U848E','\U848F','\U8490','\U8491','\U8492','\U8493','\U8494','\U8495','\U8496','\U8497','\U8498','\U8499','\U849A','\U849B','\U849C','\U849D','\U849E','\U849F','\U84A0','\U84A1','\U84A2','\U84A3','\U84A4','\U84A5','\U84A6','\U84A7','\U84A8','\U84A9','\U84AA','\U84AB','\U84AC','\U84AD','\U84AE','\U84AF','\U84B0','\U84B1','\U84B2','\U84B3','\U84B4','\U84B5','\U84B6','\U84B7','\U84B8','\U84B9','\U84BA','\U84BB','\U84BC','\U84BD','\U84BE','\U84BF','\U84C0','\U84C1','\U84C2','\U84C3','\U84C4','\U84C5','\U84C6','\U84C7','\U84C8','\U84C9','\U84CA','\U84CB','\U84CC','\U84CD','\U84CE','\U84CF','\U84D0','\U84D1','\U84D2','\U84D3','\U84D4','\U84D5','\U84D6','\U84D7','\U84D8','\U84D9','\U84DA','\U84DB','\U84DC','\U84DD','\U84DE','\U84DF','\U84E0','\U84E1','\U84E2','\U84E3','\U84E4','\U84E5','\U84E6','\U84E7','\U84E8','\U84E9','\U84EA','\U84EB','\U84EC','\U84ED','\U84EE','\U84EF','\U84F0','\U84F1','\U84F2','\U84F3','\U84F4','\U84F5','\U84F6','\U84F7','\U84F8','\U84F9','\U84FA','\U84FB','\U84FC','\U84FD','\U84FE','\U84FF','\U8500','\U8501','\U8502','\U8503','\U8504','\U8505','\U8506','\U8507','\U8508','\U8509','\U850A','\U850B','\U850C','\U850D','\U850E','\U850F','\U8510','\U8511','\U8512','\U8513','\U8514','\U8515','\U8516','\U8517','\U8518','\U8519','\U851A','\U851B','\U851C','\U851D','\U851E','\U851F','\U8520','\U8521','\U8522','\U8523','\U8524','\U8525','\U8526','\U8527','\U8528','\U8529','\U852A','\U852B','\U852C','\U852D','\U852E','\U852F','\U8530','\U8531','\U8532','\U8533','\U8534','\U8535','\U8536','\U8537','\U8538','\U8539','\U853A','\U853B','\U853C','\U853D','\U853E','\U853F','\U8540','\U8541','\U8542','\U8543','\U8544','\U8545','\U8546','\U8547','\U8548','\U8549','\U854A','\U854B','\U854C','\U854D','\U854E','\U854F','\U8550','\U8551','\U8552','\U8553','\U8554','\U8555','\U8556','\U8557','\U8558','\U8559','\U855A','\U855B','\U855C','\U855D','\U855E','\U855F','\U8560','\U8561','\U8562','\U8563','\U8564','\U8565','\U8566','\U8567','\U8568','\U8569','\U856A','\U856B','\U856C','\U856D','\U856E','\U856F','\U8570','\U8571','\U8572','\U8573','\U8574','\U8575','\U8576','\U8577','\U8578','\U8579','\U857A','\U857B','\U857C','\U857D','\U857E','\U857F','\U8580','\U8581','\U8582','\U8583','\U8584','\U8585','\U8586','\U8587','\U8588','\U8589','\U858A','\U858B','\U858C','\U858D','\U858E','\U858F','\U8590','\U8591','\U8592','\U8593','\U8594','\U8595','\U8596','\U8597','\U8598','\U8599','\U859A','\U859B','\U859C','\U859D','\U859E','\U859F','\U85A0','\U85A1','\U85A2','\U85A3','\U85A4','\U85A5','\U85A6','\U85A7','\U85A8','\U85A9','\U85AA','\U85AB','\U85AC','\U85AD','\U85AE','\U85AF','\U85B0','\U85B1','\U85B2','\U85B3','\U85B4','\U85B5','\U85B6','\U85B7','\U85B8','\U85B9','\U85BA','\U85BB','\U85BC','\U85BD','\U85BE','\U85BF','\U85C0','\U85C1','\U85C2','\U85C3','\U85C4','\U85C5','\U85C6','\U85C7','\U85C8','\U85C9','\U85CA','\U85CB','\U85CC','\U85CD','\U85CE','\U85CF','\U85D0','\U85D1','\U85D2','\U85D3','\U85D4','\U85D5','\U85D6','\U85D7','\U85D8','\U85D9','\U85DA','\U85DB','\U85DC','\U85DD','\U85DE','\U85DF','\U85E0','\U85E1','\U85E2','\U85E3','\U85E4','\U85E5','\U85E6','\U85E7','\U85E8','\U85E9','\U85EA','\U85EB','\U85EC','\U85ED','\U85EE','\U85EF','\U85F0','\U85F1','\U85F2','\U85F3','\U85F4','\U85F5','\U85F6','\U85F7','\U85F8','\U85F9','\U85FA','\U85FB','\U85FC','\U85FD','\U85FE','\U85FF','\U8600','\U8601','\U8602','\U8603','\U8604','\U8605','\U8606','\U8607','\U8608','\U8609','\U860A','\U860B','\U860C','\U860D','\U860E','\U860F','\U8610','\U8611','\U8612','\U8613','\U8614','\U8615','\U8616','\U8617','\U8618','\U8619','\U861A','\U861B','\U861C','\U861D','\U861E','\U861F','\U8620','\U8621','\U8622','\U8623','\U8624','\U8625','\U8626','\U8627','\U8628','\U8629','\U862A','\U862B','\U862C','\U862D','\U862E','\U862F','\U8630','\U8631','\U8632','\U8633','\U8634','\U8635','\U8636','\U8637','\U8638','\U8639','\U863A','\U863B','\U863C','\U863D','\U863E','\U863F','\U8640','\U8641','\U8642','\U8643','\U8644','\U8645','\U8646','\U8647','\U8648','\U8649','\U864A','\U864B','\U864C','\U864D','\U864E','\U864F','\U8650','\U8651','\U8652','\U8653','\U8654','\U8655','\U8656','\U8657','\U8658','\U8659','\U865A','\U865B','\U865C','\U865D','\U865E','\U865F','\U8660','\U8661','\U8662','\U8663','\U8664','\U8665','\U8666','\U8667','\U8668','\U8669','\U866A','\U866B','\U866C','\U866D','\U866E','\U866F','\U8670','\U8671','\U8672','\U8673','\U8674','\U8675','\U8676','\U8677','\U8678','\U8679','\U867A','\U867B','\U867C','\U867D','\U867E','\U867F','\U8680','\U8681','\U8682','\U8683','\U8684','\U8685','\U8686','\U8687','\U8688','\U8689','\U868A','\U868B','\U868C','\U868D','\U868E','\U868F','\U8690','\U8691','\U8692','\U8693','\U8694','\U8695','\U8696','\U8697','\U8698','\U8699','\U869A','\U869B','\U869C','\U869D','\U869E','\U869F','\U86A0','\U86A1','\U86A2','\U86A3','\U86A4','\U86A5','\U86A6','\U86A7','\U86A8','\U86A9','\U86AA','\U86AB','\U86AC','\U86AD','\U86AE','\U86AF','\U86B0','\U86B1','\U86B2','\U86B3','\U86B4','\U86B5','\U86B6','\U86B7','\U86B8','\U86B9','\U86BA','\U86BB','\U86BC','\U86BD','\U86BE','\U86BF','\U86C0','\U86C1','\U86C2','\U86C3','\U86C4','\U86C5','\U86C6','\U86C7','\U86C8','\U86C9','\U86CA','\U86CB','\U86CC','\U86CD','\U86CE','\U86CF','\U86D0','\U86D1','\U86D2','\U86D3','\U86D4','\U86D5','\U86D6','\U86D7','\U86D8','\U86D9','\U86DA','\U86DB','\U86DC','\U86DD','\U86DE','\U86DF','\U86E0','\U86E1','\U86E2','\U86E3','\U86E4','\U86E5','\U86E6','\U86E7','\U86E8','\U86E9','\U86EA','\U86EB','\U86EC','\U86ED','\U86EE','\U86EF','\U86F0','\U86F1','\U86F2','\U86F3','\U86F4','\U86F5','\U86F6','\U86F7','\U86F8','\U86F9','\U86FA','\U86FB','\U86FC','\U86FD','\U86FE','\U86FF','\U8700','\U8701','\U8702','\U8703','\U8704','\U8705','\U8706','\U8707','\U8708','\U8709','\U870A','\U870B','\U870C','\U870D','\U870E','\U870F','\U8710','\U8711','\U8712','\U8713','\U8714','\U8715','\U8716','\U8717','\U8718','\U8719','\U871A','\U871B','\U871C','\U871D','\U871E','\U871F','\U8720','\U8721','\U8722','\U8723','\U8724','\U8725','\U8726','\U8727','\U8728','\U8729','\U872A','\U872B','\U872C','\U872D','\U872E','\U872F','\U8730','\U8731','\U8732','\U8733','\U8734','\U8735','\U8736','\U8737','\U8738','\U8739','\U873A','\U873B','\U873C','\U873D','\U873E','\U873F','\U8740','\U8741','\U8742','\U8743','\U8744','\U8745','\U8746','\U8747','\U8748','\U8749','\U874A','\U874B','\U874C','\U874D','\U874E','\U874F','\U8750','\U8751','\U8752','\U8753','\U8754','\U8755','\U8756','\U8757','\U8758','\U8759','\U875A','\U875B','\U875C','\U875D','\U875E','\U875F','\U8760','\U8761','\U8762','\U8763','\U8764','\U8765','\U8766','\U8767','\U8768','\U8769','\U876A','\U876B','\U876C','\U876D','\U876E','\U876F','\U8770','\U8771','\U8772','\U8773','\U8774','\U8775','\U8776','\U8777','\U8778','\U8779','\U877A','\U877B','\U877C','\U877D','\U877E','\U877F','\U8780','\U8781','\U8782','\U8783','\U8784','\U8785','\U8786','\U8787','\U8788','\U8789','\U878A','\U878B','\U878C','\U878D','\U878E','\U878F','\U8790','\U8791','\U8792','\U8793','\U8794','\U8795','\U8796','\U8797','\U8798','\U8799','\U879A','\U879B','\U879C','\U879D','\U879E','\U879F','\U87A0','\U87A1','\U87A2','\U87A3','\U87A4','\U87A5','\U87A6','\U87A7','\U87A8','\U87A9','\U87AA','\U87AB','\U87AC','\U87AD','\U87AE','\U87AF','\U87B0','\U87B1','\U87B2','\U87B3','\U87B4','\U87B5','\U87B6','\U87B7','\U87B8','\U87B9','\U87BA','\U87BB','\U87BC','\U87BD','\U87BE','\U87BF','\U87C0','\U87C1','\U87C2','\U87C3','\U87C4','\U87C5','\U87C6','\U87C7','\U87C8','\U87C9','\U87CA','\U87CB','\U87CC','\U87CD','\U87CE','\U87CF','\U87D0','\U87D1','\U87D2','\U87D3','\U87D4','\U87D5','\U87D6','\U87D7','\U87D8','\U87D9','\U87DA','\U87DB','\U87DC','\U87DD','\U87DE','\U87DF','\U87E0','\U87E1','\U87E2','\U87E3','\U87E4','\U87E5','\U87E6','\U87E7','\U87E8','\U87E9','\U87EA','\U87EB','\U87EC','\U87ED','\U87EE','\U87EF','\U87F0','\U87F1','\U87F2','\U87F3','\U87F4','\U87F5','\U87F6','\U87F7','\U87F8','\U87F9','\U87FA','\U87FB','\U87FC','\U87FD','\U87FE','\U87FF','\U8800','\U8801','\U8802','\U8803','\U8804','\U8805','\U8806','\U8807','\U8808','\U8809','\U880A','\U880B','\U880C','\U880D','\U880E','\U880F','\U8810','\U8811','\U8812','\U8813','\U8814','\U8815','\U8816','\U8817','\U8818','\U8819','\U881A','\U881B','\U881C','\U881D','\U881E','\U881F','\U8820','\U8821','\U8822','\U8823','\U8824','\U8825','\U8826','\U8827','\U8828','\U8829','\U882A','\U882B','\U882C','\U882D','\U882E','\U882F','\U8830','\U8831','\U8832','\U8833','\U8834','\U8835','\U8836','\U8837','\U8838','\U8839','\U883A','\U883B','\U883C','\U883D','\U883E','\U883F','\U8840','\U8841','\U8842','\U8843','\U8844','\U8845','\U8846','\U8847','\U8848','\U8849','\U884A','\U884B','\U884C','\U884D','\U884E','\U884F','\U8850','\U8851','\U8852','\U8853','\U8854','\U8855','\U8856','\U8857','\U8858','\U8859','\U885A','\U885B','\U885C','\U885D','\U885E','\U885F','\U8860','\U8861','\U8862','\U8863','\U8864','\U8865','\U8866','\U8867','\U8868','\U8869','\U886A','\U886B','\U886C','\U886D','\U886E','\U886F','\U8870','\U8871','\U8872','\U8873','\U8874','\U8875','\U8876','\U8877','\U8878','\U8879','\U887A','\U887B','\U887C','\U887D','\U887E','\U887F','\U8880','\U8881','\U8882','\U8883','\U8884','\U8885','\U8886','\U8887','\U8888','\U8889','\U888A','\U888B','\U888C','\U888D','\U888E','\U888F','\U8890','\U8891','\U8892','\U8893','\U8894','\U8895','\U8896','\U8897','\U8898','\U8899','\U889A','\U889B','\U889C','\U889D','\U889E','\U889F','\U88A0','\U88A1','\U88A2','\U88A3','\U88A4','\U88A5','\U88A6','\U88A7','\U88A8','\U88A9','\U88AA','\U88AB','\U88AC','\U88AD','\U88AE','\U88AF','\U88B0','\U88B1','\U88B2','\U88B3','\U88B4','\U88B5','\U88B6','\U88B7','\U88B8','\U88B9','\U88BA','\U88BB','\U88BC','\U88BD','\U88BE','\U88BF','\U88C0','\U88C1','\U88C2','\U88C3','\U88C4','\U88C5','\U88C6','\U88C7','\U88C8','\U88C9','\U88CA','\U88CB','\U88CC','\U88CD','\U88CE','\U88CF','\U88D0','\U88D1','\U88D2','\U88D3','\U88D4','\U88D5','\U88D6','\U88D7','\U88D8','\U88D9','\U88DA','\U88DB','\U88DC','\U88DD','\U88DE','\U88DF','\U88E0','\U88E1','\U88E2','\U88E3','\U88E4','\U88E5','\U88E6','\U88E7','\U88E8','\U88E9','\U88EA','\U88EB','\U88EC','\U88ED','\U88EE','\U88EF','\U88F0','\U88F1','\U88F2','\U88F3','\U88F4','\U88F5','\U88F6','\U88F7','\U88F8','\U88F9','\U88FA','\U88FB','\U88FC','\U88FD','\U88FE','\U88FF','\U8900','\U8901','\U8902','\U8903','\U8904','\U8905','\U8906','\U8907','\U8908','\U8909','\U890A','\U890B','\U890C','\U890D','\U890E','\U890F','\U8910','\U8911','\U8912','\U8913','\U8914','\U8915','\U8916','\U8917','\U8918','\U8919','\U891A','\U891B','\U891C','\U891D','\U891E','\U891F','\U8920','\U8921','\U8922','\U8923','\U8924','\U8925','\U8926','\U8927','\U8928','\U8929','\U892A','\U892B','\U892C','\U892D','\U892E','\U892F','\U8930','\U8931','\U8932','\U8933','\U8934','\U8935','\U8936','\U8937','\U8938','\U8939','\U893A','\U893B','\U893C','\U893D','\U893E','\U893F','\U8940','\U8941','\U8942','\U8943','\U8944','\U8945','\U8946','\U8947','\U8948','\U8949','\U894A','\U894B','\U894C','\U894D','\U894E','\U894F','\U8950','\U8951','\U8952','\U8953','\U8954','\U8955','\U8956','\U8957','\U8958','\U8959','\U895A','\U895B','\U895C','\U895D','\U895E','\U895F','\U8960','\U8961','\U8962','\U8963','\U8964','\U8965','\U8966','\U8967','\U8968','\U8969','\U896A','\U896B','\U896C','\U896D','\U896E','\U896F','\U8970','\U8971','\U8972','\U8973','\U8974','\U8975','\U8976','\U8977','\U8978','\U8979','\U897A','\U897B','\U897C','\U897D','\U897E','\U897F','\U8980','\U8981','\U8982','\U8983','\U8984','\U8985','\U8986','\U8987','\U8988','\U8989','\U898A','\U898B','\U898C','\U898D','\U898E','\U898F','\U8990','\U8991','\U8992','\U8993','\U8994','\U8995','\U8996','\U8997','\U8998','\U8999','\U899A','\U899B','\U899C','\U899D','\U899E','\U899F','\U89A0','\U89A1','\U89A2','\U89A3','\U89A4','\U89A5','\U89A6','\U89A7','\U89A8','\U89A9','\U89AA','\U89AB','\U89AC','\U89AD','\U89AE','\U89AF','\U89B0','\U89B1','\U89B2','\U89B3','\U89B4','\U89B5','\U89B6','\U89B7','\U89B8','\U89B9','\U89BA','\U89BB','\U89BC','\U89BD','\U89BE','\U89BF','\U89C0','\U89C1','\U89C2','\U89C3','\U89C4','\U89C5','\U89C6','\U89C7','\U89C8','\U89C9','\U89CA','\U89CB','\U89CC','\U89CD','\U89CE','\U89CF','\U89D0','\U89D1','\U89D2','\U89D3','\U89D4','\U89D5','\U89D6','\U89D7','\U89D8','\U89D9','\U89DA','\U89DB','\U89DC','\U89DD','\U89DE','\U89DF','\U89E0','\U89E1','\U89E2','\U89E3','\U89E4','\U89E5','\U89E6','\U89E7','\U89E8','\U89E9','\U89EA','\U89EB','\U89EC','\U89ED','\U89EE','\U89EF','\U89F0','\U89F1','\U89F2','\U89F3','\U89F4','\U89F5','\U89F6','\U89F7','\U89F8','\U89F9','\U89FA','\U89FB','\U89FC','\U89FD','\U89FE','\U89FF','\U8A00','\U8A01','\U8A02','\U8A03','\U8A04','\U8A05','\U8A06','\U8A07','\U8A08','\U8A09','\U8A0A','\U8A0B','\U8A0C','\U8A0D','\U8A0E','\U8A0F','\U8A10','\U8A11','\U8A12','\U8A13','\U8A14','\U8A15','\U8A16','\U8A17','\U8A18','\U8A19','\U8A1A','\U8A1B','\U8A1C','\U8A1D','\U8A1E','\U8A1F','\U8A20','\U8A21','\U8A22','\U8A23','\U8A24','\U8A25','\U8A26','\U8A27','\U8A28','\U8A29','\U8A2A','\U8A2B','\U8A2C','\U8A2D','\U8A2E','\U8A2F','\U8A30','\U8A31','\U8A32','\U8A33','\U8A34','\U8A35','\U8A36','\U8A37','\U8A38','\U8A39','\U8A3A','\U8A3B','\U8A3C','\U8A3D','\U8A3E','\U8A3F','\U8A40','\U8A41','\U8A42','\U8A43','\U8A44','\U8A45','\U8A46','\U8A47','\U8A48','\U8A49','\U8A4A','\U8A4B','\U8A4C','\U8A4D','\U8A4E','\U8A4F','\U8A50','\U8A51','\U8A52','\U8A53','\U8A54','\U8A55','\U8A56','\U8A57','\U8A58','\U8A59','\U8A5A','\U8A5B','\U8A5C','\U8A5D','\U8A5E','\U8A5F','\U8A60','\U8A61','\U8A62','\U8A63','\U8A64','\U8A65','\U8A66','\U8A67','\U8A68','\U8A69','\U8A6A','\U8A6B','\U8A6C','\U8A6D','\U8A6E','\U8A6F','\U8A70','\U8A71','\U8A72','\U8A73','\U8A74','\U8A75','\U8A76','\U8A77','\U8A78','\U8A79','\U8A7A','\U8A7B','\U8A7C','\U8A7D','\U8A7E','\U8A7F','\U8A80','\U8A81','\U8A82','\U8A83','\U8A84','\U8A85','\U8A86','\U8A87','\U8A88','\U8A89','\U8A8A','\U8A8B','\U8A8C','\U8A8D','\U8A8E','\U8A8F','\U8A90','\U8A91','\U8A92','\U8A93','\U8A94','\U8A95','\U8A96','\U8A97','\U8A98','\U8A99','\U8A9A','\U8A9B','\U8A9C','\U8A9D','\U8A9E','\U8A9F','\U8AA0','\U8AA1','\U8AA2','\U8AA3','\U8AA4','\U8AA5','\U8AA6','\U8AA7','\U8AA8','\U8AA9','\U8AAA','\U8AAB','\U8AAC','\U8AAD','\U8AAE','\U8AAF','\U8AB0','\U8AB1','\U8AB2','\U8AB3','\U8AB4','\U8AB5','\U8AB6','\U8AB7','\U8AB8','\U8AB9','\U8ABA','\U8ABB','\U8ABC','\U8ABD','\U8ABE','\U8ABF','\U8AC0','\U8AC1','\U8AC2','\U8AC3','\U8AC4','\U8AC5','\U8AC6','\U8AC7','\U8AC8','\U8AC9','\U8ACA','\U8ACB','\U8ACC','\U8ACD','\U8ACE','\U8ACF','\U8AD0','\U8AD1','\U8AD2','\U8AD3','\U8AD4','\U8AD5','\U8AD6','\U8AD7','\U8AD8','\U8AD9','\U8ADA','\U8ADB','\U8ADC','\U8ADD','\U8ADE','\U8ADF','\U8AE0','\U8AE1','\U8AE2','\U8AE3','\U8AE4','\U8AE5','\U8AE6','\U8AE7','\U8AE8','\U8AE9','\U8AEA','\U8AEB','\U8AEC','\U8AED','\U8AEE','\U8AEF','\U8AF0','\U8AF1','\U8AF2','\U8AF3','\U8AF4','\U8AF5','\U8AF6','\U8AF7','\U8AF8','\U8AF9','\U8AFA','\U8AFB','\U8AFC','\U8AFD','\U8AFE','\U8AFF','\U8B00','\U8B01','\U8B02','\U8B03','\U8B04','\U8B05','\U8B06','\U8B07','\U8B08','\U8B09','\U8B0A','\U8B0B','\U8B0C','\U8B0D','\U8B0E','\U8B0F','\U8B10','\U8B11','\U8B12','\U8B13','\U8B14','\U8B15','\U8B16','\U8B17','\U8B18','\U8B19','\U8B1A','\U8B1B','\U8B1C','\U8B1D','\U8B1E','\U8B1F','\U8B20','\U8B21','\U8B22','\U8B23','\U8B24','\U8B25','\U8B26','\U8B27','\U8B28','\U8B29','\U8B2A','\U8B2B','\U8B2C','\U8B2D','\U8B2E','\U8B2F','\U8B30','\U8B31','\U8B32','\U8B33','\U8B34','\U8B35','\U8B36','\U8B37','\U8B38','\U8B39','\U8B3A','\U8B3B','\U8B3C','\U8B3D','\U8B3E','\U8B3F','\U8B40','\U8B41','\U8B42','\U8B43','\U8B44','\U8B45','\U8B46','\U8B47','\U8B48','\U8B49','\U8B4A','\U8B4B','\U8B4C','\U8B4D','\U8B4E','\U8B4F','\U8B50','\U8B51','\U8B52','\U8B53','\U8B54','\U8B55','\U8B56','\U8B57','\U8B58','\U8B59','\U8B5A','\U8B5B','\U8B5C','\U8B5D','\U8B5E','\U8B5F','\U8B60','\U8B61','\U8B62','\U8B63','\U8B64','\U8B65','\U8B66','\U8B67','\U8B68','\U8B69','\U8B6A','\U8B6B','\U8B6C','\U8B6D','\U8B6E','\U8B6F','\U8B70','\U8B71','\U8B72','\U8B73','\U8B74','\U8B75','\U8B76','\U8B77','\U8B78','\U8B79','\U8B7A','\U8B7B','\U8B7C','\U8B7D','\U8B7E','\U8B7F','\U8B80','\U8B81','\U8B82','\U8B83','\U8B84','\U8B85','\U8B86','\U8B87','\U8B88','\U8B89','\U8B8A','\U8B8B','\U8B8C','\U8B8D','\U8B8E','\U8B8F','\U8B90','\U8B91','\U8B92','\U8B93','\U8B94','\U8B95','\U8B96','\U8B97','\U8B98','\U8B99','\U8B9A','\U8B9B','\U8B9C','\U8B9D','\U8B9E','\U8B9F','\U8BA0','\U8BA1','\U8BA2','\U8BA3','\U8BA4','\U8BA5','\U8BA6','\U8BA7','\U8BA8','\U8BA9','\U8BAA','\U8BAB','\U8BAC','\U8BAD','\U8BAE','\U8BAF','\U8BB0','\U8BB1','\U8BB2','\U8BB3','\U8BB4','\U8BB5','\U8BB6','\U8BB7','\U8BB8','\U8BB9','\U8BBA','\U8BBB','\U8BBC','\U8BBD','\U8BBE','\U8BBF','\U8BC0','\U8BC1','\U8BC2','\U8BC3','\U8BC4','\U8BC5','\U8BC6','\U8BC7','\U8BC8','\U8BC9','\U8BCA','\U8BCB','\U8BCC','\U8BCD','\U8BCE','\U8BCF','\U8BD0','\U8BD1','\U8BD2','\U8BD3','\U8BD4','\U8BD5','\U8BD6','\U8BD7','\U8BD8','\U8BD9','\U8BDA','\U8BDB','\U8BDC','\U8BDD','\U8BDE','\U8BDF','\U8BE0','\U8BE1','\U8BE2','\U8BE3','\U8BE4','\U8BE5','\U8BE6','\U8BE7','\U8BE8','\U8BE9','\U8BEA','\U8BEB','\U8BEC','\U8BED','\U8BEE','\U8BEF','\U8BF0','\U8BF1','\U8BF2','\U8BF3','\U8BF4','\U8BF5','\U8BF6','\U8BF7','\U8BF8','\U8BF9','\U8BFA','\U8BFB','\U8BFC','\U8BFD','\U8BFE','\U8BFF','\U8C00','\U8C01','\U8C02','\U8C03','\U8C04','\U8C05','\U8C06','\U8C07','\U8C08','\U8C09','\U8C0A','\U8C0B','\U8C0C','\U8C0D','\U8C0E','\U8C0F','\U8C10','\U8C11','\U8C12','\U8C13','\U8C14','\U8C15','\U8C16','\U8C17','\U8C18','\U8C19','\U8C1A','\U8C1B','\U8C1C','\U8C1D','\U8C1E','\U8C1F','\U8C20','\U8C21','\U8C22','\U8C23','\U8C24','\U8C25','\U8C26','\U8C27','\U8C28','\U8C29','\U8C2A','\U8C2B','\U8C2C','\U8C2D','\U8C2E','\U8C2F','\U8C30','\U8C31','\U8C32','\U8C33','\U8C34','\U8C35','\U8C36','\U8C37','\U8C38','\U8C39','\U8C3A','\U8C3B','\U8C3C','\U8C3D','\U8C3E','\U8C3F','\U8C40','\U8C41','\U8C42','\U8C43','\U8C44','\U8C45','\U8C46','\U8C47','\U8C48','\U8C49','\U8C4A','\U8C4B','\U8C4C','\U8C4D','\U8C4E','\U8C4F','\U8C50','\U8C51','\U8C52','\U8C53','\U8C54','\U8C55','\U8C56','\U8C57','\U8C58','\U8C59','\U8C5A','\U8C5B','\U8C5C','\U8C5D','\U8C5E','\U8C5F','\U8C60','\U8C61','\U8C62','\U8C63','\U8C64','\U8C65','\U8C66','\U8C67','\U8C68','\U8C69','\U8C6A','\U8C6B','\U8C6C','\U8C6D','\U8C6E','\U8C6F','\U8C70','\U8C71','\U8C72','\U8C73','\U8C74','\U8C75','\U8C76','\U8C77','\U8C78','\U8C79','\U8C7A','\U8C7B','\U8C7C','\U8C7D','\U8C7E','\U8C7F','\U8C80','\U8C81','\U8C82','\U8C83','\U8C84','\U8C85','\U8C86','\U8C87','\U8C88','\U8C89','\U8C8A','\U8C8B','\U8C8C','\U8C8D','\U8C8E','\U8C8F','\U8C90','\U8C91','\U8C92','\U8C93','\U8C94','\U8C95','\U8C96','\U8C97','\U8C98','\U8C99','\U8C9A','\U8C9B','\U8C9C','\U8C9D','\U8C9E','\U8C9F','\U8CA0','\U8CA1','\U8CA2','\U8CA3','\U8CA4','\U8CA5','\U8CA6','\U8CA7','\U8CA8','\U8CA9','\U8CAA','\U8CAB','\U8CAC','\U8CAD','\U8CAE','\U8CAF','\U8CB0','\U8CB1','\U8CB2','\U8CB3','\U8CB4','\U8CB5','\U8CB6','\U8CB7','\U8CB8','\U8CB9','\U8CBA','\U8CBB','\U8CBC','\U8CBD','\U8CBE','\U8CBF','\U8CC0','\U8CC1','\U8CC2','\U8CC3','\U8CC4','\U8CC5','\U8CC6','\U8CC7','\U8CC8','\U8CC9','\U8CCA','\U8CCB','\U8CCC','\U8CCD','\U8CCE','\U8CCF','\U8CD0','\U8CD1','\U8CD2','\U8CD3','\U8CD4','\U8CD5','\U8CD6','\U8CD7','\U8CD8','\U8CD9','\U8CDA','\U8CDB','\U8CDC','\U8CDD','\U8CDE','\U8CDF','\U8CE0','\U8CE1','\U8CE2','\U8CE3','\U8CE4','\U8CE5','\U8CE6','\U8CE7','\U8CE8','\U8CE9','\U8CEA','\U8CEB','\U8CEC','\U8CED','\U8CEE','\U8CEF','\U8CF0','\U8CF1','\U8CF2','\U8CF3','\U8CF4','\U8CF5','\U8CF6','\U8CF7','\U8CF8','\U8CF9','\U8CFA','\U8CFB','\U8CFC','\U8CFD','\U8CFE','\U8CFF','\U8D00','\U8D01','\U8D02','\U8D03','\U8D04','\U8D05','\U8D06','\U8D07','\U8D08','\U8D09','\U8D0A','\U8D0B','\U8D0C','\U8D0D','\U8D0E','\U8D0F','\U8D10','\U8D11','\U8D12','\U8D13','\U8D14','\U8D15','\U8D16','\U8D17','\U8D18','\U8D19','\U8D1A','\U8D1B','\U8D1C','\U8D1D','\U8D1E','\U8D1F','\U8D20','\U8D21','\U8D22','\U8D23','\U8D24','\U8D25','\U8D26','\U8D27','\U8D28','\U8D29','\U8D2A','\U8D2B','\U8D2C','\U8D2D','\U8D2E','\U8D2F','\U8D30','\U8D31','\U8D32','\U8D33','\U8D34','\U8D35','\U8D36','\U8D37','\U8D38','\U8D39','\U8D3A','\U8D3B','\U8D3C','\U8D3D','\U8D3E','\U8D3F','\U8D40','\U8D41','\U8D42','\U8D43','\U8D44','\U8D45','\U8D46','\U8D47','\U8D48','\U8D49','\U8D4A','\U8D4B','\U8D4C','\U8D4D','\U8D4E','\U8D4F','\U8D50','\U8D51','\U8D52','\U8D53','\U8D54','\U8D55','\U8D56','\U8D57','\U8D58','\U8D59','\U8D5A','\U8D5B','\U8D5C','\U8D5D','\U8D5E','\U8D5F','\U8D60','\U8D61','\U8D62','\U8D63','\U8D64','\U8D65','\U8D66','\U8D67','\U8D68','\U8D69','\U8D6A','\U8D6B','\U8D6C','\U8D6D','\U8D6E','\U8D6F','\U8D70','\U8D71','\U8D72','\U8D73','\U8D74','\U8D75','\U8D76','\U8D77','\U8D78','\U8D79','\U8D7A','\U8D7B','\U8D7C','\U8D7D','\U8D7E','\U8D7F','\U8D80','\U8D81','\U8D82','\U8D83','\U8D84','\U8D85','\U8D86','\U8D87','\U8D88','\U8D89','\U8D8A','\U8D8B','\U8D8C','\U8D8D','\U8D8E','\U8D8F','\U8D90','\U8D91','\U8D92','\U8D93','\U8D94','\U8D95','\U8D96','\U8D97','\U8D98','\U8D99','\U8D9A','\U8D9B','\U8D9C','\U8D9D','\U8D9E','\U8D9F','\U8DA0','\U8DA1','\U8DA2','\U8DA3','\U8DA4','\U8DA5','\U8DA6','\U8DA7','\U8DA8','\U8DA9','\U8DAA','\U8DAB','\U8DAC','\U8DAD','\U8DAE','\U8DAF','\U8DB0','\U8DB1','\U8DB2','\U8DB3','\U8DB4','\U8DB5','\U8DB6','\U8DB7','\U8DB8','\U8DB9','\U8DBA','\U8DBB','\U8DBC','\U8DBD','\U8DBE','\U8DBF','\U8DC0','\U8DC1','\U8DC2','\U8DC3','\U8DC4','\U8DC5','\U8DC6','\U8DC7','\U8DC8','\U8DC9','\U8DCA','\U8DCB','\U8DCC','\U8DCD','\U8DCE','\U8DCF','\U8DD0','\U8DD1','\U8DD2','\U8DD3','\U8DD4','\U8DD5','\U8DD6','\U8DD7','\U8DD8','\U8DD9','\U8DDA','\U8DDB','\U8DDC','\U8DDD','\U8DDE','\U8DDF','\U8DE0','\U8DE1','\U8DE2','\U8DE3','\U8DE4','\U8DE5','\U8DE6','\U8DE7','\U8DE8','\U8DE9','\U8DEA','\U8DEB','\U8DEC','\U8DED','\U8DEE','\U8DEF','\U8DF0','\U8DF1','\U8DF2','\U8DF3','\U8DF4','\U8DF5','\U8DF6','\U8DF7','\U8DF8','\U8DF9','\U8DFA','\U8DFB','\U8DFC','\U8DFD','\U8DFE','\U8DFF','\U8E00','\U8E01','\U8E02','\U8E03','\U8E04','\U8E05','\U8E06','\U8E07','\U8E08','\U8E09','\U8E0A','\U8E0B','\U8E0C','\U8E0D','\U8E0E','\U8E0F','\U8E10','\U8E11','\U8E12','\U8E13','\U8E14','\U8E15','\U8E16','\U8E17','\U8E18','\U8E19','\U8E1A','\U8E1B','\U8E1C','\U8E1D','\U8E1E','\U8E1F','\U8E20','\U8E21','\U8E22','\U8E23','\U8E24','\U8E25','\U8E26','\U8E27','\U8E28','\U8E29','\U8E2A','\U8E2B','\U8E2C','\U8E2D','\U8E2E','\U8E2F','\U8E30','\U8E31','\U8E32','\U8E33','\U8E34','\U8E35','\U8E36','\U8E37','\U8E38','\U8E39','\U8E3A','\U8E3B','\U8E3C','\U8E3D','\U8E3E','\U8E3F','\U8E40','\U8E41','\U8E42','\U8E43','\U8E44','\U8E45','\U8E46','\U8E47','\U8E48','\U8E49','\U8E4A','\U8E4B','\U8E4C','\U8E4D','\U8E4E','\U8E4F','\U8E50','\U8E51','\U8E52','\U8E53','\U8E54','\U8E55','\U8E56','\U8E57','\U8E58','\U8E59','\U8E5A','\U8E5B','\U8E5C','\U8E5D','\U8E5E','\U8E5F','\U8E60','\U8E61','\U8E62','\U8E63','\U8E64','\U8E65','\U8E66','\U8E67','\U8E68','\U8E69','\U8E6A','\U8E6B','\U8E6C','\U8E6D','\U8E6E','\U8E6F','\U8E70','\U8E71','\U8E72','\U8E73','\U8E74','\U8E75','\U8E76','\U8E77','\U8E78','\U8E79','\U8E7A','\U8E7B','\U8E7C','\U8E7D','\U8E7E','\U8E7F','\U8E80','\U8E81','\U8E82','\U8E83','\U8E84','\U8E85','\U8E86','\U8E87','\U8E88','\U8E89','\U8E8A','\U8E8B','\U8E8C','\U8E8D','\U8E8E','\U8E8F','\U8E90','\U8E91','\U8E92','\U8E93','\U8E94','\U8E95','\U8E96','\U8E97','\U8E98','\U8E99','\U8E9A','\U8E9B','\U8E9C','\U8E9D','\U8E9E','\U8E9F','\U8EA0','\U8EA1','\U8EA2','\U8EA3','\U8EA4','\U8EA5','\U8EA6','\U8EA7','\U8EA8','\U8EA9','\U8EAA','\U8EAB','\U8EAC','\U8EAD','\U8EAE','\U8EAF','\U8EB0','\U8EB1','\U8EB2','\U8EB3','\U8EB4','\U8EB5','\U8EB6','\U8EB7','\U8EB8','\U8EB9','\U8EBA','\U8EBB','\U8EBC','\U8EBD','\U8EBE','\U8EBF','\U8EC0','\U8EC1','\U8EC2','\U8EC3','\U8EC4','\U8EC5','\U8EC6','\U8EC7','\U8EC8','\U8EC9','\U8ECA','\U8ECB','\U8ECC','\U8ECD','\U8ECE','\U8ECF','\U8ED0','\U8ED1','\U8ED2','\U8ED3','\U8ED4','\U8ED5','\U8ED6','\U8ED7','\U8ED8','\U8ED9','\U8EDA','\U8EDB','\U8EDC','\U8EDD','\U8EDE','\U8EDF','\U8EE0','\U8EE1','\U8EE2','\U8EE3','\U8EE4','\U8EE5','\U8EE6','\U8EE7','\U8EE8','\U8EE9','\U8EEA','\U8EEB','\U8EEC','\U8EED','\U8EEE','\U8EEF','\U8EF0','\U8EF1','\U8EF2','\U8EF3','\U8EF4','\U8EF5','\U8EF6','\U8EF7','\U8EF8','\U8EF9','\U8EFA','\U8EFB','\U8EFC','\U8EFD','\U8EFE','\U8EFF','\U8F00','\U8F01','\U8F02','\U8F03','\U8F04','\U8F05','\U8F06','\U8F07','\U8F08','\U8F09','\U8F0A','\U8F0B','\U8F0C','\U8F0D','\U8F0E','\U8F0F','\U8F10','\U8F11','\U8F12','\U8F13','\U8F14','\U8F15','\U8F16','\U8F17','\U8F18','\U8F19','\U8F1A','\U8F1B','\U8F1C','\U8F1D','\U8F1E','\U8F1F','\U8F20','\U8F21','\U8F22','\U8F23','\U8F24','\U8F25','\U8F26','\U8F27','\U8F28','\U8F29','\U8F2A','\U8F2B','\U8F2C','\U8F2D','\U8F2E','\U8F2F','\U8F30','\U8F31','\U8F32','\U8F33','\U8F34','\U8F35','\U8F36','\U8F37','\U8F38','\U8F39','\U8F3A','\U8F3B','\U8F3C','\U8F3D','\U8F3E','\U8F3F','\U8F40','\U8F41','\U8F42','\U8F43','\U8F44','\U8F45','\U8F46','\U8F47','\U8F48','\U8F49','\U8F4A','\U8F4B','\U8F4C','\U8F4D','\U8F4E','\U8F4F','\U8F50','\U8F51','\U8F52','\U8F53','\U8F54','\U8F55','\U8F56','\U8F57','\U8F58','\U8F59','\U8F5A','\U8F5B','\U8F5C','\U8F5D','\U8F5E','\U8F5F','\U8F60','\U8F61','\U8F62','\U8F63','\U8F64','\U8F65','\U8F66','\U8F67','\U8F68','\U8F69','\U8F6A','\U8F6B','\U8F6C','\U8F6D','\U8F6E','\U8F6F','\U8F70','\U8F71','\U8F72','\U8F73','\U8F74','\U8F75','\U8F76','\U8F77','\U8F78','\U8F79','\U8F7A','\U8F7B','\U8F7C','\U8F7D','\U8F7E','\U8F7F','\U8F80','\U8F81','\U8F82','\U8F83','\U8F84','\U8F85','\U8F86','\U8F87','\U8F88','\U8F89','\U8F8A','\U8F8B','\U8F8C','\U8F8D','\U8F8E','\U8F8F','\U8F90','\U8F91','\U8F92','\U8F93','\U8F94','\U8F95','\U8F96','\U8F97','\U8F98','\U8F99','\U8F9A','\U8F9B','\U8F9C','\U8F9D','\U8F9E','\U8F9F','\U8FA0','\U8FA1','\U8FA2','\U8FA3','\U8FA4','\U8FA5','\U8FA6','\U8FA7','\U8FA8','\U8FA9','\U8FAA','\U8FAB','\U8FAC','\U8FAD','\U8FAE','\U8FAF','\U8FB0','\U8FB1','\U8FB2','\U8FB3','\U8FB4','\U8FB5','\U8FB6','\U8FB7','\U8FB8','\U8FB9','\U8FBA','\U8FBB','\U8FBC','\U8FBD','\U8FBE','\U8FBF','\U8FC0','\U8FC1','\U8FC2','\U8FC3','\U8FC4','\U8FC5','\U8FC6','\U8FC7','\U8FC8','\U8FC9','\U8FCA','\U8FCB','\U8FCC','\U8FCD','\U8FCE','\U8FCF','\U8FD0','\U8FD1','\U8FD2','\U8FD3','\U8FD4','\U8FD5','\U8FD6','\U8FD7','\U8FD8','\U8FD9','\U8FDA','\U8FDB','\U8FDC','\U8FDD','\U8FDE','\U8FDF','\U8FE0','\U8FE1','\U8FE2','\U8FE3','\U8FE4','\U8FE5','\U8FE6','\U8FE7','\U8FE8','\U8FE9','\U8FEA','\U8FEB','\U8FEC','\U8FED','\U8FEE','\U8FEF','\U8FF0','\U8FF1','\U8FF2','\U8FF3','\U8FF4','\U8FF5','\U8FF6','\U8FF7','\U8FF8','\U8FF9','\U8FFA','\U8FFB','\U8FFC','\U8FFD','\U8FFE','\U8FFF','\U9000','\U9001','\U9002','\U9003','\U9004','\U9005','\U9006','\U9007','\U9008','\U9009','\U900A','\U900B','\U900C','\U900D','\U900E','\U900F','\U9010','\U9011','\U9012','\U9013','\U9014','\U9015','\U9016','\U9017','\U9018','\U9019','\U901A','\U901B','\U901C','\U901D','\U901E','\U901F','\U9020','\U9021','\U9022','\U9023','\U9024','\U9025','\U9026','\U9027','\U9028','\U9029','\U902A','\U902B','\U902C','\U902D','\U902E','\U902F','\U9030','\U9031','\U9032','\U9033','\U9034','\U9035','\U9036','\U9037','\U9038','\U9039','\U903A','\U903B','\U903C','\U903D','\U903E','\U903F','\U9040','\U9041','\U9042','\U9043','\U9044','\U9045','\U9046','\U9047','\U9048','\U9049','\U904A','\U904B','\U904C','\U904D','\U904E','\U904F','\U9050','\U9051','\U9052','\U9053','\U9054','\U9055','\U9056','\U9057','\U9058','\U9059','\U905A','\U905B','\U905C','\U905D','\U905E','\U905F','\U9060','\U9061','\U9062','\U9063','\U9064','\U9065','\U9066','\U9067','\U9068','\U9069','\U906A','\U906B','\U906C','\U906D','\U906E','\U906F','\U9070','\U9071','\U9072','\U9073','\U9074','\U9075','\U9076','\U9077','\U9078','\U9079','\U907A','\U907B','\U907C','\U907D','\U907E','\U907F','\U9080','\U9081','\U9082','\U9083','\U9084','\U9085','\U9086','\U9087','\U9088','\U9089','\U908A','\U908B','\U908C','\U908D','\U908E','\U908F','\U9090','\U9091','\U9092','\U9093','\U9094','\U9095','\U9096','\U9097','\U9098','\U9099','\U909A','\U909B','\U909C','\U909D','\U909E','\U909F','\U90A0','\U90A1','\U90A2','\U90A3','\U90A4','\U90A5','\U90A6','\U90A7','\U90A8','\U90A9','\U90AA','\U90AB','\U90AC','\U90AD','\U90AE','\U90AF','\U90B0','\U90B1','\U90B2','\U90B3','\U90B4','\U90B5','\U90B6','\U90B7','\U90B8','\U90B9','\U90BA','\U90BB','\U90BC','\U90BD','\U90BE','\U90BF','\U90C0','\U90C1','\U90C2','\U90C3','\U90C4','\U90C5','\U90C6','\U90C7','\U90C8','\U90C9','\U90CA','\U90CB','\U90CC','\U90CD','\U90CE','\U90CF','\U90D0','\U90D1','\U90D2','\U90D3','\U90D4','\U90D5','\U90D6','\U90D7','\U90D8','\U90D9','\U90DA','\U90DB','\U90DC','\U90DD','\U90DE','\U90DF','\U90E0','\U90E1','\U90E2','\U90E3','\U90E4','\U90E5','\U90E6','\U90E7','\U90E8','\U90E9','\U90EA','\U90EB','\U90EC','\U90ED','\U90EE','\U90EF','\U90F0','\U90F1','\U90F2','\U90F3','\U90F4','\U90F5','\U90F6','\U90F7','\U90F8','\U90F9','\U90FA','\U90FB','\U90FC','\U90FD','\U90FE','\U90FF','\U9100','\U9101','\U9102','\U9103','\U9104','\U9105','\U9106','\U9107','\U9108','\U9109','\U910A','\U910B','\U910C','\U910D','\U910E','\U910F','\U9110','\U9111','\U9112','\U9113','\U9114','\U9115','\U9116','\U9117','\U9118','\U9119','\U911A','\U911B','\U911C','\U911D','\U911E','\U911F','\U9120','\U9121','\U9122','\U9123','\U9124','\U9125','\U9126','\U9127','\U9128','\U9129','\U912A','\U912B','\U912C','\U912D','\U912E','\U912F','\U9130','\U9131','\U9132','\U9133','\U9134','\U9135','\U9136','\U9137','\U9138','\U9139','\U913A','\U913B','\U913C','\U913D','\U913E','\U913F','\U9140','\U9141','\U9142','\U9143','\U9144','\U9145','\U9146','\U9147','\U9148','\U9149','\U914A','\U914B','\U914C','\U914D','\U914E','\U914F','\U9150','\U9151','\U9152','\U9153','\U9154','\U9155','\U9156','\U9157','\U9158','\U9159','\U915A','\U915B','\U915C','\U915D','\U915E','\U915F','\U9160','\U9161','\U9162','\U9163','\U9164','\U9165','\U9166','\U9167','\U9168','\U9169','\U916A','\U916B','\U916C','\U916D','\U916E','\U916F','\U9170','\U9171','\U9172','\U9173','\U9174','\U9175','\U9176','\U9177','\U9178','\U9179','\U917A','\U917B','\U917C','\U917D','\U917E','\U917F','\U9180','\U9181','\U9182','\U9183','\U9184','\U9185','\U9186','\U9187','\U9188','\U9189','\U918A','\U918B','\U918C','\U918D','\U918E','\U918F','\U9190','\U9191','\U9192','\U9193','\U9194','\U9195','\U9196','\U9197','\U9198','\U9199','\U919A','\U919B','\U919C','\U919D','\U919E','\U919F','\U91A0','\U91A1','\U91A2','\U91A3','\U91A4','\U91A5','\U91A6','\U91A7','\U91A8','\U91A9','\U91AA','\U91AB','\U91AC','\U91AD','\U91AE','\U91AF','\U91B0','\U91B1','\U91B2','\U91B3','\U91B4','\U91B5','\U91B6','\U91B7','\U91B8','\U91B9','\U91BA','\U91BB','\U91BC','\U91BD','\U91BE','\U91BF','\U91C0','\U91C1','\U91C2','\U91C3','\U91C4','\U91C5','\U91C6','\U91C7','\U91C8','\U91C9','\U91CA','\U91CB','\U91CC','\U91CD','\U91CE','\U91CF','\U91D0','\U91D1','\U91D2','\U91D3','\U91D4','\U91D5','\U91D6','\U91D7','\U91D8','\U91D9','\U91DA','\U91DB','\U91DC','\U91DD','\U91DE','\U91DF','\U91E0','\U91E1','\U91E2','\U91E3','\U91E4','\U91E5','\U91E6','\U91E7','\U91E8','\U91E9','\U91EA','\U91EB','\U91EC','\U91ED','\U91EE','\U91EF','\U91F0','\U91F1','\U91F2','\U91F3','\U91F4','\U91F5','\U91F6','\U91F7','\U91F8','\U91F9','\U91FA','\U91FB','\U91FC','\U91FD','\U91FE','\U91FF','\U9200','\U9201','\U9202','\U9203','\U9204','\U9205','\U9206','\U9207','\U9208','\U9209','\U920A','\U920B','\U920C','\U920D','\U920E','\U920F','\U9210','\U9211','\U9212','\U9213','\U9214','\U9215','\U9216','\U9217','\U9218','\U9219','\U921A','\U921B','\U921C','\U921D','\U921E','\U921F','\U9220','\U9221','\U9222','\U9223','\U9224','\U9225','\U9226','\U9227','\U9228','\U9229','\U922A','\U922B','\U922C','\U922D','\U922E','\U922F','\U9230','\U9231','\U9232','\U9233','\U9234','\U9235','\U9236','\U9237','\U9238','\U9239','\U923A','\U923B','\U923C','\U923D','\U923E','\U923F','\U9240','\U9241','\U9242','\U9243','\U9244','\U9245','\U9246','\U9247','\U9248','\U9249','\U924A','\U924B','\U924C','\U924D','\U924E','\U924F','\U9250','\U9251','\U9252','\U9253','\U9254','\U9255','\U9256','\U9257','\U9258','\U9259','\U925A','\U925B','\U925C','\U925D','\U925E','\U925F','\U9260','\U9261','\U9262','\U9263','\U9264','\U9265','\U9266','\U9267','\U9268','\U9269','\U926A','\U926B','\U926C','\U926D','\U926E','\U926F','\U9270','\U9271','\U9272','\U9273','\U9274','\U9275','\U9276','\U9277','\U9278','\U9279','\U927A','\U927B','\U927C','\U927D','\U927E','\U927F','\U9280','\U9281','\U9282','\U9283','\U9284','\U9285','\U9286','\U9287','\U9288','\U9289','\U928A','\U928B','\U928C','\U928D','\U928E','\U928F','\U9290','\U9291','\U9292','\U9293','\U9294','\U9295','\U9296','\U9297','\U9298','\U9299','\U929A','\U929B','\U929C','\U929D','\U929E','\U929F','\U92A0','\U92A1','\U92A2','\U92A3','\U92A4','\U92A5','\U92A6','\U92A7','\U92A8','\U92A9','\U92AA','\U92AB','\U92AC','\U92AD','\U92AE','\U92AF','\U92B0','\U92B1','\U92B2','\U92B3','\U92B4','\U92B5','\U92B6','\U92B7','\U92B8','\U92B9','\U92BA','\U92BB','\U92BC','\U92BD','\U92BE','\U92BF','\U92C0','\U92C1','\U92C2','\U92C3','\U92C4','\U92C5','\U92C6','\U92C7','\U92C8','\U92C9','\U92CA','\U92CB','\U92CC','\U92CD','\U92CE','\U92CF','\U92D0','\U92D1','\U92D2','\U92D3','\U92D4','\U92D5','\U92D6','\U92D7','\U92D8','\U92D9','\U92DA','\U92DB','\U92DC','\U92DD','\U92DE','\U92DF','\U92E0','\U92E1','\U92E2','\U92E3','\U92E4','\U92E5','\U92E6','\U92E7','\U92E8','\U92E9','\U92EA','\U92EB','\U92EC','\U92ED','\U92EE','\U92EF','\U92F0','\U92F1','\U92F2','\U92F3','\U92F4','\U92F5','\U92F6','\U92F7','\U92F8','\U92F9','\U92FA','\U92FB','\U92FC','\U92FD','\U92FE','\U92FF','\U9300','\U9301','\U9302','\U9303','\U9304','\U9305','\U9306','\U9307','\U9308','\U9309','\U930A','\U930B','\U930C','\U930D','\U930E','\U930F','\U9310','\U9311','\U9312','\U9313','\U9314','\U9315','\U9316','\U9317','\U9318','\U9319','\U931A','\U931B','\U931C','\U931D','\U931E','\U931F','\U9320','\U9321','\U9322','\U9323','\U9324','\U9325','\U9326','\U9327','\U9328','\U9329','\U932A','\U932B','\U932C','\U932D','\U932E','\U932F','\U9330','\U9331','\U9332','\U9333','\U9334','\U9335','\U9336','\U9337','\U9338','\U9339','\U933A','\U933B','\U933C','\U933D','\U933E','\U933F','\U9340','\U9341','\U9342','\U9343','\U9344','\U9345','\U9346','\U9347','\U9348','\U9349','\U934A','\U934B','\U934C','\U934D','\U934E','\U934F','\U9350','\U9351','\U9352','\U9353','\U9354','\U9355','\U9356','\U9357','\U9358','\U9359','\U935A','\U935B','\U935C','\U935D','\U935E','\U935F','\U9360','\U9361','\U9362','\U9363','\U9364','\U9365','\U9366','\U9367','\U9368','\U9369','\U936A','\U936B','\U936C','\U936D','\U936E','\U936F','\U9370','\U9371','\U9372','\U9373','\U9374','\U9375','\U9376','\U9377','\U9378','\U9379','\U937A','\U937B','\U937C','\U937D','\U937E','\U937F','\U9380','\U9381','\U9382','\U9383','\U9384','\U9385','\U9386','\U9387','\U9388','\U9389','\U938A','\U938B','\U938C','\U938D','\U938E','\U938F','\U9390','\U9391','\U9392','\U9393','\U9394','\U9395','\U9396','\U9397','\U9398','\U9399','\U939A','\U939B','\U939C','\U939D','\U939E','\U939F','\U93A0','\U93A1','\U93A2','\U93A3','\U93A4','\U93A5','\U93A6','\U93A7','\U93A8','\U93A9','\U93AA','\U93AB','\U93AC','\U93AD','\U93AE','\U93AF','\U93B0','\U93B1','\U93B2','\U93B3','\U93B4','\U93B5','\U93B6','\U93B7','\U93B8','\U93B9','\U93BA','\U93BB','\U93BC','\U93BD','\U93BE','\U93BF','\U93C0','\U93C1','\U93C2','\U93C3','\U93C4','\U93C5','\U93C6','\U93C7','\U93C8','\U93C9','\U93CA','\U93CB','\U93CC','\U93CD','\U93CE','\U93CF','\U93D0','\U93D1','\U93D2','\U93D3','\U93D4','\U93D5','\U93D6','\U93D7','\U93D8','\U93D9','\U93DA','\U93DB','\U93DC','\U93DD','\U93DE','\U93DF','\U93E0','\U93E1','\U93E2','\U93E3','\U93E4','\U93E5','\U93E6','\U93E7','\U93E8','\U93E9','\U93EA','\U93EB','\U93EC','\U93ED','\U93EE','\U93EF','\U93F0','\U93F1','\U93F2','\U93F3','\U93F4','\U93F5','\U93F6','\U93F7','\U93F8','\U93F9','\U93FA','\U93FB','\U93FC','\U93FD','\U93FE','\U93FF','\U9400','\U9401','\U9402','\U9403','\U9404','\U9405','\U9406','\U9407','\U9408','\U9409','\U940A','\U940B','\U940C','\U940D','\U940E','\U940F','\U9410','\U9411','\U9412','\U9413','\U9414','\U9415','\U9416','\U9417','\U9418','\U9419','\U941A','\U941B','\U941C','\U941D','\U941E','\U941F','\U9420','\U9421','\U9422','\U9423','\U9424','\U9425','\U9426','\U9427','\U9428','\U9429','\U942A','\U942B','\U942C','\U942D','\U942E','\U942F','\U9430','\U9431','\U9432','\U9433','\U9434','\U9435','\U9436','\U9437','\U9438','\U9439','\U943A','\U943B','\U943C','\U943D','\U943E','\U943F','\U9440','\U9441','\U9442','\U9443','\U9444','\U9445','\U9446','\U9447','\U9448','\U9449','\U944A','\U944B','\U944C','\U944D','\U944E','\U944F','\U9450','\U9451','\U9452','\U9453','\U9454','\U9455','\U9456','\U9457','\U9458','\U9459','\U945A','\U945B','\U945C','\U945D','\U945E','\U945F','\U9460','\U9461','\U9462','\U9463','\U9464','\U9465','\U9466','\U9467','\U9468','\U9469','\U946A','\U946B','\U946C','\U946D','\U946E','\U946F','\U9470','\U9471','\U9472','\U9473','\U9474','\U9475','\U9476','\U9477','\U9478','\U9479','\U947A','\U947B','\U947C','\U947D','\U947E','\U947F','\U9480','\U9481','\U9482','\U9483','\U9484','\U9485','\U9486','\U9487','\U9488','\U9489','\U948A','\U948B','\U948C','\U948D','\U948E','\U948F','\U9490','\U9491','\U9492','\U9493','\U9494','\U9495','\U9496','\U9497','\U9498','\U9499','\U949A','\U949B','\U949C','\U949D','\U949E','\U949F','\U94A0','\U94A1','\U94A2','\U94A3','\U94A4','\U94A5','\U94A6','\U94A7','\U94A8','\U94A9','\U94AA','\U94AB','\U94AC','\U94AD','\U94AE','\U94AF','\U94B0','\U94B1','\U94B2','\U94B3','\U94B4','\U94B5','\U94B6','\U94B7','\U94B8','\U94B9','\U94BA','\U94BB','\U94BC','\U94BD','\U94BE','\U94BF','\U94C0','\U94C1','\U94C2','\U94C3','\U94C4','\U94C5','\U94C6','\U94C7','\U94C8','\U94C9','\U94CA','\U94CB','\U94CC','\U94CD','\U94CE','\U94CF','\U94D0','\U94D1','\U94D2','\U94D3','\U94D4','\U94D5','\U94D6','\U94D7','\U94D8','\U94D9','\U94DA','\U94DB','\U94DC','\U94DD','\U94DE','\U94DF','\U94E0','\U94E1','\U94E2','\U94E3','\U94E4','\U94E5','\U94E6','\U94E7','\U94E8','\U94E9','\U94EA','\U94EB','\U94EC','\U94ED','\U94EE','\U94EF','\U94F0','\U94F1','\U94F2','\U94F3','\U94F4','\U94F5','\U94F6','\U94F7','\U94F8','\U94F9','\U94FA','\U94FB','\U94FC','\U94FD','\U94FE','\U94FF','\U9500','\U9501','\U9502','\U9503','\U9504','\U9505','\U9506','\U9507','\U9508','\U9509','\U950A','\U950B','\U950C','\U950D','\U950E','\U950F','\U9510','\U9511','\U9512','\U9513','\U9514','\U9515','\U9516','\U9517','\U9518','\U9519','\U951A','\U951B','\U951C','\U951D','\U951E','\U951F','\U9520','\U9521','\U9522','\U9523','\U9524','\U9525','\U9526','\U9527','\U9528','\U9529','\U952A','\U952B','\U952C','\U952D','\U952E','\U952F','\U9530','\U9531','\U9532','\U9533','\U9534','\U9535','\U9536','\U9537','\U9538','\U9539','\U953A','\U953B','\U953C','\U953D','\U953E','\U953F','\U9540','\U9541','\U9542','\U9543','\U9544','\U9545','\U9546','\U9547','\U9548','\U9549','\U954A','\U954B','\U954C','\U954D','\U954E','\U954F','\U9550','\U9551','\U9552','\U9553','\U9554','\U9555','\U9556','\U9557','\U9558','\U9559','\U955A','\U955B','\U955C','\U955D','\U955E','\U955F','\U9560','\U9561','\U9562','\U9563','\U9564','\U9565','\U9566','\U9567','\U9568','\U9569','\U956A','\U956B','\U956C','\U956D','\U956E','\U956F','\U9570','\U9571','\U9572','\U9573','\U9574','\U9575','\U9576','\U9577','\U9578','\U9579','\U957A','\U957B','\U957C','\U957D','\U957E','\U957F','\U9580','\U9581','\U9582','\U9583','\U9584','\U9585','\U9586','\U9587','\U9588','\U9589','\U958A','\U958B','\U958C','\U958D','\U958E','\U958F','\U9590','\U9591','\U9592','\U9593','\U9594','\U9595','\U9596','\U9597','\U9598','\U9599','\U959A','\U959B','\U959C','\U959D','\U959E','\U959F','\U95A0','\U95A1','\U95A2','\U95A3','\U95A4','\U95A5','\U95A6','\U95A7','\U95A8','\U95A9','\U95AA','\U95AB','\U95AC','\U95AD','\U95AE','\U95AF','\U95B0','\U95B1','\U95B2','\U95B3','\U95B4','\U95B5','\U95B6','\U95B7','\U95B8','\U95B9','\U95BA','\U95BB','\U95BC','\U95BD','\U95BE','\U95BF','\U95C0','\U95C1','\U95C2','\U95C3','\U95C4','\U95C5','\U95C6','\U95C7','\U95C8','\U95C9','\U95CA','\U95CB','\U95CC','\U95CD','\U95CE','\U95CF','\U95D0','\U95D1','\U95D2','\U95D3','\U95D4','\U95D5','\U95D6','\U95D7','\U95D8','\U95D9','\U95DA','\U95DB','\U95DC','\U95DD','\U95DE','\U95DF','\U95E0','\U95E1','\U95E2','\U95E3','\U95E4','\U95E5','\U95E6','\U95E7','\U95E8','\U95E9','\U95EA','\U95EB','\U95EC','\U95ED','\U95EE','\U95EF','\U95F0','\U95F1','\U95F2','\U95F3','\U95F4','\U95F5','\U95F6','\U95F7','\U95F8','\U95F9','\U95FA','\U95FB','\U95FC','\U95FD','\U95FE','\U95FF','\U9600','\U9601','\U9602','\U9603','\U9604','\U9605','\U9606','\U9607','\U9608','\U9609','\U960A','\U960B','\U960C','\U960D','\U960E','\U960F','\U9610','\U9611','\U9612','\U9613','\U9614','\U9615','\U9616','\U9617','\U9618','\U9619','\U961A','\U961B','\U961C','\U961D','\U961E','\U961F','\U9620','\U9621','\U9622','\U9623','\U9624','\U9625','\U9626','\U9627','\U9628','\U9629','\U962A','\U962B','\U962C','\U962D','\U962E','\U962F','\U9630','\U9631','\U9632','\U9633','\U9634','\U9635','\U9636','\U9637','\U9638','\U9639','\U963A','\U963B','\U963C','\U963D','\U963E','\U963F','\U9640','\U9641','\U9642','\U9643','\U9644','\U9645','\U9646','\U9647','\U9648','\U9649','\U964A','\U964B','\U964C','\U964D','\U964E','\U964F','\U9650','\U9651','\U9652','\U9653','\U9654','\U9655','\U9656','\U9657','\U9658','\U9659','\U965A','\U965B','\U965C','\U965D','\U965E','\U965F','\U9660','\U9661','\U9662','\U9663','\U9664','\U9665','\U9666','\U9667','\U9668','\U9669','\U966A','\U966B','\U966C','\U966D','\U966E','\U966F','\U9670','\U9671','\U9672','\U9673','\U9674','\U9675','\U9676','\U9677','\U9678','\U9679','\U967A','\U967B','\U967C','\U967D','\U967E','\U967F','\U9680','\U9681','\U9682','\U9683','\U9684','\U9685','\U9686','\U9687','\U9688','\U9689','\U968A','\U968B','\U968C','\U968D','\U968E','\U968F','\U9690','\U9691','\U9692','\U9693','\U9694','\U9695','\U9696','\U9697','\U9698','\U9699','\U969A','\U969B','\U969C','\U969D','\U969E','\U969F','\U96A0','\U96A1','\U96A2','\U96A3','\U96A4','\U96A5','\U96A6','\U96A7','\U96A8','\U96A9','\U96AA','\U96AB','\U96AC','\U96AD','\U96AE','\U96AF','\U96B0','\U96B1','\U96B2','\U96B3','\U96B4','\U96B5','\U96B6','\U96B7','\U96B8','\U96B9','\U96BA','\U96BB','\U96BC','\U96BD','\U96BE','\U96BF','\U96C0','\U96C1','\U96C2','\U96C3','\U96C4','\U96C5','\U96C6','\U96C7','\U96C8','\U96C9','\U96CA','\U96CB','\U96CC','\U96CD','\U96CE','\U96CF','\U96D0','\U96D1','\U96D2','\U96D3','\U96D4','\U96D5','\U96D6','\U96D7','\U96D8','\U96D9','\U96DA','\U96DB','\U96DC','\U96DD','\U96DE','\U96DF','\U96E0','\U96E1','\U96E2','\U96E3','\U96E4','\U96E5','\U96E6','\U96E7','\U96E8','\U96E9','\U96EA','\U96EB','\U96EC','\U96ED','\U96EE','\U96EF','\U96F0','\U96F1','\U96F2','\U96F3','\U96F4','\U96F5','\U96F6','\U96F7','\U96F8','\U96F9','\U96FA','\U96FB','\U96FC','\U96FD','\U96FE','\U96FF','\U9700','\U9701','\U9702','\U9703','\U9704','\U9705','\U9706','\U9707','\U9708','\U9709','\U970A','\U970B','\U970C','\U970D','\U970E','\U970F','\U9710','\U9711','\U9712','\U9713','\U9714','\U9715','\U9716','\U9717','\U9718','\U9719','\U971A','\U971B','\U971C','\U971D','\U971E','\U971F','\U9720','\U9721','\U9722','\U9723','\U9724','\U9725','\U9726','\U9727','\U9728','\U9729','\U972A','\U972B','\U972C','\U972D','\U972E','\U972F','\U9730','\U9731','\U9732','\U9733','\U9734','\U9735','\U9736','\U9737','\U9738','\U9739','\U973A','\U973B','\U973C','\U973D','\U973E','\U973F','\U9740','\U9741','\U9742','\U9743','\U9744','\U9745','\U9746','\U9747','\U9748','\U9749','\U974A','\U974B','\U974C','\U974D','\U974E','\U974F','\U9750','\U9751','\U9752','\U9753','\U9754','\U9755','\U9756','\U9757','\U9758','\U9759','\U975A','\U975B','\U975C','\U975D','\U975E','\U975F','\U9760','\U9761','\U9762','\U9763','\U9764','\U9765','\U9766','\U9767','\U9768','\U9769','\U976A','\U976B','\U976C','\U976D','\U976E','\U976F','\U9770','\U9771','\U9772','\U9773','\U9774','\U9775','\U9776','\U9777','\U9778','\U9779','\U977A','\U977B','\U977C','\U977D','\U977E','\U977F','\U9780','\U9781','\U9782','\U9783','\U9784','\U9785','\U9786','\U9787','\U9788','\U9789','\U978A','\U978B','\U978C','\U978D','\U978E','\U978F','\U9790','\U9791','\U9792','\U9793','\U9794','\U9795','\U9796','\U9797','\U9798','\U9799','\U979A','\U979B','\U979C','\U979D','\U979E','\U979F','\U97A0','\U97A1','\U97A2','\U97A3','\U97A4','\U97A5','\U97A6','\U97A7','\U97A8','\U97A9','\U97AA','\U97AB','\U97AC','\U97AD','\U97AE','\U97AF','\U97B0','\U97B1','\U97B2','\U97B3','\U97B4','\U97B5','\U97B6','\U97B7','\U97B8','\U97B9','\U97BA','\U97BB','\U97BC','\U97BD','\U97BE','\U97BF','\U97C0','\U97C1','\U97C2','\U97C3','\U97C4','\U97C5','\U97C6','\U97C7','\U97C8','\U97C9','\U97CA','\U97CB','\U97CC','\U97CD','\U97CE','\U97CF','\U97D0','\U97D1','\U97D2','\U97D3','\U97D4','\U97D5','\U97D6','\U97D7','\U97D8','\U97D9','\U97DA','\U97DB','\U97DC','\U97DD','\U97DE','\U97DF','\U97E0','\U97E1','\U97E2','\U97E3','\U97E4','\U97E5','\U97E6','\U97E7','\U97E8','\U97E9','\U97EA','\U97EB','\U97EC','\U97ED','\U97EE','\U97EF','\U97F0','\U97F1','\U97F2','\U97F3','\U97F4','\U97F5','\U97F6','\U97F7','\U97F8','\U97F9','\U97FA','\U97FB','\U97FC','\U97FD','\U97FE','\U97FF','\U9800','\U9801','\U9802','\U9803','\U9804','\U9805','\U9806','\U9807','\U9808','\U9809','\U980A','\U980B','\U980C','\U980D','\U980E','\U980F','\U9810','\U9811','\U9812','\U9813','\U9814','\U9815','\U9816','\U9817','\U9818','\U9819','\U981A','\U981B','\U981C','\U981D','\U981E','\U981F','\U9820','\U9821','\U9822','\U9823','\U9824','\U9825','\U9826','\U9827','\U9828','\U9829','\U982A','\U982B','\U982C','\U982D','\U982E','\U982F','\U9830','\U9831','\U9832','\U9833','\U9834','\U9835','\U9836','\U9837','\U9838','\U9839','\U983A','\U983B','\U983C','\U983D','\U983E','\U983F','\U9840','\U9841','\U9842','\U9843','\U9844','\U9845','\U9846','\U9847','\U9848','\U9849','\U984A','\U984B','\U984C','\U984D','\U984E','\U984F','\U9850','\U9851','\U9852','\U9853','\U9854','\U9855','\U9856','\U9857','\U9858','\U9859','\U985A','\U985B','\U985C','\U985D','\U985E','\U985F','\U9860','\U9861','\U9862','\U9863','\U9864','\U9865','\U9866','\U9867','\U9868','\U9869','\U986A','\U986B','\U986C','\U986D','\U986E','\U986F','\U9870','\U9871','\U9872','\U9873','\U9874','\U9875','\U9876','\U9877','\U9878','\U9879','\U987A','\U987B','\U987C','\U987D','\U987E','\U987F','\U9880','\U9881','\U9882','\U9883','\U9884','\U9885','\U9886','\U9887','\U9888','\U9889','\U988A','\U988B','\U988C','\U988D','\U988E','\U988F','\U9890','\U9891','\U9892','\U9893','\U9894','\U9895','\U9896','\U9897','\U9898','\U9899','\U989A','\U989B','\U989C','\U989D','\U989E','\U989F','\U98A0','\U98A1','\U98A2','\U98A3','\U98A4','\U98A5','\U98A6','\U98A7','\U98A8','\U98A9','\U98AA','\U98AB','\U98AC','\U98AD','\U98AE','\U98AF','\U98B0','\U98B1','\U98B2','\U98B3','\U98B4','\U98B5','\U98B6','\U98B7','\U98B8','\U98B9','\U98BA','\U98BB','\U98BC','\U98BD','\U98BE','\U98BF','\U98C0','\U98C1','\U98C2','\U98C3','\U98C4','\U98C5','\U98C6','\U98C7','\U98C8','\U98C9','\U98CA','\U98CB','\U98CC','\U98CD','\U98CE','\U98CF','\U98D0','\U98D1','\U98D2','\U98D3','\U98D4','\U98D5','\U98D6','\U98D7','\U98D8','\U98D9','\U98DA','\U98DB','\U98DC','\U98DD','\U98DE','\U98DF','\U98E0','\U98E1','\U98E2','\U98E3','\U98E4','\U98E5','\U98E6','\U98E7','\U98E8','\U98E9','\U98EA','\U98EB','\U98EC','\U98ED','\U98EE','\U98EF','\U98F0','\U98F1','\U98F2','\U98F3','\U98F4','\U98F5','\U98F6','\U98F7','\U98F8','\U98F9','\U98FA','\U98FB','\U98FC','\U98FD','\U98FE','\U98FF','\U9900','\U9901','\U9902','\U9903','\U9904','\U9905','\U9906','\U9907','\U9908','\U9909','\U990A','\U990B','\U990C','\U990D','\U990E','\U990F','\U9910','\U9911','\U9912','\U9913','\U9914','\U9915','\U9916','\U9917','\U9918','\U9919','\U991A','\U991B','\U991C','\U991D','\U991E','\U991F','\U9920','\U9921','\U9922','\U9923','\U9924','\U9925','\U9926','\U9927','\U9928','\U9929','\U992A','\U992B','\U992C','\U992D','\U992E','\U992F','\U9930','\U9931','\U9932','\U9933','\U9934','\U9935','\U9936','\U9937','\U9938','\U9939','\U993A','\U993B','\U993C','\U993D','\U993E','\U993F','\U9940','\U9941','\U9942','\U9943','\U9944','\U9945','\U9946','\U9947','\U9948','\U9949','\U994A','\U994B','\U994C','\U994D','\U994E','\U994F','\U9950','\U9951','\U9952','\U9953','\U9954','\U9955','\U9956','\U9957','\U9958','\U9959','\U995A','\U995B','\U995C','\U995D','\U995E','\U995F','\U9960','\U9961','\U9962','\U9963','\U9964','\U9965','\U9966','\U9967','\U9968','\U9969','\U996A','\U996B','\U996C','\U996D','\U996E','\U996F','\U9970','\U9971','\U9972','\U9973','\U9974','\U9975','\U9976','\U9977','\U9978','\U9979','\U997A','\U997B','\U997C','\U997D','\U997E','\U997F','\U9980','\U9981','\U9982','\U9983','\U9984','\U9985','\U9986','\U9987','\U9988','\U9989','\U998A','\U998B','\U998C','\U998D','\U998E','\U998F','\U9990','\U9991','\U9992','\U9993','\U9994','\U9995','\U9996','\U9997','\U9998','\U9999','\U999A','\U999B','\U999C','\U999D','\U999E','\U999F','\U99A0','\U99A1','\U99A2','\U99A3','\U99A4','\U99A5','\U99A6','\U99A7','\U99A8','\U99A9','\U99AA','\U99AB','\U99AC','\U99AD','\U99AE','\U99AF','\U99B0','\U99B1','\U99B2','\U99B3','\U99B4','\U99B5','\U99B6','\U99B7','\U99B8','\U99B9','\U99BA','\U99BB','\U99BC','\U99BD','\U99BE','\U99BF','\U99C0','\U99C1','\U99C2','\U99C3','\U99C4','\U99C5','\U99C6','\U99C7','\U99C8','\U99C9','\U99CA','\U99CB','\U99CC','\U99CD','\U99CE','\U99CF','\U99D0','\U99D1','\U99D2','\U99D3','\U99D4','\U99D5','\U99D6','\U99D7','\U99D8','\U99D9','\U99DA','\U99DB','\U99DC','\U99DD','\U99DE','\U99DF','\U99E0','\U99E1','\U99E2','\U99E3','\U99E4','\U99E5','\U99E6','\U99E7','\U99E8','\U99E9','\U99EA','\U99EB','\U99EC','\U99ED','\U99EE','\U99EF','\U99F0','\U99F1','\U99F2','\U99F3','\U99F4','\U99F5','\U99F6','\U99F7','\U99F8','\U99F9','\U99FA','\U99FB','\U99FC','\U99FD','\U99FE','\U99FF','\U9A00','\U9A01','\U9A02','\U9A03','\U9A04','\U9A05','\U9A06','\U9A07','\U9A08','\U9A09','\U9A0A','\U9A0B','\U9A0C','\U9A0D','\U9A0E','\U9A0F','\U9A10','\U9A11','\U9A12','\U9A13','\U9A14','\U9A15','\U9A16','\U9A17','\U9A18','\U9A19','\U9A1A','\U9A1B','\U9A1C','\U9A1D','\U9A1E','\U9A1F','\U9A20','\U9A21','\U9A22','\U9A23','\U9A24','\U9A25','\U9A26','\U9A27','\U9A28','\U9A29','\U9A2A','\U9A2B','\U9A2C','\U9A2D','\U9A2E','\U9A2F','\U9A30','\U9A31','\U9A32','\U9A33','\U9A34','\U9A35','\U9A36','\U9A37','\U9A38','\U9A39','\U9A3A','\U9A3B','\U9A3C','\U9A3D','\U9A3E','\U9A3F','\U9A40','\U9A41','\U9A42','\U9A43','\U9A44','\U9A45','\U9A46','\U9A47','\U9A48','\U9A49','\U9A4A','\U9A4B','\U9A4C','\U9A4D','\U9A4E','\U9A4F','\U9A50','\U9A51','\U9A52','\U9A53','\U9A54','\U9A55','\U9A56','\U9A57','\U9A58','\U9A59','\U9A5A','\U9A5B','\U9A5C','\U9A5D','\U9A5E','\U9A5F','\U9A60','\U9A61','\U9A62','\U9A63','\U9A64','\U9A65','\U9A66','\U9A67','\U9A68','\U9A69','\U9A6A','\U9A6B','\U9A6C','\U9A6D','\U9A6E','\U9A6F','\U9A70','\U9A71','\U9A72','\U9A73','\U9A74','\U9A75','\U9A76','\U9A77','\U9A78','\U9A79','\U9A7A','\U9A7B','\U9A7C','\U9A7D','\U9A7E','\U9A7F','\U9A80','\U9A81','\U9A82','\U9A83','\U9A84','\U9A85','\U9A86','\U9A87','\U9A88','\U9A89','\U9A8A','\U9A8B','\U9A8C','\U9A8D','\U9A8E','\U9A8F','\U9A90','\U9A91','\U9A92','\U9A93','\U9A94','\U9A95','\U9A96','\U9A97','\U9A98','\U9A99','\U9A9A','\U9A9B','\U9A9C','\U9A9D','\U9A9E','\U9A9F','\U9AA0','\U9AA1','\U9AA2','\U9AA3','\U9AA4','\U9AA5','\U9AA6','\U9AA7','\U9AA8','\U9AA9','\U9AAA','\U9AAB','\U9AAC','\U9AAD','\U9AAE','\U9AAF','\U9AB0','\U9AB1','\U9AB2','\U9AB3','\U9AB4','\U9AB5','\U9AB6','\U9AB7','\U9AB8','\U9AB9','\U9ABA','\U9ABB','\U9ABC','\U9ABD','\U9ABE','\U9ABF','\U9AC0','\U9AC1','\U9AC2','\U9AC3','\U9AC4','\U9AC5','\U9AC6','\U9AC7','\U9AC8','\U9AC9','\U9ACA','\U9ACB','\U9ACC','\U9ACD','\U9ACE','\U9ACF','\U9AD0','\U9AD1','\U9AD2','\U9AD3','\U9AD4','\U9AD5','\U9AD6','\U9AD7','\U9AD8','\U9AD9','\U9ADA','\U9ADB','\U9ADC','\U9ADD','\U9ADE','\U9ADF','\U9AE0','\U9AE1','\U9AE2','\U9AE3','\U9AE4','\U9AE5','\U9AE6','\U9AE7','\U9AE8','\U9AE9','\U9AEA','\U9AEB','\U9AEC','\U9AED','\U9AEE','\U9AEF','\U9AF0','\U9AF1','\U9AF2','\U9AF3','\U9AF4','\U9AF5','\U9AF6','\U9AF7','\U9AF8','\U9AF9','\U9AFA','\U9AFB','\U9AFC','\U9AFD','\U9AFE','\U9AFF','\U9B00','\U9B01','\U9B02','\U9B03','\U9B04','\U9B05','\U9B06','\U9B07','\U9B08','\U9B09','\U9B0A','\U9B0B','\U9B0C','\U9B0D','\U9B0E','\U9B0F','\U9B10','\U9B11','\U9B12','\U9B13','\U9B14','\U9B15','\U9B16','\U9B17','\U9B18','\U9B19','\U9B1A','\U9B1B','\U9B1C','\U9B1D','\U9B1E','\U9B1F','\U9B20','\U9B21','\U9B22','\U9B23','\U9B24','\U9B25','\U9B26','\U9B27','\U9B28','\U9B29','\U9B2A','\U9B2B','\U9B2C','\U9B2D','\U9B2E','\U9B2F','\U9B30','\U9B31','\U9B32','\U9B33','\U9B34','\U9B35','\U9B36','\U9B37','\U9B38','\U9B39','\U9B3A','\U9B3B','\U9B3C','\U9B3D','\U9B3E','\U9B3F','\U9B40','\U9B41','\U9B42','\U9B43','\U9B44','\U9B45','\U9B46','\U9B47','\U9B48','\U9B49','\U9B4A','\U9B4B','\U9B4C','\U9B4D','\U9B4E','\U9B4F','\U9B50','\U9B51','\U9B52','\U9B53','\U9B54','\U9B55','\U9B56','\U9B57','\U9B58','\U9B59','\U9B5A','\U9B5B','\U9B5C','\U9B5D','\U9B5E','\U9B5F','\U9B60','\U9B61','\U9B62','\U9B63','\U9B64','\U9B65','\U9B66','\U9B67','\U9B68','\U9B69','\U9B6A','\U9B6B','\U9B6C','\U9B6D','\U9B6E','\U9B6F','\U9B70','\U9B71','\U9B72','\U9B73','\U9B74','\U9B75','\U9B76','\U9B77','\U9B78','\U9B79','\U9B7A','\U9B7B','\U9B7C','\U9B7D','\U9B7E','\U9B7F','\U9B80','\U9B81','\U9B82','\U9B83','\U9B84','\U9B85','\U9B86','\U9B87','\U9B88','\U9B89','\U9B8A','\U9B8B','\U9B8C','\U9B8D','\U9B8E','\U9B8F','\U9B90','\U9B91','\U9B92','\U9B93','\U9B94','\U9B95','\U9B96','\U9B97','\U9B98','\U9B99','\U9B9A','\U9B9B','\U9B9C','\U9B9D','\U9B9E','\U9B9F','\U9BA0','\U9BA1','\U9BA2','\U9BA3','\U9BA4','\U9BA5','\U9BA6','\U9BA7','\U9BA8','\U9BA9','\U9BAA','\U9BAB','\U9BAC','\U9BAD','\U9BAE','\U9BAF','\U9BB0','\U9BB1','\U9BB2','\U9BB3','\U9BB4','\U9BB5','\U9BB6','\U9BB7','\U9BB8','\U9BB9','\U9BBA','\U9BBB','\U9BBC','\U9BBD','\U9BBE','\U9BBF','\U9BC0','\U9BC1','\U9BC2','\U9BC3','\U9BC4','\U9BC5','\U9BC6','\U9BC7','\U9BC8','\U9BC9','\U9BCA','\U9BCB','\U9BCC','\U9BCD','\U9BCE','\U9BCF','\U9BD0','\U9BD1','\U9BD2','\U9BD3','\U9BD4','\U9BD5','\U9BD6','\U9BD7','\U9BD8','\U9BD9','\U9BDA','\U9BDB','\U9BDC','\U9BDD','\U9BDE','\U9BDF','\U9BE0','\U9BE1','\U9BE2','\U9BE3','\U9BE4','\U9BE5','\U9BE6','\U9BE7','\U9BE8','\U9BE9','\U9BEA','\U9BEB','\U9BEC','\U9BED','\U9BEE','\U9BEF','\U9BF0','\U9BF1','\U9BF2','\U9BF3','\U9BF4','\U9BF5','\U9BF6','\U9BF7','\U9BF8','\U9BF9','\U9BFA','\U9BFB','\U9BFC','\U9BFD','\U9BFE','\U9BFF','\U9C00','\U9C01','\U9C02','\U9C03','\U9C04','\U9C05','\U9C06','\U9C07','\U9C08','\U9C09','\U9C0A','\U9C0B','\U9C0C','\U9C0D','\U9C0E','\U9C0F','\U9C10','\U9C11','\U9C12','\U9C13','\U9C14','\U9C15','\U9C16','\U9C17','\U9C18','\U9C19','\U9C1A','\U9C1B','\U9C1C','\U9C1D','\U9C1E','\U9C1F','\U9C20','\U9C21','\U9C22','\U9C23','\U9C24','\U9C25','\U9C26','\U9C27','\U9C28','\U9C29','\U9C2A','\U9C2B','\U9C2C','\U9C2D','\U9C2E','\U9C2F','\U9C30','\U9C31','\U9C32','\U9C33','\U9C34','\U9C35','\U9C36','\U9C37','\U9C38','\U9C39','\U9C3A','\U9C3B','\U9C3C','\U9C3D','\U9C3E','\U9C3F','\U9C40','\U9C41','\U9C42','\U9C43','\U9C44','\U9C45','\U9C46','\U9C47','\U9C48','\U9C49','\U9C4A','\U9C4B','\U9C4C','\U9C4D','\U9C4E','\U9C4F','\U9C50','\U9C51','\U9C52','\U9C53','\U9C54','\U9C55','\U9C56','\U9C57','\U9C58','\U9C59','\U9C5A','\U9C5B','\U9C5C','\U9C5D','\U9C5E','\U9C5F','\U9C60','\U9C61','\U9C62','\U9C63','\U9C64','\U9C65','\U9C66','\U9C67','\U9C68','\U9C69','\U9C6A','\U9C6B','\U9C6C','\U9C6D','\U9C6E','\U9C6F','\U9C70','\U9C71','\U9C72','\U9C73','\U9C74','\U9C75','\U9C76','\U9C77','\U9C78','\U9C79','\U9C7A','\U9C7B','\U9C7C','\U9C7D','\U9C7E','\U9C7F','\U9C80','\U9C81','\U9C82','\U9C83','\U9C84','\U9C85','\U9C86','\U9C87','\U9C88','\U9C89','\U9C8A','\U9C8B','\U9C8C','\U9C8D','\U9C8E','\U9C8F','\U9C90','\U9C91','\U9C92','\U9C93','\U9C94','\U9C95','\U9C96','\U9C97','\U9C98','\U9C99','\U9C9A','\U9C9B','\U9C9C','\U9C9D','\U9C9E','\U9C9F','\U9CA0','\U9CA1','\U9CA2','\U9CA3','\U9CA4','\U9CA5','\U9CA6','\U9CA7','\U9CA8','\U9CA9','\U9CAA','\U9CAB','\U9CAC','\U9CAD','\U9CAE','\U9CAF','\U9CB0','\U9CB1','\U9CB2','\U9CB3','\U9CB4','\U9CB5','\U9CB6','\U9CB7','\U9CB8','\U9CB9','\U9CBA','\U9CBB','\U9CBC','\U9CBD','\U9CBE','\U9CBF','\U9CC0','\U9CC1','\U9CC2','\U9CC3','\U9CC4','\U9CC5','\U9CC6','\U9CC7','\U9CC8','\U9CC9','\U9CCA','\U9CCB','\U9CCC','\U9CCD','\U9CCE','\U9CCF','\U9CD0','\U9CD1','\U9CD2','\U9CD3','\U9CD4','\U9CD5','\U9CD6','\U9CD7','\U9CD8','\U9CD9','\U9CDA','\U9CDB','\U9CDC','\U9CDD','\U9CDE','\U9CDF','\U9CE0','\U9CE1','\U9CE2','\U9CE3','\U9CE4','\U9CE5','\U9CE6','\U9CE7','\U9CE8','\U9CE9','\U9CEA','\U9CEB','\U9CEC','\U9CED','\U9CEE','\U9CEF','\U9CF0','\U9CF1','\U9CF2','\U9CF3','\U9CF4','\U9CF5','\U9CF6','\U9CF7','\U9CF8','\U9CF9','\U9CFA','\U9CFB','\U9CFC','\U9CFD','\U9CFE','\U9CFF','\U9D00','\U9D01','\U9D02','\U9D03','\U9D04','\U9D05','\U9D06','\U9D07','\U9D08','\U9D09','\U9D0A','\U9D0B','\U9D0C','\U9D0D','\U9D0E','\U9D0F','\U9D10','\U9D11','\U9D12','\U9D13','\U9D14','\U9D15','\U9D16','\U9D17','\U9D18','\U9D19','\U9D1A','\U9D1B','\U9D1C','\U9D1D','\U9D1E','\U9D1F','\U9D20','\U9D21','\U9D22','\U9D23','\U9D24','\U9D25','\U9D26','\U9D27','\U9D28','\U9D29','\U9D2A','\U9D2B','\U9D2C','\U9D2D','\U9D2E','\U9D2F','\U9D30','\U9D31','\U9D32','\U9D33','\U9D34','\U9D35','\U9D36','\U9D37','\U9D38','\U9D39','\U9D3A','\U9D3B','\U9D3C','\U9D3D','\U9D3E','\U9D3F','\U9D40','\U9D41','\U9D42','\U9D43','\U9D44','\U9D45','\U9D46','\U9D47','\U9D48','\U9D49','\U9D4A','\U9D4B','\U9D4C','\U9D4D','\U9D4E','\U9D4F','\U9D50','\U9D51','\U9D52','\U9D53','\U9D54','\U9D55','\U9D56','\U9D57','\U9D58','\U9D59','\U9D5A','\U9D5B','\U9D5C','\U9D5D','\U9D5E','\U9D5F','\U9D60','\U9D61','\U9D62','\U9D63','\U9D64','\U9D65','\U9D66','\U9D67','\U9D68','\U9D69','\U9D6A','\U9D6B','\U9D6C','\U9D6D','\U9D6E','\U9D6F','\U9D70','\U9D71','\U9D72','\U9D73','\U9D74','\U9D75','\U9D76','\U9D77','\U9D78','\U9D79','\U9D7A','\U9D7B','\U9D7C','\U9D7D','\U9D7E','\U9D7F','\U9D80','\U9D81','\U9D82','\U9D83','\U9D84','\U9D85','\U9D86','\U9D87','\U9D88','\U9D89','\U9D8A','\U9D8B','\U9D8C','\U9D8D','\U9D8E','\U9D8F','\U9D90','\U9D91','\U9D92','\U9D93','\U9D94','\U9D95','\U9D96','\U9D97','\U9D98','\U9D99','\U9D9A','\U9D9B','\U9D9C','\U9D9D','\U9D9E','\U9D9F','\U9DA0','\U9DA1','\U9DA2','\U9DA3','\U9DA4','\U9DA5','\U9DA6','\U9DA7','\U9DA8','\U9DA9','\U9DAA','\U9DAB','\U9DAC','\U9DAD','\U9DAE','\U9DAF','\U9DB0','\U9DB1','\U9DB2','\U9DB3','\U9DB4','\U9DB5','\U9DB6','\U9DB7','\U9DB8','\U9DB9','\U9DBA','\U9DBB','\U9DBC','\U9DBD','\U9DBE','\U9DBF','\U9DC0','\U9DC1','\U9DC2','\U9DC3','\U9DC4','\U9DC5','\U9DC6','\U9DC7','\U9DC8','\U9DC9','\U9DCA','\U9DCB','\U9DCC','\U9DCD','\U9DCE','\U9DCF','\U9DD0','\U9DD1','\U9DD2','\U9DD3','\U9DD4','\U9DD5','\U9DD6','\U9DD7','\U9DD8','\U9DD9','\U9DDA','\U9DDB','\U9DDC','\U9DDD','\U9DDE','\U9DDF','\U9DE0','\U9DE1','\U9DE2','\U9DE3','\U9DE4','\U9DE5','\U9DE6','\U9DE7','\U9DE8','\U9DE9','\U9DEA','\U9DEB','\U9DEC','\U9DED','\U9DEE','\U9DEF','\U9DF0','\U9DF1','\U9DF2','\U9DF3','\U9DF4','\U9DF5','\U9DF6','\U9DF7','\U9DF8','\U9DF9','\U9DFA','\U9DFB','\U9DFC','\U9DFD','\U9DFE','\U9DFF','\U9E00','\U9E01','\U9E02','\U9E03','\U9E04','\U9E05','\U9E06','\U9E07','\U9E08','\U9E09','\U9E0A','\U9E0B','\U9E0C','\U9E0D','\U9E0E','\U9E0F','\U9E10','\U9E11','\U9E12','\U9E13','\U9E14','\U9E15','\U9E16','\U9E17','\U9E18','\U9E19','\U9E1A','\U9E1B','\U9E1C','\U9E1D','\U9E1E','\U9E1F','\U9E20','\U9E21','\U9E22','\U9E23','\U9E24','\U9E25','\U9E26','\U9E27','\U9E28','\U9E29','\U9E2A','\U9E2B','\U9E2C','\U9E2D','\U9E2E','\U9E2F','\U9E30','\U9E31','\U9E32','\U9E33','\U9E34','\U9E35','\U9E36','\U9E37','\U9E38','\U9E39','\U9E3A','\U9E3B','\U9E3C','\U9E3D','\U9E3E','\U9E3F','\U9E40','\U9E41','\U9E42','\U9E43','\U9E44','\U9E45','\U9E46','\U9E47','\U9E48','\U9E49','\U9E4A','\U9E4B','\U9E4C','\U9E4D','\U9E4E','\U9E4F','\U9E50','\U9E51','\U9E52','\U9E53','\U9E54','\U9E55','\U9E56','\U9E57','\U9E58','\U9E59','\U9E5A','\U9E5B','\U9E5C','\U9E5D','\U9E5E','\U9E5F','\U9E60','\U9E61','\U9E62','\U9E63','\U9E64','\U9E65','\U9E66','\U9E67','\U9E68','\U9E69','\U9E6A','\U9E6B','\U9E6C','\U9E6D','\U9E6E','\U9E6F','\U9E70','\U9E71','\U9E72','\U9E73','\U9E74','\U9E75','\U9E76','\U9E77','\U9E78','\U9E79','\U9E7A','\U9E7B','\U9E7C','\U9E7D','\U9E7E','\U9E7F','\U9E80','\U9E81','\U9E82','\U9E83','\U9E84','\U9E85','\U9E86','\U9E87','\U9E88','\U9E89','\U9E8A','\U9E8B','\U9E8C','\U9E8D','\U9E8E','\U9E8F','\U9E90','\U9E91','\U9E92','\U9E93','\U9E94','\U9E95','\U9E96','\U9E97','\U9E98','\U9E99','\U9E9A','\U9E9B','\U9E9C','\U9E9D','\U9E9E','\U9E9F','\U9EA0','\U9EA1','\U9EA2','\U9EA3','\U9EA4','\U9EA5','\U9EA6','\U9EA7','\U9EA8','\U9EA9','\U9EAA','\U9EAB','\U9EAC','\U9EAD','\U9EAE','\U9EAF','\U9EB0','\U9EB1','\U9EB2','\U9EB3','\U9EB4','\U9EB5','\U9EB6','\U9EB7','\U9EB8','\U9EB9','\U9EBA','\U9EBB','\U9EBC','\U9EBD','\U9EBE','\U9EBF','\U9EC0','\U9EC1','\U9EC2','\U9EC3','\U9EC4','\U9EC5','\U9EC6','\U9EC7','\U9EC8','\U9EC9','\U9ECA','\U9ECB','\U9ECC','\U9ECD','\U9ECE','\U9ECF','\U9ED0','\U9ED1','\U9ED2','\U9ED3','\U9ED4','\U9ED5','\U9ED6','\U9ED7','\U9ED8','\U9ED9','\U9EDA','\U9EDB','\U9EDC','\U9EDD','\U9EDE','\U9EDF','\U9EE0','\U9EE1','\U9EE2','\U9EE3','\U9EE4','\U9EE5','\U9EE6','\U9EE7','\U9EE8','\U9EE9','\U9EEA','\U9EEB','\U9EEC','\U9EED','\U9EEE','\U9EEF','\U9EF0','\U9EF1','\U9EF2','\U9EF3','\U9EF4','\U9EF5','\U9EF6','\U9EF7','\U9EF8','\U9EF9','\U9EFA','\U9EFB','\U9EFC','\U9EFD','\U9EFE','\U9EFF','\U9F00','\U9F01','\U9F02','\U9F03','\U9F04','\U9F05','\U9F06','\U9F07','\U9F08','\U9F09','\U9F0A','\U9F0B','\U9F0C','\U9F0D','\U9F0E','\U9F0F','\U9F10','\U9F11','\U9F12','\U9F13','\U9F14','\U9F15','\U9F16','\U9F17','\U9F18','\U9F19','\U9F1A','\U9F1B','\U9F1C','\U9F1D','\U9F1E','\U9F1F','\U9F20','\U9F21','\U9F22','\U9F23','\U9F24','\U9F25','\U9F26','\U9F27','\U9F28','\U9F29','\U9F2A','\U9F2B','\U9F2C','\U9F2D','\U9F2E','\U9F2F','\U9F30','\U9F31','\U9F32','\U9F33','\U9F34','\U9F35','\U9F36','\U9F37','\U9F38','\U9F39','\U9F3A','\U9F3B','\U9F3C','\U9F3D','\U9F3E','\U9F3F','\U9F40','\U9F41','\U9F42','\U9F43','\U9F44','\U9F45','\U9F46','\U9F47','\U9F48','\U9F49','\U9F4A','\U9F4B','\U9F4C','\U9F4D','\U9F4E','\U9F4F','\U9F50','\U9F51','\U9F52','\U9F53','\U9F54','\U9F55','\U9F56','\U9F57','\U9F58','\U9F59','\U9F5A','\U9F5B','\U9F5C','\U9F5D','\U9F5E','\U9F5F','\U9F60','\U9F61','\U9F62','\U9F63','\U9F64','\U9F65','\U9F66','\U9F67','\U9F68','\U9F69','\U9F6A','\U9F6B','\U9F6C','\U9F6D','\U9F6E','\U9F6F','\U9F70','\U9F71','\U9F72','\U9F73','\U9F74','\U9F75','\U9F76','\U9F77','\U9F78','\U9F79','\U9F7A','\U9F7B','\U9F7C','\U9F7D','\U9F7E','\U9F7F','\U9F80','\U9F81','\U9F82','\U9F83','\U9F84','\U9F85','\U9F86','\U9F87','\U9F88','\U9F89','\U9F8A','\U9F8B','\U9F8C','\U9F8D','\U9F8E','\U9F8F','\U9F90','\U9F91','\U9F92','\U9F93','\U9F94','\U9F95','\U9F96','\U9F97','\U9F98','\U9F99','\U9F9A','\U9F9B','\U9F9C','\U9F9D','\U9F9E','\U9F9F','\U9FA0','\U9FA1','\U9FA2','\U9FA3','\U9FA4','\U9FA5','\U9FA6','\U9FA7','\U9FA8','\U9FA9','\U9FAA','\U9FAB','\U9FAC','\U9FAD','\U9FAE','\U9FAF','\U9FB0','\U9FB1','\U9FB2','\U9FB3','\U9FB4','\U9FB5','\U9FB6','\U9FB7','\U9FB8','\U9FB9','\U9FBA','\U9FBB','\U9FBC','\U9FBD','\U9FBE','\U9FBF','\U9FC0','\U9FC1','\U9FC2','\U9FC3','\U9FC4','\U9FC5','\U9FC6','\U9FC7','\U9FC8','\U9FC9','\U9FCA','\U9FCB','\U9FCC','\U9FCD','\U9FCE','\U9FCF','\U9FD0','\U9FD1','\U9FD2','\U9FD3','\U9FD4','\U9FD5','\U9FD6','\U9FD7','\U9FD8','\U9FD9','\U9FDA','\U9FDB','\U9FDC','\U9FDD','\U9FDE','\U9FDF','\U9FE0','\U9FE1','\U9FE2','\U9FE3','\U9FE4','\U9FE5','\U9FE6','\U9FE7','\U9FE8','\U9FE9','\U9FEA','\U9FEB','\U9FEC','\U9FED','\U9FEE','\U9FEF','\U9FF0','\U9FF1','\U9FF2','\U9FF3','\U9FF4','\U9FF5','\U9FF6','\U9FF7','\U9FF8','\U9FF9','\U9FFA','\U9FFB','\U9FFC','\U9FFD','\U9FFE','\U9FFF','\UA000','\UA001','\UA002','\UA003','\UA004','\UA005','\UA006','\UA007','\UA008','\UA009','\UA00A','\UA00B','\UA00C','\UA00D','\UA00E','\UA00F','\UA010','\UA011','\UA012','\UA013','\UA014','\UA015','\UA016','\UA017','\UA018','\UA019','\UA01A','\UA01B','\UA01C','\UA01D','\UA01E','\UA01F','\UA020','\UA021','\UA022','\UA023','\UA024','\UA025','\UA026','\UA027','\UA028','\UA029','\UA02A','\UA02B','\UA02C','\UA02D','\UA02E','\UA02F','\UA030','\UA031','\UA032','\UA033','\UA034','\UA035','\UA036','\UA037','\UA038','\UA039','\UA03A','\UA03B','\UA03C','\UA03D','\UA03E','\UA03F','\UA040','\UA041','\UA042','\UA043','\UA044','\UA045','\UA046','\UA047','\UA048','\UA049','\UA04A','\UA04B','\UA04C','\UA04D','\UA04E','\UA04F','\UA050','\UA051','\UA052','\UA053','\UA054','\UA055','\UA056','\UA057','\UA058','\UA059','\UA05A','\UA05B','\UA05C','\UA05D','\UA05E','\UA05F','\UA060','\UA061','\UA062','\UA063','\UA064','\UA065','\UA066','\UA067','\UA068','\UA069','\UA06A','\UA06B','\UA06C','\UA06D','\UA06E','\UA06F','\UA070','\UA071','\UA072','\UA073','\UA074','\UA075','\UA076','\UA077','\UA078','\UA079','\UA07A','\UA07B','\UA07C','\UA07D','\UA07E','\UA07F','\UA080','\UA081','\UA082','\UA083','\UA084','\UA085','\UA086','\UA087','\UA088','\UA089','\UA08A','\UA08B','\UA08C','\UA08D','\UA08E','\UA08F','\UA090','\UA091','\UA092','\UA093','\UA094','\UA095','\UA096','\UA097','\UA098','\UA099','\UA09A','\UA09B','\UA09C','\UA09D','\UA09E','\UA09F','\UA0A0','\UA0A1','\UA0A2','\UA0A3','\UA0A4','\UA0A5','\UA0A6','\UA0A7','\UA0A8','\UA0A9','\UA0AA','\UA0AB','\UA0AC','\UA0AD','\UA0AE','\UA0AF','\UA0B0','\UA0B1','\UA0B2','\UA0B3','\UA0B4','\UA0B5','\UA0B6','\UA0B7','\UA0B8','\UA0B9','\UA0BA','\UA0BB','\UA0BC','\UA0BD','\UA0BE','\UA0BF','\UA0C0','\UA0C1','\UA0C2','\UA0C3','\UA0C4','\UA0C5','\UA0C6','\UA0C7','\UA0C8','\UA0C9','\UA0CA','\UA0CB','\UA0CC','\UA0CD','\UA0CE','\UA0CF','\UA0D0','\UA0D1','\UA0D2','\UA0D3','\UA0D4','\UA0D5','\UA0D6','\UA0D7','\UA0D8','\UA0D9','\UA0DA','\UA0DB','\UA0DC','\UA0DD','\UA0DE','\UA0DF','\UA0E0','\UA0E1','\UA0E2','\UA0E3','\UA0E4','\UA0E5','\UA0E6','\UA0E7','\UA0E8','\UA0E9','\UA0EA','\UA0EB','\UA0EC','\UA0ED','\UA0EE','\UA0EF','\UA0F0','\UA0F1','\UA0F2','\UA0F3','\UA0F4','\UA0F5','\UA0F6','\UA0F7','\UA0F8','\UA0F9','\UA0FA','\UA0FB','\UA0FC','\UA0FD','\UA0FE','\UA0FF','\UA100','\UA101','\UA102','\UA103','\UA104','\UA105','\UA106','\UA107','\UA108','\UA109','\UA10A','\UA10B','\UA10C','\UA10D','\UA10E','\UA10F','\UA110','\UA111','\UA112','\UA113','\UA114','\UA115','\UA116','\UA117','\UA118','\UA119','\UA11A','\UA11B','\UA11C','\UA11D','\UA11E','\UA11F','\UA120','\UA121','\UA122','\UA123','\UA124','\UA125','\UA126','\UA127','\UA128','\UA129','\UA12A','\UA12B','\UA12C','\UA12D','\UA12E','\UA12F','\UA130','\UA131','\UA132','\UA133','\UA134','\UA135','\UA136','\UA137','\UA138','\UA139','\UA13A','\UA13B','\UA13C','\UA13D','\UA13E','\UA13F','\UA140','\UA141','\UA142','\UA143','\UA144','\UA145','\UA146','\UA147','\UA148','\UA149','\UA14A','\UA14B','\UA14C','\UA14D','\UA14E','\UA14F','\UA150','\UA151','\UA152','\UA153','\UA154','\UA155','\UA156','\UA157','\UA158','\UA159','\UA15A','\UA15B','\UA15C','\UA15D','\UA15E','\UA15F','\UA160','\UA161','\UA162','\UA163','\UA164','\UA165','\UA166','\UA167','\UA168','\UA169','\UA16A','\UA16B','\UA16C','\UA16D','\UA16E','\UA16F','\UA170','\UA171','\UA172','\UA173','\UA174','\UA175','\UA176','\UA177','\UA178','\UA179','\UA17A','\UA17B','\UA17C','\UA17D','\UA17E','\UA17F','\UA180','\UA181','\UA182','\UA183','\UA184','\UA185','\UA186','\UA187','\UA188','\UA189','\UA18A','\UA18B','\UA18C','\UA18D','\UA18E','\UA18F','\UA190','\UA191','\UA192','\UA193','\UA194','\UA195','\UA196','\UA197','\UA198','\UA199','\UA19A','\UA19B','\UA19C','\UA19D','\UA19E','\UA19F','\UA1A0','\UA1A1','\UA1A2','\UA1A3','\UA1A4','\UA1A5','\UA1A6','\UA1A7','\UA1A8','\UA1A9','\UA1AA','\UA1AB','\UA1AC','\UA1AD','\UA1AE','\UA1AF','\UA1B0','\UA1B1','\UA1B2','\UA1B3','\UA1B4','\UA1B5','\UA1B6','\UA1B7','\UA1B8','\UA1B9','\UA1BA','\UA1BB','\UA1BC','\UA1BD','\UA1BE','\UA1BF','\UA1C0','\UA1C1','\UA1C2','\UA1C3','\UA1C4','\UA1C5','\UA1C6','\UA1C7','\UA1C8','\UA1C9','\UA1CA','\UA1CB','\UA1CC','\UA1CD','\UA1CE','\UA1CF','\UA1D0','\UA1D1','\UA1D2','\UA1D3','\UA1D4','\UA1D5','\UA1D6','\UA1D7','\UA1D8','\UA1D9','\UA1DA','\UA1DB','\UA1DC','\UA1DD','\UA1DE','\UA1DF','\UA1E0','\UA1E1','\UA1E2','\UA1E3','\UA1E4','\UA1E5','\UA1E6','\UA1E7','\UA1E8','\UA1E9','\UA1EA','\UA1EB','\UA1EC','\UA1ED','\UA1EE','\UA1EF','\UA1F0','\UA1F1','\UA1F2','\UA1F3','\UA1F4','\UA1F5','\UA1F6','\UA1F7','\UA1F8','\UA1F9','\UA1FA','\UA1FB','\UA1FC','\UA1FD','\UA1FE','\UA1FF','\UA200','\UA201','\UA202','\UA203','\UA204','\UA205','\UA206','\UA207','\UA208','\UA209','\UA20A','\UA20B','\UA20C','\UA20D','\UA20E','\UA20F','\UA210','\UA211','\UA212','\UA213','\UA214','\UA215','\UA216','\UA217','\UA218','\UA219','\UA21A','\UA21B','\UA21C','\UA21D','\UA21E','\UA21F','\UA220','\UA221','\UA222','\UA223','\UA224','\UA225','\UA226','\UA227','\UA228','\UA229','\UA22A','\UA22B','\UA22C','\UA22D','\UA22E','\UA22F','\UA230','\UA231','\UA232','\UA233','\UA234','\UA235','\UA236','\UA237','\UA238','\UA239','\UA23A','\UA23B','\UA23C','\UA23D','\UA23E','\UA23F','\UA240','\UA241','\UA242','\UA243','\UA244','\UA245','\UA246','\UA247','\UA248','\UA249','\UA24A','\UA24B','\UA24C','\UA24D','\UA24E','\UA24F','\UA250','\UA251','\UA252','\UA253','\UA254','\UA255','\UA256','\UA257','\UA258','\UA259','\UA25A','\UA25B','\UA25C','\UA25D','\UA25E','\UA25F','\UA260','\UA261','\UA262','\UA263','\UA264','\UA265','\UA266','\UA267','\UA268','\UA269','\UA26A','\UA26B','\UA26C','\UA26D','\UA26E','\UA26F','\UA270','\UA271','\UA272','\UA273','\UA274','\UA275','\UA276','\UA277','\UA278','\UA279','\UA27A','\UA27B','\UA27C','\UA27D','\UA27E','\UA27F','\UA280','\UA281','\UA282','\UA283','\UA284','\UA285','\UA286','\UA287','\UA288','\UA289','\UA28A','\UA28B','\UA28C','\UA28D','\UA28E','\UA28F','\UA290','\UA291','\UA292','\UA293','\UA294','\UA295','\UA296','\UA297','\UA298','\UA299','\UA29A','\UA29B','\UA29C','\UA29D','\UA29E','\UA29F','\UA2A0','\UA2A1','\UA2A2','\UA2A3','\UA2A4','\UA2A5','\UA2A6','\UA2A7','\UA2A8','\UA2A9','\UA2AA','\UA2AB','\UA2AC','\UA2AD','\UA2AE','\UA2AF','\UA2B0','\UA2B1','\UA2B2','\UA2B3','\UA2B4','\UA2B5','\UA2B6','\UA2B7','\UA2B8','\UA2B9','\UA2BA','\UA2BB','\UA2BC','\UA2BD','\UA2BE','\UA2BF','\UA2C0','\UA2C1','\UA2C2','\UA2C3','\UA2C4','\UA2C5','\UA2C6','\UA2C7','\UA2C8','\UA2C9','\UA2CA','\UA2CB','\UA2CC','\UA2CD','\UA2CE','\UA2CF','\UA2D0','\UA2D1','\UA2D2','\UA2D3','\UA2D4','\UA2D5','\UA2D6','\UA2D7','\UA2D8','\UA2D9','\UA2DA','\UA2DB','\UA2DC','\UA2DD','\UA2DE','\UA2DF','\UA2E0','\UA2E1','\UA2E2','\UA2E3','\UA2E4','\UA2E5','\UA2E6','\UA2E7','\UA2E8','\UA2E9','\UA2EA','\UA2EB','\UA2EC','\UA2ED','\UA2EE','\UA2EF','\UA2F0','\UA2F1','\UA2F2','\UA2F3','\UA2F4','\UA2F5','\UA2F6','\UA2F7','\UA2F8','\UA2F9','\UA2FA','\UA2FB','\UA2FC','\UA2FD','\UA2FE','\UA2FF','\UA300','\UA301','\UA302','\UA303','\UA304','\UA305','\UA306','\UA307','\UA308','\UA309','\UA30A','\UA30B','\UA30C','\UA30D','\UA30E','\UA30F','\UA310','\UA311','\UA312','\UA313','\UA314','\UA315','\UA316','\UA317','\UA318','\UA319','\UA31A','\UA31B','\UA31C','\UA31D','\UA31E','\UA31F','\UA320','\UA321','\UA322','\UA323','\UA324','\UA325','\UA326','\UA327','\UA328','\UA329','\UA32A','\UA32B','\UA32C','\UA32D','\UA32E','\UA32F','\UA330','\UA331','\UA332','\UA333','\UA334','\UA335','\UA336','\UA337','\UA338','\UA339','\UA33A','\UA33B','\UA33C','\UA33D','\UA33E','\UA33F','\UA340','\UA341','\UA342','\UA343','\UA344','\UA345','\UA346','\UA347','\UA348','\UA349','\UA34A','\UA34B','\UA34C','\UA34D','\UA34E','\UA34F','\UA350','\UA351','\UA352','\UA353','\UA354','\UA355','\UA356','\UA357','\UA358','\UA359','\UA35A','\UA35B','\UA35C','\UA35D','\UA35E','\UA35F','\UA360','\UA361','\UA362','\UA363','\UA364','\UA365','\UA366','\UA367','\UA368','\UA369','\UA36A','\UA36B','\UA36C','\UA36D','\UA36E','\UA36F','\UA370','\UA371','\UA372','\UA373','\UA374','\UA375','\UA376','\UA377','\UA378','\UA379','\UA37A','\UA37B','\UA37C','\UA37D','\UA37E','\UA37F','\UA380','\UA381','\UA382','\UA383','\UA384','\UA385','\UA386','\UA387','\UA388','\UA389','\UA38A','\UA38B','\UA38C','\UA38D','\UA38E','\UA38F','\UA390','\UA391','\UA392','\UA393','\UA394','\UA395','\UA396','\UA397','\UA398','\UA399','\UA39A','\UA39B','\UA39C','\UA39D','\UA39E','\UA39F','\UA3A0','\UA3A1','\UA3A2','\UA3A3','\UA3A4','\UA3A5','\UA3A6','\UA3A7','\UA3A8','\UA3A9','\UA3AA','\UA3AB','\UA3AC','\UA3AD','\UA3AE','\UA3AF','\UA3B0','\UA3B1','\UA3B2','\UA3B3','\UA3B4','\UA3B5','\UA3B6','\UA3B7','\UA3B8','\UA3B9','\UA3BA','\UA3BB','\UA3BC','\UA3BD','\UA3BE','\UA3BF','\UA3C0','\UA3C1','\UA3C2','\UA3C3','\UA3C4','\UA3C5','\UA3C6','\UA3C7','\UA3C8','\UA3C9','\UA3CA','\UA3CB','\UA3CC','\UA3CD','\UA3CE','\UA3CF','\UA3D0','\UA3D1','\UA3D2','\UA3D3','\UA3D4','\UA3D5','\UA3D6','\UA3D7','\UA3D8','\UA3D9','\UA3DA','\UA3DB','\UA3DC','\UA3DD','\UA3DE','\UA3DF','\UA3E0','\UA3E1','\UA3E2','\UA3E3','\UA3E4','\UA3E5','\UA3E6','\UA3E7','\UA3E8','\UA3E9','\UA3EA','\UA3EB','\UA3EC','\UA3ED','\UA3EE','\UA3EF','\UA3F0','\UA3F1','\UA3F2','\UA3F3','\UA3F4','\UA3F5','\UA3F6','\UA3F7','\UA3F8','\UA3F9','\UA3FA','\UA3FB','\UA3FC','\UA3FD','\UA3FE','\UA3FF','\UA400','\UA401','\UA402','\UA403','\UA404','\UA405','\UA406','\UA407','\UA408','\UA409','\UA40A','\UA40B','\UA40C','\UA40D','\UA40E','\UA40F','\UA410','\UA411','\UA412','\UA413','\UA414','\UA415','\UA416','\UA417','\UA418','\UA419','\UA41A','\UA41B','\UA41C','\UA41D','\UA41E','\UA41F','\UA420','\UA421','\UA422','\UA423','\UA424','\UA425','\UA426','\UA427','\UA428','\UA429','\UA42A','\UA42B','\UA42C','\UA42D','\UA42E','\UA42F','\UA430','\UA431','\UA432','\UA433','\UA434','\UA435','\UA436','\UA437','\UA438','\UA439','\UA43A','\UA43B','\UA43C','\UA43D','\UA43E','\UA43F','\UA440','\UA441','\UA442','\UA443','\UA444','\UA445','\UA446','\UA447','\UA448','\UA449','\UA44A','\UA44B','\UA44C','\UA44D','\UA44E','\UA44F','\UA450','\UA451','\UA452','\UA453','\UA454','\UA455','\UA456','\UA457','\UA458','\UA459','\UA45A','\UA45B','\UA45C','\UA45D','\UA45E','\UA45F','\UA460','\UA461','\UA462','\UA463','\UA464','\UA465','\UA466','\UA467','\UA468','\UA469','\UA46A','\UA46B','\UA46C','\UA46D','\UA46E','\UA46F','\UA470','\UA471','\UA472','\UA473','\UA474','\UA475','\UA476','\UA477','\UA478','\UA479','\UA47A','\UA47B','\UA47C','\UA47D','\UA47E','\UA47F','\UA480','\UA481','\UA482','\UA483','\UA484','\UA485','\UA486','\UA487','\UA488','\UA489','\UA48A','\UA48B','\UA48C','\UA48D','\UA48E','\UA48F','\UA490','\UA491','\UA492','\UA493','\UA494','\UA495','\UA496','\UA497','\UA498','\UA499','\UA49A','\UA49B','\UA49C','\UA49D','\UA49E','\UA49F','\UA4A0','\UA4A1','\UA4A2','\UA4A3','\UA4A4','\UA4A5','\UA4A6','\UA4A7','\UA4A8','\UA4A9','\UA4AA','\UA4AB','\UA4AC','\UA4AD','\UA4AE','\UA4AF','\UA4B0','\UA4B1','\UA4B2','\UA4B3','\UA4B4','\UA4B5','\UA4B6','\UA4B7','\UA4B8','\UA4B9','\UA4BA','\UA4BB','\UA4BC','\UA4BD','\UA4BE','\UA4BF','\UA4C0','\UA4C1','\UA4C2','\UA4C3','\UA4C4','\UA4C5','\UA4C6','\UA4C7','\UA4C8','\UA4C9','\UA4CA','\UA4CB','\UA4CC','\UA4CD','\UA4CE','\UA4CF','\UA4D0','\UA4D1','\UA4D2','\UA4D3','\UA4D4','\UA4D5','\UA4D6','\UA4D7','\UA4D8','\UA4D9','\UA4DA','\UA4DB','\UA4DC','\UA4DD','\UA4DE','\UA4DF','\UA4E0','\UA4E1','\UA4E2','\UA4E3','\UA4E4','\UA4E5','\UA4E6','\UA4E7','\UA4E8','\UA4E9','\UA4EA','\UA4EB','\UA4EC','\UA4ED','\UA4EE','\UA4EF','\UA4F0','\UA4F1','\UA4F2','\UA4F3','\UA4F4','\UA4F5','\UA4F6','\UA4F7','\UA4F8','\UA4F9','\UA4FA','\UA4FB','\UA4FC','\UA4FD','\UA4FE','\UA4FF','\UA500','\UA501','\UA502','\UA503','\UA504','\UA505','\UA506','\UA507','\UA508','\UA509','\UA50A','\UA50B','\UA50C','\UA50D','\UA50E','\UA50F','\UA510','\UA511','\UA512','\UA513','\UA514','\UA515','\UA516','\UA517','\UA518','\UA519','\UA51A','\UA51B','\UA51C','\UA51D','\UA51E','\UA51F','\UA520','\UA521','\UA522','\UA523','\UA524','\UA525','\UA526','\UA527','\UA528','\UA529','\UA52A','\UA52B','\UA52C','\UA52D','\UA52E','\UA52F','\UA530','\UA531','\UA532','\UA533','\UA534','\UA535','\UA536','\UA537','\UA538','\UA539','\UA53A','\UA53B','\UA53C','\UA53D','\UA53E','\UA53F','\UA540','\UA541','\UA542','\UA543','\UA544','\UA545','\UA546','\UA547','\UA548','\UA549','\UA54A','\UA54B','\UA54C','\UA54D','\UA54E','\UA54F','\UA550','\UA551','\UA552','\UA553','\UA554','\UA555','\UA556','\UA557','\UA558','\UA559','\UA55A','\UA55B','\UA55C','\UA55D','\UA55E','\UA55F','\UA560','\UA561','\UA562','\UA563','\UA564','\UA565','\UA566','\UA567','\UA568','\UA569','\UA56A','\UA56B','\UA56C','\UA56D','\UA56E','\UA56F','\UA570','\UA571','\UA572','\UA573','\UA574','\UA575','\UA576','\UA577','\UA578','\UA579','\UA57A','\UA57B','\UA57C','\UA57D','\UA57E','\UA57F','\UA580','\UA581','\UA582','\UA583','\UA584','\UA585','\UA586','\UA587','\UA588','\UA589','\UA58A','\UA58B','\UA58C','\UA58D','\UA58E','\UA58F','\UA590','\UA591','\UA592','\UA593','\UA594','\UA595','\UA596','\UA597','\UA598','\UA599','\UA59A','\UA59B','\UA59C','\UA59D','\UA59E','\UA59F','\UA5A0','\UA5A1','\UA5A2','\UA5A3','\UA5A4','\UA5A5','\UA5A6','\UA5A7','\UA5A8','\UA5A9','\UA5AA','\UA5AB','\UA5AC','\UA5AD','\UA5AE','\UA5AF','\UA5B0','\UA5B1','\UA5B2','\UA5B3','\UA5B4','\UA5B5','\UA5B6','\UA5B7','\UA5B8','\UA5B9','\UA5BA','\UA5BB','\UA5BC','\UA5BD','\UA5BE','\UA5BF','\UA5C0','\UA5C1','\UA5C2','\UA5C3','\UA5C4','\UA5C5','\UA5C6','\UA5C7','\UA5C8','\UA5C9','\UA5CA','\UA5CB','\UA5CC','\UA5CD','\UA5CE','\UA5CF','\UA5D0','\UA5D1','\UA5D2','\UA5D3','\UA5D4','\UA5D5','\UA5D6','\UA5D7','\UA5D8','\UA5D9','\UA5DA','\UA5DB','\UA5DC','\UA5DD','\UA5DE','\UA5DF','\UA5E0','\UA5E1','\UA5E2','\UA5E3','\UA5E4','\UA5E5','\UA5E6','\UA5E7','\UA5E8','\UA5E9','\UA5EA','\UA5EB','\UA5EC','\UA5ED','\UA5EE','\UA5EF','\UA5F0','\UA5F1','\UA5F2','\UA5F3','\UA5F4','\UA5F5','\UA5F6','\UA5F7','\UA5F8','\UA5F9','\UA5FA','\UA5FB','\UA5FC','\UA5FD','\UA5FE','\UA5FF','\UA600','\UA601','\UA602','\UA603','\UA604','\UA605','\UA606','\UA607','\UA608','\UA609','\UA60A','\UA60B','\UA60C','\UA60D','\UA60E','\UA60F','\UA610','\UA611','\UA612','\UA613','\UA614','\UA615','\UA616','\UA617','\UA618','\UA619','\UA61A','\UA61B','\UA61C','\UA61D','\UA61E','\UA61F','\UA620','\UA621','\UA622','\UA623','\UA624','\UA625','\UA626','\UA627','\UA628','\UA629','\UA62A','\UA62B','\UA62C','\UA62D','\UA62E','\UA62F','\UA630','\UA631','\UA632','\UA633','\UA634','\UA635','\UA636','\UA637','\UA638','\UA639','\UA63A','\UA63B','\UA63C','\UA63D','\UA63E','\UA63F','\UA640','\UA641','\UA642','\UA643','\UA644','\UA645','\UA646','\UA647','\UA648','\UA649','\UA64A','\UA64B','\UA64C','\UA64D','\UA64E','\UA64F','\UA650','\UA651','\UA652','\UA653','\UA654','\UA655','\UA656','\UA657','\UA658','\UA659','\UA65A','\UA65B','\UA65C','\UA65D','\UA65E','\UA65F','\UA660','\UA661','\UA662','\UA663','\UA664','\UA665','\UA666','\UA667','\UA668','\UA669','\UA66A','\UA66B','\UA66C','\UA66D','\UA66E','\UA66F','\UA670','\UA671','\UA672','\UA673','\UA674','\UA675','\UA676','\UA677','\UA678','\UA679','\UA67A','\UA67B','\UA67C','\UA67D','\UA67E','\UA67F','\UA680','\UA681','\UA682','\UA683','\UA684','\UA685','\UA686','\UA687','\UA688','\UA689','\UA68A','\UA68B','\UA68C','\UA68D','\UA68E','\UA68F','\UA690','\UA691','\UA692','\UA693','\UA694','\UA695','\UA696','\UA697','\UA698','\UA699','\UA69A','\UA69B','\UA69C','\UA69D','\UA69E','\UA69F','\UA6A0','\UA6A1','\UA6A2','\UA6A3','\UA6A4','\UA6A5','\UA6A6','\UA6A7','\UA6A8','\UA6A9','\UA6AA','\UA6AB','\UA6AC','\UA6AD','\UA6AE','\UA6AF','\UA6B0','\UA6B1','\UA6B2','\UA6B3','\UA6B4','\UA6B5','\UA6B6','\UA6B7','\UA6B8','\UA6B9','\UA6BA','\UA6BB','\UA6BC','\UA6BD','\UA6BE','\UA6BF','\UA6C0','\UA6C1','\UA6C2','\UA6C3','\UA6C4','\UA6C5','\UA6C6','\UA6C7','\UA6C8','\UA6C9','\UA6CA','\UA6CB','\UA6CC','\UA6CD','\UA6CE','\UA6CF','\UA6D0','\UA6D1','\UA6D2','\UA6D3','\UA6D4','\UA6D5','\UA6D6','\UA6D7','\UA6D8','\UA6D9','\UA6DA','\UA6DB','\UA6DC','\UA6DD','\UA6DE','\UA6DF','\UA6E0','\UA6E1','\UA6E2','\UA6E3','\UA6E4','\UA6E5','\UA6E6','\UA6E7','\UA6E8','\UA6E9','\UA6EA','\UA6EB','\UA6EC','\UA6ED','\UA6EE','\UA6EF','\UA6F0','\UA6F1','\UA6F2','\UA6F3','\UA6F4','\UA6F5','\UA6F6','\UA6F7','\UA6F8','\UA6F9','\UA6FA','\UA6FB','\UA6FC','\UA6FD','\UA6FE','\UA6FF','\UA700','\UA701','\UA702','\UA703','\UA704','\UA705','\UA706','\UA707','\UA708','\UA709','\UA70A','\UA70B','\UA70C','\UA70D','\UA70E','\UA70F','\UA710','\UA711','\UA712','\UA713','\UA714','\UA715','\UA716','\UA717','\UA718','\UA719','\UA71A','\UA71B','\UA71C','\UA71D','\UA71E','\UA71F','\UA720','\UA721','\UA722','\UA723','\UA724','\UA725','\UA726','\UA727','\UA728','\UA729','\UA72A','\UA72B','\UA72C','\UA72D','\UA72E','\UA72F','\UA730','\UA731','\UA732','\UA733','\UA734','\UA735','\UA736','\UA737','\UA738','\UA739','\UA73A','\UA73B','\UA73C','\UA73D','\UA73E','\UA73F','\UA740','\UA741','\UA742','\UA743','\UA744','\UA745','\UA746','\UA747','\UA748','\UA749','\UA74A','\UA74B','\UA74C','\UA74D','\UA74E','\UA74F','\UA750','\UA751','\UA752','\UA753','\UA754','\UA755','\UA756','\UA757','\UA758','\UA759','\UA75A','\UA75B','\UA75C','\UA75D','\UA75E','\UA75F','\UA760','\UA761','\UA762','\UA763','\UA764','\UA765','\UA766','\UA767','\UA768','\UA769','\UA76A','\UA76B','\UA76C','\UA76D','\UA76E','\UA76F','\UA770','\UA771','\UA772','\UA773','\UA774','\UA775','\UA776','\UA777','\UA778','\UA779','\UA77A','\UA77B','\UA77C','\UA77D','\UA77E','\UA77F','\UA780','\UA781','\UA782','\UA783','\UA784','\UA785','\UA786','\UA787','\UA788','\UA789','\UA78A','\UA78B','\UA78C','\UA78D','\UA78E','\UA78F','\UA790','\UA791','\UA792','\UA793','\UA794','\UA795','\UA796','\UA797','\UA798','\UA799','\UA79A','\UA79B','\UA79C','\UA79D','\UA79E','\UA79F','\UA7A0','\UA7A1','\UA7A2','\UA7A3','\UA7A4','\UA7A5','\UA7A6','\UA7A7','\UA7A8','\UA7A9','\UA7AA','\UA7AB','\UA7AC','\UA7AD','\UA7AE','\UA7AF','\UA7B0','\UA7B1','\UA7B2','\UA7B3','\UA7B4','\UA7B5','\UA7B6','\UA7B7','\UA7B8','\UA7B9','\UA7BA','\UA7BB','\UA7BC','\UA7BD','\UA7BE','\UA7BF','\UA7C0','\UA7C1','\UA7C2','\UA7C3','\UA7C4','\UA7C5','\UA7C6','\UA7C7','\UA7C8','\UA7C9','\UA7CA','\UA7CB','\UA7CC','\UA7CD','\UA7CE','\UA7CF','\UA7D0','\UA7D1','\UA7D2','\UA7D3','\UA7D4','\UA7D5','\UA7D6','\UA7D7','\UA7D8','\UA7D9','\UA7DA','\UA7DB','\UA7DC','\UA7DD','\UA7DE','\UA7DF','\UA7E0','\UA7E1','\UA7E2','\UA7E3','\UA7E4','\UA7E5','\UA7E6','\UA7E7','\UA7E8','\UA7E9','\UA7EA','\UA7EB','\UA7EC','\UA7ED','\UA7EE','\UA7EF','\UA7F0','\UA7F1','\UA7F2','\UA7F3','\UA7F4','\UA7F5','\UA7F6','\UA7F7','\UA7F8','\UA7F9','\UA7FA','\UA7FB','\UA7FC','\UA7FD','\UA7FE','\UA7FF','\UA800','\UA801','\UA802','\UA803','\UA804','\UA805','\UA806','\UA807','\UA808','\UA809','\UA80A','\UA80B','\UA80C','\UA80D','\UA80E','\UA80F','\UA810','\UA811','\UA812','\UA813','\UA814','\UA815','\UA816','\UA817','\UA818','\UA819','\UA81A','\UA81B','\UA81C','\UA81D','\UA81E','\UA81F','\UA820','\UA821','\UA822','\UA823','\UA824','\UA825','\UA826','\UA827','\UA828','\UA829','\UA82A','\UA82B','\UA82C','\UA82D','\UA82E','\UA82F','\UA830','\UA831','\UA832','\UA833','\UA834','\UA835','\UA836','\UA837','\UA838','\UA839','\UA83A','\UA83B','\UA83C','\UA83D','\UA83E','\UA83F','\UA840','\UA841','\UA842','\UA843','\UA844','\UA845','\UA846','\UA847','\UA848','\UA849','\UA84A','\UA84B','\UA84C','\UA84D','\UA84E','\UA84F','\UA850','\UA851','\UA852','\UA853','\UA854','\UA855','\UA856','\UA857','\UA858','\UA859','\UA85A','\UA85B','\UA85C','\UA85D','\UA85E','\UA85F','\UA860','\UA861','\UA862','\UA863','\UA864','\UA865','\UA866','\UA867','\UA868','\UA869','\UA86A','\UA86B','\UA86C','\UA86D','\UA86E','\UA86F','\UA870','\UA871','\UA872','\UA873','\UA874','\UA875','\UA876','\UA877','\UA878','\UA879','\UA87A','\UA87B','\UA87C','\UA87D','\UA87E','\UA87F','\UA880','\UA881','\UA882','\UA883','\UA884','\UA885','\UA886','\UA887','\UA888','\UA889','\UA88A','\UA88B','\UA88C','\UA88D','\UA88E','\UA88F','\UA890','\UA891','\UA892','\UA893','\UA894','\UA895','\UA896','\UA897','\UA898','\UA899','\UA89A','\UA89B','\UA89C','\UA89D','\UA89E','\UA89F','\UA8A0','\UA8A1','\UA8A2','\UA8A3','\UA8A4','\UA8A5','\UA8A6','\UA8A7','\UA8A8','\UA8A9','\UA8AA','\UA8AB','\UA8AC','\UA8AD','\UA8AE','\UA8AF','\UA8B0','\UA8B1','\UA8B2','\UA8B3','\UA8B4','\UA8B5','\UA8B6','\UA8B7','\UA8B8','\UA8B9','\UA8BA','\UA8BB','\UA8BC','\UA8BD','\UA8BE','\UA8BF','\UA8C0','\UA8C1','\UA8C2','\UA8C3','\UA8C4','\UA8C5','\UA8C6','\UA8C7','\UA8C8','\UA8C9','\UA8CA','\UA8CB','\UA8CC','\UA8CD','\UA8CE','\UA8CF','\UA8D0','\UA8D1','\UA8D2','\UA8D3','\UA8D4','\UA8D5','\UA8D6','\UA8D7','\UA8D8','\UA8D9','\UA8DA','\UA8DB','\UA8DC','\UA8DD','\UA8DE','\UA8DF','\UA8E0','\UA8E1','\UA8E2','\UA8E3','\UA8E4','\UA8E5','\UA8E6','\UA8E7','\UA8E8','\UA8E9','\UA8EA','\UA8EB','\UA8EC','\UA8ED','\UA8EE','\UA8EF','\UA8F0','\UA8F1','\UA8F2','\UA8F3','\UA8F4','\UA8F5','\UA8F6','\UA8F7','\UA8F8','\UA8F9','\UA8FA','\UA8FB','\UA8FC','\UA8FD','\UA8FE','\UA8FF','\UA900','\UA901','\UA902','\UA903','\UA904','\UA905','\UA906','\UA907','\UA908','\UA909','\UA90A','\UA90B','\UA90C','\UA90D','\UA90E','\UA90F','\UA910','\UA911','\UA912','\UA913','\UA914','\UA915','\UA916','\UA917','\UA918','\UA919','\UA91A','\UA91B','\UA91C','\UA91D','\UA91E','\UA91F','\UA920','\UA921','\UA922','\UA923','\UA924','\UA925','\UA926','\UA927','\UA928','\UA929','\UA92A','\UA92B','\UA92C','\UA92D','\UA92E','\UA92F','\UA930','\UA931','\UA932','\UA933','\UA934','\UA935','\UA936','\UA937','\UA938','\UA939','\UA93A','\UA93B','\UA93C','\UA93D','\UA93E','\UA93F','\UA940','\UA941','\UA942','\UA943','\UA944','\UA945','\UA946','\UA947','\UA948','\UA949','\UA94A','\UA94B','\UA94C','\UA94D','\UA94E','\UA94F','\UA950','\UA951','\UA952','\UA953','\UA954','\UA955','\UA956','\UA957','\UA958','\UA959','\UA95A','\UA95B','\UA95C','\UA95D','\UA95E','\UA95F','\UA960','\UA961','\UA962','\UA963','\UA964','\UA965','\UA966','\UA967','\UA968','\UA969','\UA96A','\UA96B','\UA96C','\UA96D','\UA96E','\UA96F','\UA970','\UA971','\UA972','\UA973','\UA974','\UA975','\UA976','\UA977','\UA978','\UA979','\UA97A','\UA97B','\UA97C','\UA97D','\UA97E','\UA97F','\UA980','\UA981','\UA982','\UA983','\UA984','\UA985','\UA986','\UA987','\UA988','\UA989','\UA98A','\UA98B','\UA98C','\UA98D','\UA98E','\UA98F','\UA990','\UA991','\UA992','\UA993','\UA994','\UA995','\UA996','\UA997','\UA998','\UA999','\UA99A','\UA99B','\UA99C','\UA99D','\UA99E','\UA99F','\UA9A0','\UA9A1','\UA9A2','\UA9A3','\UA9A4','\UA9A5','\UA9A6','\UA9A7','\UA9A8','\UA9A9','\UA9AA','\UA9AB','\UA9AC','\UA9AD','\UA9AE','\UA9AF','\UA9B0','\UA9B1','\UA9B2','\UA9B3','\UA9B4','\UA9B5','\UA9B6','\UA9B7','\UA9B8','\UA9B9','\UA9BA','\UA9BB','\UA9BC','\UA9BD','\UA9BE','\UA9BF','\UA9C0','\UA9C1','\UA9C2','\UA9C3','\UA9C4','\UA9C5','\UA9C6','\UA9C7','\UA9C8','\UA9C9','\UA9CA','\UA9CB','\UA9CC','\UA9CD','\UA9CE','\UA9CF','\UA9D0','\UA9D1','\UA9D2','\UA9D3','\UA9D4','\UA9D5','\UA9D6','\UA9D7','\UA9D8','\UA9D9','\UA9DA','\UA9DB','\UA9DC','\UA9DD','\UA9DE','\UA9DF','\UA9E0','\UA9E1','\UA9E2','\UA9E3','\UA9E4','\UA9E5','\UA9E6','\UA9E7','\UA9E8','\UA9E9','\UA9EA','\UA9EB','\UA9EC','\UA9ED','\UA9EE','\UA9EF','\UA9F0','\UA9F1','\UA9F2','\UA9F3','\UA9F4','\UA9F5','\UA9F6','\UA9F7','\UA9F8','\UA9F9','\UA9FA','\UA9FB','\UA9FC','\UA9FD','\UA9FE','\UA9FF','\UAA00','\UAA01','\UAA02','\UAA03','\UAA04','\UAA05','\UAA06','\UAA07','\UAA08','\UAA09','\UAA0A','\UAA0B','\UAA0C','\UAA0D','\UAA0E','\UAA0F','\UAA10','\UAA11','\UAA12','\UAA13','\UAA14','\UAA15','\UAA16','\UAA17','\UAA18','\UAA19','\UAA1A','\UAA1B','\UAA1C','\UAA1D','\UAA1E','\UAA1F','\UAA20','\UAA21','\UAA22','\UAA23','\UAA24','\UAA25','\UAA26','\UAA27','\UAA28','\UAA29','\UAA2A','\UAA2B','\UAA2C','\UAA2D','\UAA2E','\UAA2F','\UAA30','\UAA31','\UAA32','\UAA33','\UAA34','\UAA35','\UAA36','\UAA37','\UAA38','\UAA39','\UAA3A','\UAA3B','\UAA3C','\UAA3D','\UAA3E','\UAA3F','\UAA40','\UAA41','\UAA42','\UAA43','\UAA44','\UAA45','\UAA46','\UAA47','\UAA48','\UAA49','\UAA4A','\UAA4B','\UAA4C','\UAA4D','\UAA4E','\UAA4F','\UAA50','\UAA51','\UAA52','\UAA53','\UAA54','\UAA55','\UAA56','\UAA57','\UAA58','\UAA59','\UAA5A','\UAA5B','\UAA5C','\UAA5D','\UAA5E','\UAA5F','\UAA60','\UAA61','\UAA62','\UAA63','\UAA64','\UAA65','\UAA66','\UAA67','\UAA68','\UAA69','\UAA6A','\UAA6B','\UAA6C','\UAA6D','\UAA6E','\UAA6F','\UAA70','\UAA71','\UAA72','\UAA73','\UAA74','\UAA75','\UAA76','\UAA77','\UAA78','\UAA79','\UAA7A','\UAA7B','\UAA7C','\UAA7D','\UAA7E','\UAA7F','\UAA80','\UAA81','\UAA82','\UAA83','\UAA84','\UAA85','\UAA86','\UAA87','\UAA88','\UAA89','\UAA8A','\UAA8B','\UAA8C','\UAA8D','\UAA8E','\UAA8F','\UAA90','\UAA91','\UAA92','\UAA93','\UAA94','\UAA95','\UAA96','\UAA97','\UAA98','\UAA99','\UAA9A','\UAA9B','\UAA9C','\UAA9D','\UAA9E','\UAA9F','\UAAA0','\UAAA1','\UAAA2','\UAAA3','\UAAA4','\UAAA5','\UAAA6','\UAAA7','\UAAA8','\UAAA9','\UAAAA','\UAAAB','\UAAAC','\UAAAD','\UAAAE','\UAAAF','\UAAB0','\UAAB1','\UAAB2','\UAAB3','\UAAB4','\UAAB5','\UAAB6','\UAAB7','\UAAB8','\UAAB9','\UAABA','\UAABB','\UAABC','\UAABD','\UAABE','\UAABF','\UAAC0','\UAAC1','\UAAC2','\UAAC3','\UAAC4','\UAAC5','\UAAC6','\UAAC7','\UAAC8','\UAAC9','\UAACA','\UAACB','\UAACC','\UAACD','\UAACE','\UAACF','\UAAD0','\UAAD1','\UAAD2','\UAAD3','\UAAD4','\UAAD5','\UAAD6','\UAAD7','\UAAD8','\UAAD9','\UAADA','\UAADB','\UAADC','\UAADD','\UAADE','\UAADF','\UAAE0','\UAAE1','\UAAE2','\UAAE3','\UAAE4','\UAAE5','\UAAE6','\UAAE7','\UAAE8','\UAAE9','\UAAEA','\UAAEB','\UAAEC','\UAAED','\UAAEE','\UAAEF','\UAAF0','\UAAF1','\UAAF2','\UAAF3','\UAAF4','\UAAF5','\UAAF6','\UAAF7','\UAAF8','\UAAF9','\UAAFA','\UAAFB','\UAAFC','\UAAFD','\UAAFE','\UAAFF','\UAB00','\UAB01','\UAB02','\UAB03','\UAB04','\UAB05','\UAB06','\UAB07','\UAB08','\UAB09','\UAB0A','\UAB0B','\UAB0C','\UAB0D','\UAB0E','\UAB0F','\UAB10','\UAB11','\UAB12','\UAB13','\UAB14','\UAB15','\UAB16','\UAB17','\UAB18','\UAB19','\UAB1A','\UAB1B','\UAB1C','\UAB1D','\UAB1E','\UAB1F','\UAB20','\UAB21','\UAB22','\UAB23','\UAB24','\UAB25','\UAB26','\UAB27','\UAB28','\UAB29','\UAB2A','\UAB2B','\UAB2C','\UAB2D','\UAB2E','\UAB2F','\UAB30','\UAB31','\UAB32','\UAB33','\UAB34','\UAB35','\UAB36','\UAB37','\UAB38','\UAB39','\UAB3A','\UAB3B','\UAB3C','\UAB3D','\UAB3E','\UAB3F','\UAB40','\UAB41','\UAB42','\UAB43','\UAB44','\UAB45','\UAB46','\UAB47','\UAB48','\UAB49','\UAB4A','\UAB4B','\UAB4C','\UAB4D','\UAB4E','\UAB4F','\UAB50','\UAB51','\UAB52','\UAB53','\UAB54','\UAB55','\UAB56','\UAB57','\UAB58','\UAB59','\UAB5A','\UAB5B','\UAB5C','\UAB5D','\UAB5E','\UAB5F','\UAB60','\UAB61','\UAB62','\UAB63','\UAB64','\UAB65','\UAB66','\UAB67','\UAB68','\UAB69','\UAB6A','\UAB6B','\UAB6C','\UAB6D','\UAB6E','\UAB6F','\UAB70','\UAB71','\UAB72','\UAB73','\UAB74','\UAB75','\UAB76','\UAB77','\UAB78','\UAB79','\UAB7A','\UAB7B','\UAB7C','\UAB7D','\UAB7E','\UAB7F','\UAB80','\UAB81','\UAB82','\UAB83','\UAB84','\UAB85','\UAB86','\UAB87','\UAB88','\UAB89','\UAB8A','\UAB8B','\UAB8C','\UAB8D','\UAB8E','\UAB8F','\UAB90','\UAB91','\UAB92','\UAB93','\UAB94','\UAB95','\UAB96','\UAB97','\UAB98','\UAB99','\UAB9A','\UAB9B','\UAB9C','\UAB9D','\UAB9E','\UAB9F','\UABA0','\UABA1','\UABA2','\UABA3','\UABA4','\UABA5','\UABA6','\UABA7','\UABA8','\UABA9','\UABAA','\UABAB','\UABAC','\UABAD','\UABAE','\UABAF','\UABB0','\UABB1','\UABB2','\UABB3','\UABB4','\UABB5','\UABB6','\UABB7','\UABB8','\UABB9','\UABBA','\UABBB','\UABBC','\UABBD','\UABBE','\UABBF','\UABC0','\UABC1','\UABC2','\UABC3','\UABC4','\UABC5','\UABC6','\UABC7','\UABC8','\UABC9','\UABCA','\UABCB','\UABCC','\UABCD','\UABCE','\UABCF','\UABD0','\UABD1','\UABD2','\UABD3','\UABD4','\UABD5','\UABD6','\UABD7','\UABD8','\UABD9','\UABDA','\UABDB','\UABDC','\UABDD','\UABDE','\UABDF','\UABE0','\UABE1','\UABE2','\UABE3','\UABE4','\UABE5','\UABE6','\UABE7','\UABE8','\UABE9','\UABEA','\UABEB','\UABEC','\UABED','\UABEE','\UABEF','\UABF0','\UABF1','\UABF2','\UABF3','\UABF4','\UABF5','\UABF6','\UABF7','\UABF8','\UABF9','\UABFA','\UABFB','\UABFC','\UABFD','\UABFE','\UABFF','\UAC00','\UAC01','\UAC02','\UAC03','\UAC04','\UAC05','\UAC06','\UAC07','\UAC08','\UAC09','\UAC0A','\UAC0B','\UAC0C','\UAC0D','\UAC0E','\UAC0F','\UAC10','\UAC11','\UAC12','\UAC13','\UAC14','\UAC15','\UAC16','\UAC17','\UAC18','\UAC19','\UAC1A','\UAC1B','\UAC1C','\UAC1D','\UAC1E','\UAC1F','\UAC20','\UAC21','\UAC22','\UAC23','\UAC24','\UAC25','\UAC26','\UAC27','\UAC28','\UAC29','\UAC2A','\UAC2B','\UAC2C','\UAC2D','\UAC2E','\UAC2F','\UAC30','\UAC31','\UAC32','\UAC33','\UAC34','\UAC35','\UAC36','\UAC37','\UAC38','\UAC39','\UAC3A','\UAC3B','\UAC3C','\UAC3D','\UAC3E','\UAC3F','\UAC40','\UAC41','\UAC42','\UAC43','\UAC44','\UAC45','\UAC46','\UAC47','\UAC48','\UAC49','\UAC4A','\UAC4B','\UAC4C','\UAC4D','\UAC4E','\UAC4F','\UAC50','\UAC51','\UAC52','\UAC53','\UAC54','\UAC55','\UAC56','\UAC57','\UAC58','\UAC59','\UAC5A','\UAC5B','\UAC5C','\UAC5D','\UAC5E','\UAC5F','\UAC60','\UAC61','\UAC62','\UAC63','\UAC64','\UAC65','\UAC66','\UAC67','\UAC68','\UAC69','\UAC6A','\UAC6B','\UAC6C','\UAC6D','\UAC6E','\UAC6F','\UAC70','\UAC71','\UAC72','\UAC73','\UAC74','\UAC75','\UAC76','\UAC77','\UAC78','\UAC79','\UAC7A','\UAC7B','\UAC7C','\UAC7D','\UAC7E','\UAC7F','\UAC80','\UAC81','\UAC82','\UAC83','\UAC84','\UAC85','\UAC86','\UAC87','\UAC88','\UAC89','\UAC8A','\UAC8B','\UAC8C','\UAC8D','\UAC8E','\UAC8F','\UAC90','\UAC91','\UAC92','\UAC93','\UAC94','\UAC95','\UAC96','\UAC97','\UAC98','\UAC99','\UAC9A','\UAC9B','\UAC9C','\UAC9D','\UAC9E','\UAC9F','\UACA0','\UACA1','\UACA2','\UACA3','\UACA4','\UACA5','\UACA6','\UACA7','\UACA8','\UACA9','\UACAA','\UACAB','\UACAC','\UACAD','\UACAE','\UACAF','\UACB0','\UACB1','\UACB2','\UACB3','\UACB4','\UACB5','\UACB6','\UACB7','\UACB8','\UACB9','\UACBA','\UACBB','\UACBC','\UACBD','\UACBE','\UACBF','\UACC0','\UACC1','\UACC2','\UACC3','\UACC4','\UACC5','\UACC6','\UACC7','\UACC8','\UACC9','\UACCA','\UACCB','\UACCC','\UACCD','\UACCE','\UACCF','\UACD0','\UACD1','\UACD2','\UACD3','\UACD4','\UACD5','\UACD6','\UACD7','\UACD8','\UACD9','\UACDA','\UACDB','\UACDC','\UACDD','\UACDE','\UACDF','\UACE0','\UACE1','\UACE2','\UACE3','\UACE4','\UACE5','\UACE6','\UACE7','\UACE8','\UACE9','\UACEA','\UACEB','\UACEC','\UACED','\UACEE','\UACEF','\UACF0','\UACF1','\UACF2','\UACF3','\UACF4','\UACF5','\UACF6','\UACF7','\UACF8','\UACF9','\UACFA','\UACFB','\UACFC','\UACFD','\UACFE','\UACFF','\UAD00','\UAD01','\UAD02','\UAD03','\UAD04','\UAD05','\UAD06','\UAD07','\UAD08','\UAD09','\UAD0A','\UAD0B','\UAD0C','\UAD0D','\UAD0E','\UAD0F','\UAD10','\UAD11','\UAD12','\UAD13','\UAD14','\UAD15','\UAD16','\UAD17','\UAD18','\UAD19','\UAD1A','\UAD1B','\UAD1C','\UAD1D','\UAD1E','\UAD1F','\UAD20','\UAD21','\UAD22','\UAD23','\UAD24','\UAD25','\UAD26','\UAD27','\UAD28','\UAD29','\UAD2A','\UAD2B','\UAD2C','\UAD2D','\UAD2E','\UAD2F','\UAD30','\UAD31','\UAD32','\UAD33','\UAD34','\UAD35','\UAD36','\UAD37','\UAD38','\UAD39','\UAD3A','\UAD3B','\UAD3C','\UAD3D','\UAD3E','\UAD3F','\UAD40','\UAD41','\UAD42','\UAD43','\UAD44','\UAD45','\UAD46','\UAD47','\UAD48','\UAD49','\UAD4A','\UAD4B','\UAD4C','\UAD4D','\UAD4E','\UAD4F','\UAD50','\UAD51','\UAD52','\UAD53','\UAD54','\UAD55','\UAD56','\UAD57','\UAD58','\UAD59','\UAD5A','\UAD5B','\UAD5C','\UAD5D','\UAD5E','\UAD5F','\UAD60','\UAD61','\UAD62','\UAD63','\UAD64','\UAD65','\UAD66','\UAD67','\UAD68','\UAD69','\UAD6A','\UAD6B','\UAD6C','\UAD6D','\UAD6E','\UAD6F','\UAD70','\UAD71','\UAD72','\UAD73','\UAD74','\UAD75','\UAD76','\UAD77','\UAD78','\UAD79','\UAD7A','\UAD7B','\UAD7C','\UAD7D','\UAD7E','\UAD7F','\UAD80','\UAD81','\UAD82','\UAD83','\UAD84','\UAD85','\UAD86','\UAD87','\UAD88','\UAD89','\UAD8A','\UAD8B','\UAD8C','\UAD8D','\UAD8E','\UAD8F','\UAD90','\UAD91','\UAD92','\UAD93','\UAD94','\UAD95','\UAD96','\UAD97','\UAD98','\UAD99','\UAD9A','\UAD9B','\UAD9C','\UAD9D','\UAD9E','\UAD9F','\UADA0','\UADA1','\UADA2','\UADA3','\UADA4','\UADA5','\UADA6','\UADA7','\UADA8','\UADA9','\UADAA','\UADAB','\UADAC','\UADAD','\UADAE','\UADAF','\UADB0','\UADB1','\UADB2','\UADB3','\UADB4','\UADB5','\UADB6','\UADB7','\UADB8','\UADB9','\UADBA','\UADBB','\UADBC','\UADBD','\UADBE','\UADBF','\UADC0','\UADC1','\UADC2','\UADC3','\UADC4','\UADC5','\UADC6','\UADC7','\UADC8','\UADC9','\UADCA','\UADCB','\UADCC','\UADCD','\UADCE','\UADCF','\UADD0','\UADD1','\UADD2','\UADD3','\UADD4','\UADD5','\UADD6','\UADD7','\UADD8','\UADD9','\UADDA','\UADDB','\UADDC','\UADDD','\UADDE','\UADDF','\UADE0','\UADE1','\UADE2','\UADE3','\UADE4','\UADE5','\UADE6','\UADE7','\UADE8','\UADE9','\UADEA','\UADEB','\UADEC','\UADED','\UADEE','\UADEF','\UADF0','\UADF1','\UADF2','\UADF3','\UADF4','\UADF5','\UADF6','\UADF7','\UADF8','\UADF9','\UADFA','\UADFB','\UADFC','\UADFD','\UADFE','\UADFF','\UAE00','\UAE01','\UAE02','\UAE03','\UAE04','\UAE05','\UAE06','\UAE07','\UAE08','\UAE09','\UAE0A','\UAE0B','\UAE0C','\UAE0D','\UAE0E','\UAE0F','\UAE10','\UAE11','\UAE12','\UAE13','\UAE14','\UAE15','\UAE16','\UAE17','\UAE18','\UAE19','\UAE1A','\UAE1B','\UAE1C','\UAE1D','\UAE1E','\UAE1F','\UAE20','\UAE21','\UAE22','\UAE23','\UAE24','\UAE25','\UAE26','\UAE27','\UAE28','\UAE29','\UAE2A','\UAE2B','\UAE2C','\UAE2D','\UAE2E','\UAE2F','\UAE30','\UAE31','\UAE32','\UAE33','\UAE34','\UAE35','\UAE36','\UAE37','\UAE38','\UAE39','\UAE3A','\UAE3B','\UAE3C','\UAE3D','\UAE3E','\UAE3F','\UAE40','\UAE41','\UAE42','\UAE43','\UAE44','\UAE45','\UAE46','\UAE47','\UAE48','\UAE49','\UAE4A','\UAE4B','\UAE4C','\UAE4D','\UAE4E','\UAE4F','\UAE50','\UAE51','\UAE52','\UAE53','\UAE54','\UAE55','\UAE56','\UAE57','\UAE58','\UAE59','\UAE5A','\UAE5B','\UAE5C','\UAE5D','\UAE5E','\UAE5F','\UAE60','\UAE61','\UAE62','\UAE63','\UAE64','\UAE65','\UAE66','\UAE67','\UAE68','\UAE69','\UAE6A','\UAE6B','\UAE6C','\UAE6D','\UAE6E','\UAE6F','\UAE70','\UAE71','\UAE72','\UAE73','\UAE74','\UAE75','\UAE76','\UAE77','\UAE78','\UAE79','\UAE7A','\UAE7B','\UAE7C','\UAE7D','\UAE7E','\UAE7F','\UAE80','\UAE81','\UAE82','\UAE83','\UAE84','\UAE85','\UAE86','\UAE87','\UAE88','\UAE89','\UAE8A','\UAE8B','\UAE8C','\UAE8D','\UAE8E','\UAE8F','\UAE90','\UAE91','\UAE92','\UAE93','\UAE94','\UAE95','\UAE96','\UAE97','\UAE98','\UAE99','\UAE9A','\UAE9B','\UAE9C','\UAE9D','\UAE9E','\UAE9F','\UAEA0','\UAEA1','\UAEA2','\UAEA3','\UAEA4','\UAEA5','\UAEA6','\UAEA7','\UAEA8','\UAEA9','\UAEAA','\UAEAB','\UAEAC','\UAEAD','\UAEAE','\UAEAF','\UAEB0','\UAEB1','\UAEB2','\UAEB3','\UAEB4','\UAEB5','\UAEB6','\UAEB7','\UAEB8','\UAEB9','\UAEBA','\UAEBB','\UAEBC','\UAEBD','\UAEBE','\UAEBF','\UAEC0','\UAEC1','\UAEC2','\UAEC3','\UAEC4','\UAEC5','\UAEC6','\UAEC7','\UAEC8','\UAEC9','\UAECA','\UAECB','\UAECC','\UAECD','\UAECE','\UAECF','\UAED0','\UAED1','\UAED2','\UAED3','\UAED4','\UAED5','\UAED6','\UAED7','\UAED8','\UAED9','\UAEDA','\UAEDB','\UAEDC','\UAEDD','\UAEDE','\UAEDF','\UAEE0','\UAEE1','\UAEE2','\UAEE3','\UAEE4','\UAEE5','\UAEE6','\UAEE7','\UAEE8','\UAEE9','\UAEEA','\UAEEB','\UAEEC','\UAEED','\UAEEE','\UAEEF','\UAEF0','\UAEF1','\UAEF2','\UAEF3','\UAEF4','\UAEF5','\UAEF6','\UAEF7','\UAEF8','\UAEF9','\UAEFA','\UAEFB','\UAEFC','\UAEFD','\UAEFE','\UAEFF','\UAF00','\UAF01','\UAF02','\UAF03','\UAF04','\UAF05','\UAF06','\UAF07','\UAF08','\UAF09','\UAF0A','\UAF0B','\UAF0C','\UAF0D','\UAF0E','\UAF0F','\UAF10','\UAF11','\UAF12','\UAF13','\UAF14','\UAF15','\UAF16','\UAF17','\UAF18','\UAF19','\UAF1A','\UAF1B','\UAF1C','\UAF1D','\UAF1E','\UAF1F','\UAF20','\UAF21','\UAF22','\UAF23','\UAF24','\UAF25','\UAF26','\UAF27','\UAF28','\UAF29','\UAF2A','\UAF2B','\UAF2C','\UAF2D','\UAF2E','\UAF2F','\UAF30','\UAF31','\UAF32','\UAF33','\UAF34','\UAF35','\UAF36','\UAF37','\UAF38','\UAF39','\UAF3A','\UAF3B','\UAF3C','\UAF3D','\UAF3E','\UAF3F','\UAF40','\UAF41','\UAF42','\UAF43','\UAF44','\UAF45','\UAF46','\UAF47','\UAF48','\UAF49','\UAF4A','\UAF4B','\UAF4C','\UAF4D','\UAF4E','\UAF4F','\UAF50','\UAF51','\UAF52','\UAF53','\UAF54','\UAF55','\UAF56','\UAF57','\UAF58','\UAF59','\UAF5A','\UAF5B','\UAF5C','\UAF5D','\UAF5E','\UAF5F','\UAF60','\UAF61','\UAF62','\UAF63','\UAF64','\UAF65','\UAF66','\UAF67','\UAF68','\UAF69','\UAF6A','\UAF6B','\UAF6C','\UAF6D','\UAF6E','\UAF6F','\UAF70','\UAF71','\UAF72','\UAF73','\UAF74','\UAF75','\UAF76','\UAF77','\UAF78','\UAF79','\UAF7A','\UAF7B','\UAF7C','\UAF7D','\UAF7E','\UAF7F','\UAF80','\UAF81','\UAF82','\UAF83','\UAF84','\UAF85','\UAF86','\UAF87','\UAF88','\UAF89','\UAF8A','\UAF8B','\UAF8C','\UAF8D','\UAF8E','\UAF8F','\UAF90','\UAF91','\UAF92','\UAF93','\UAF94','\UAF95','\UAF96','\UAF97','\UAF98','\UAF99','\UAF9A','\UAF9B','\UAF9C','\UAF9D','\UAF9E','\UAF9F','\UAFA0','\UAFA1','\UAFA2','\UAFA3','\UAFA4','\UAFA5','\UAFA6','\UAFA7','\UAFA8','\UAFA9','\UAFAA','\UAFAB','\UAFAC','\UAFAD','\UAFAE','\UAFAF','\UAFB0','\UAFB1','\UAFB2','\UAFB3','\UAFB4','\UAFB5','\UAFB6','\UAFB7','\UAFB8','\UAFB9','\UAFBA','\UAFBB','\UAFBC','\UAFBD','\UAFBE','\UAFBF','\UAFC0','\UAFC1','\UAFC2','\UAFC3','\UAFC4','\UAFC5','\UAFC6','\UAFC7','\UAFC8','\UAFC9','\UAFCA','\UAFCB','\UAFCC','\UAFCD','\UAFCE','\UAFCF','\UAFD0','\UAFD1','\UAFD2','\UAFD3','\UAFD4','\UAFD5','\UAFD6','\UAFD7','\UAFD8','\UAFD9','\UAFDA','\UAFDB','\UAFDC','\UAFDD','\UAFDE','\UAFDF','\UAFE0','\UAFE1','\UAFE2','\UAFE3','\UAFE4','\UAFE5','\UAFE6','\UAFE7','\UAFE8','\UAFE9','\UAFEA','\UAFEB','\UAFEC','\UAFED','\UAFEE','\UAFEF','\UAFF0','\UAFF1','\UAFF2','\UAFF3','\UAFF4','\UAFF5','\UAFF6','\UAFF7','\UAFF8','\UAFF9','\UAFFA','\UAFFB','\UAFFC','\UAFFD','\UAFFE','\UAFFF','\UB000','\UB001','\UB002','\UB003','\UB004','\UB005','\UB006','\UB007','\UB008','\UB009','\UB00A','\UB00B','\UB00C','\UB00D','\UB00E','\UB00F','\UB010','\UB011','\UB012','\UB013','\UB014','\UB015','\UB016','\UB017','\UB018','\UB019','\UB01A','\UB01B','\UB01C','\UB01D','\UB01E','\UB01F','\UB020','\UB021','\UB022','\UB023','\UB024','\UB025','\UB026','\UB027','\UB028','\UB029','\UB02A','\UB02B','\UB02C','\UB02D','\UB02E','\UB02F','\UB030','\UB031','\UB032','\UB033','\UB034','\UB035','\UB036','\UB037','\UB038','\UB039','\UB03A','\UB03B','\UB03C','\UB03D','\UB03E','\UB03F','\UB040','\UB041','\UB042','\UB043','\UB044','\UB045','\UB046','\UB047','\UB048','\UB049','\UB04A','\UB04B','\UB04C','\UB04D','\UB04E','\UB04F','\UB050','\UB051','\UB052','\UB053','\UB054','\UB055','\UB056','\UB057','\UB058','\UB059','\UB05A','\UB05B','\UB05C','\UB05D','\UB05E','\UB05F','\UB060','\UB061','\UB062','\UB063','\UB064','\UB065','\UB066','\UB067','\UB068','\UB069','\UB06A','\UB06B','\UB06C','\UB06D','\UB06E','\UB06F','\UB070','\UB071','\UB072','\UB073','\UB074','\UB075','\UB076','\UB077','\UB078','\UB079','\UB07A','\UB07B','\UB07C','\UB07D','\UB07E','\UB07F','\UB080','\UB081','\UB082','\UB083','\UB084','\UB085','\UB086','\UB087','\UB088','\UB089','\UB08A','\UB08B','\UB08C','\UB08D','\UB08E','\UB08F','\UB090','\UB091','\UB092','\UB093','\UB094','\UB095','\UB096','\UB097','\UB098','\UB099','\UB09A','\UB09B','\UB09C','\UB09D','\UB09E','\UB09F','\UB0A0','\UB0A1','\UB0A2','\UB0A3','\UB0A4','\UB0A5','\UB0A6','\UB0A7','\UB0A8','\UB0A9','\UB0AA','\UB0AB','\UB0AC','\UB0AD','\UB0AE','\UB0AF','\UB0B0','\UB0B1','\UB0B2','\UB0B3','\UB0B4','\UB0B5','\UB0B6','\UB0B7','\UB0B8','\UB0B9','\UB0BA','\UB0BB','\UB0BC','\UB0BD','\UB0BE','\UB0BF','\UB0C0','\UB0C1','\UB0C2','\UB0C3','\UB0C4','\UB0C5','\UB0C6','\UB0C7','\UB0C8','\UB0C9','\UB0CA','\UB0CB','\UB0CC','\UB0CD','\UB0CE','\UB0CF','\UB0D0','\UB0D1','\UB0D2','\UB0D3','\UB0D4','\UB0D5','\UB0D6','\UB0D7','\UB0D8','\UB0D9','\UB0DA','\UB0DB','\UB0DC','\UB0DD','\UB0DE','\UB0DF','\UB0E0','\UB0E1','\UB0E2','\UB0E3','\UB0E4','\UB0E5','\UB0E6','\UB0E7','\UB0E8','\UB0E9','\UB0EA','\UB0EB','\UB0EC','\UB0ED','\UB0EE','\UB0EF','\UB0F0','\UB0F1','\UB0F2','\UB0F3','\UB0F4','\UB0F5','\UB0F6','\UB0F7','\UB0F8','\UB0F9','\UB0FA','\UB0FB','\UB0FC','\UB0FD','\UB0FE','\UB0FF','\UB100','\UB101','\UB102','\UB103','\UB104','\UB105','\UB106','\UB107','\UB108','\UB109','\UB10A','\UB10B','\UB10C','\UB10D','\UB10E','\UB10F','\UB110','\UB111','\UB112','\UB113','\UB114','\UB115','\UB116','\UB117','\UB118','\UB119','\UB11A','\UB11B','\UB11C','\UB11D','\UB11E','\UB11F','\UB120','\UB121','\UB122','\UB123','\UB124','\UB125','\UB126','\UB127','\UB128','\UB129','\UB12A','\UB12B','\UB12C','\UB12D','\UB12E','\UB12F','\UB130','\UB131','\UB132','\UB133','\UB134','\UB135','\UB136','\UB137','\UB138','\UB139','\UB13A','\UB13B','\UB13C','\UB13D','\UB13E','\UB13F','\UB140','\UB141','\UB142','\UB143','\UB144','\UB145','\UB146','\UB147','\UB148','\UB149','\UB14A','\UB14B','\UB14C','\UB14D','\UB14E','\UB14F','\UB150','\UB151','\UB152','\UB153','\UB154','\UB155','\UB156','\UB157','\UB158','\UB159','\UB15A','\UB15B','\UB15C','\UB15D','\UB15E','\UB15F','\UB160','\UB161','\UB162','\UB163','\UB164','\UB165','\UB166','\UB167','\UB168','\UB169','\UB16A','\UB16B','\UB16C','\UB16D','\UB16E','\UB16F','\UB170','\UB171','\UB172','\UB173','\UB174','\UB175','\UB176','\UB177','\UB178','\UB179','\UB17A','\UB17B','\UB17C','\UB17D','\UB17E','\UB17F','\UB180','\UB181','\UB182','\UB183','\UB184','\UB185','\UB186','\UB187','\UB188','\UB189','\UB18A','\UB18B','\UB18C','\UB18D','\UB18E','\UB18F','\UB190','\UB191','\UB192','\UB193','\UB194','\UB195','\UB196','\UB197','\UB198','\UB199','\UB19A','\UB19B','\UB19C','\UB19D','\UB19E','\UB19F','\UB1A0','\UB1A1','\UB1A2','\UB1A3','\UB1A4','\UB1A5','\UB1A6','\UB1A7','\UB1A8','\UB1A9','\UB1AA','\UB1AB','\UB1AC','\UB1AD','\UB1AE','\UB1AF','\UB1B0','\UB1B1','\UB1B2','\UB1B3','\UB1B4','\UB1B5','\UB1B6','\UB1B7','\UB1B8','\UB1B9','\UB1BA','\UB1BB','\UB1BC','\UB1BD','\UB1BE','\UB1BF','\UB1C0','\UB1C1','\UB1C2','\UB1C3','\UB1C4','\UB1C5','\UB1C6','\UB1C7','\UB1C8','\UB1C9','\UB1CA','\UB1CB','\UB1CC','\UB1CD','\UB1CE','\UB1CF','\UB1D0','\UB1D1','\UB1D2','\UB1D3','\UB1D4','\UB1D5','\UB1D6','\UB1D7','\UB1D8','\UB1D9','\UB1DA','\UB1DB','\UB1DC','\UB1DD','\UB1DE','\UB1DF','\UB1E0','\UB1E1','\UB1E2','\UB1E3','\UB1E4','\UB1E5','\UB1E6','\UB1E7','\UB1E8','\UB1E9','\UB1EA','\UB1EB','\UB1EC','\UB1ED','\UB1EE','\UB1EF','\UB1F0','\UB1F1','\UB1F2','\UB1F3','\UB1F4','\UB1F5','\UB1F6','\UB1F7','\UB1F8','\UB1F9','\UB1FA','\UB1FB','\UB1FC','\UB1FD','\UB1FE','\UB1FF','\UB200','\UB201','\UB202','\UB203','\UB204','\UB205','\UB206','\UB207','\UB208','\UB209','\UB20A','\UB20B','\UB20C','\UB20D','\UB20E','\UB20F','\UB210','\UB211','\UB212','\UB213','\UB214','\UB215','\UB216','\UB217','\UB218','\UB219','\UB21A','\UB21B','\UB21C','\UB21D','\UB21E','\UB21F','\UB220','\UB221','\UB222','\UB223','\UB224','\UB225','\UB226','\UB227','\UB228','\UB229','\UB22A','\UB22B','\UB22C','\UB22D','\UB22E','\UB22F','\UB230','\UB231','\UB232','\UB233','\UB234','\UB235','\UB236','\UB237','\UB238','\UB239','\UB23A','\UB23B','\UB23C','\UB23D','\UB23E','\UB23F','\UB240','\UB241','\UB242','\UB243','\UB244','\UB245','\UB246','\UB247','\UB248','\UB249','\UB24A','\UB24B','\UB24C','\UB24D','\UB24E','\UB24F','\UB250','\UB251','\UB252','\UB253','\UB254','\UB255','\UB256','\UB257','\UB258','\UB259','\UB25A','\UB25B','\UB25C','\UB25D','\UB25E','\UB25F','\UB260','\UB261','\UB262','\UB263','\UB264','\UB265','\UB266','\UB267','\UB268','\UB269','\UB26A','\UB26B','\UB26C','\UB26D','\UB26E','\UB26F','\UB270','\UB271','\UB272','\UB273','\UB274','\UB275','\UB276','\UB277','\UB278','\UB279','\UB27A','\UB27B','\UB27C','\UB27D','\UB27E','\UB27F','\UB280','\UB281','\UB282','\UB283','\UB284','\UB285','\UB286','\UB287','\UB288','\UB289','\UB28A','\UB28B','\UB28C','\UB28D','\UB28E','\UB28F','\UB290','\UB291','\UB292','\UB293','\UB294','\UB295','\UB296','\UB297','\UB298','\UB299','\UB29A','\UB29B','\UB29C','\UB29D','\UB29E','\UB29F','\UB2A0','\UB2A1','\UB2A2','\UB2A3','\UB2A4','\UB2A5','\UB2A6','\UB2A7','\UB2A8','\UB2A9','\UB2AA','\UB2AB','\UB2AC','\UB2AD','\UB2AE','\UB2AF','\UB2B0','\UB2B1','\UB2B2','\UB2B3','\UB2B4','\UB2B5','\UB2B6','\UB2B7','\UB2B8','\UB2B9','\UB2BA','\UB2BB','\UB2BC','\UB2BD','\UB2BE','\UB2BF','\UB2C0','\UB2C1','\UB2C2','\UB2C3','\UB2C4','\UB2C5','\UB2C6','\UB2C7','\UB2C8','\UB2C9','\UB2CA','\UB2CB','\UB2CC','\UB2CD','\UB2CE','\UB2CF','\UB2D0','\UB2D1','\UB2D2','\UB2D3','\UB2D4','\UB2D5','\UB2D6','\UB2D7','\UB2D8','\UB2D9','\UB2DA','\UB2DB','\UB2DC','\UB2DD','\UB2DE','\UB2DF','\UB2E0','\UB2E1','\UB2E2','\UB2E3','\UB2E4','\UB2E5','\UB2E6','\UB2E7','\UB2E8','\UB2E9','\UB2EA','\UB2EB','\UB2EC','\UB2ED','\UB2EE','\UB2EF','\UB2F0','\UB2F1','\UB2F2','\UB2F3','\UB2F4','\UB2F5','\UB2F6','\UB2F7','\UB2F8','\UB2F9','\UB2FA','\UB2FB','\UB2FC','\UB2FD','\UB2FE','\UB2FF','\UB300','\UB301','\UB302','\UB303','\UB304','\UB305','\UB306','\UB307','\UB308','\UB309','\UB30A','\UB30B','\UB30C','\UB30D','\UB30E','\UB30F','\UB310','\UB311','\UB312','\UB313','\UB314','\UB315','\UB316','\UB317','\UB318','\UB319','\UB31A','\UB31B','\UB31C','\UB31D','\UB31E','\UB31F','\UB320','\UB321','\UB322','\UB323','\UB324','\UB325','\UB326','\UB327','\UB328','\UB329','\UB32A','\UB32B','\UB32C','\UB32D','\UB32E','\UB32F','\UB330','\UB331','\UB332','\UB333','\UB334','\UB335','\UB336','\UB337','\UB338','\UB339','\UB33A','\UB33B','\UB33C','\UB33D','\UB33E','\UB33F','\UB340','\UB341','\UB342','\UB343','\UB344','\UB345','\UB346','\UB347','\UB348','\UB349','\UB34A','\UB34B','\UB34C','\UB34D','\UB34E','\UB34F','\UB350','\UB351','\UB352','\UB353','\UB354','\UB355','\UB356','\UB357','\UB358','\UB359','\UB35A','\UB35B','\UB35C','\UB35D','\UB35E','\UB35F','\UB360','\UB361','\UB362','\UB363','\UB364','\UB365','\UB366','\UB367','\UB368','\UB369','\UB36A','\UB36B','\UB36C','\UB36D','\UB36E','\UB36F','\UB370','\UB371','\UB372','\UB373','\UB374','\UB375','\UB376','\UB377','\UB378','\UB379','\UB37A','\UB37B','\UB37C','\UB37D','\UB37E','\UB37F','\UB380','\UB381','\UB382','\UB383','\UB384','\UB385','\UB386','\UB387','\UB388','\UB389','\UB38A','\UB38B','\UB38C','\UB38D','\UB38E','\UB38F','\UB390','\UB391','\UB392','\UB393','\UB394','\UB395','\UB396','\UB397','\UB398','\UB399','\UB39A','\UB39B','\UB39C','\UB39D','\UB39E','\UB39F','\UB3A0','\UB3A1','\UB3A2','\UB3A3','\UB3A4','\UB3A5','\UB3A6','\UB3A7','\UB3A8','\UB3A9','\UB3AA','\UB3AB','\UB3AC','\UB3AD','\UB3AE','\UB3AF','\UB3B0','\UB3B1','\UB3B2','\UB3B3','\UB3B4','\UB3B5','\UB3B6','\UB3B7','\UB3B8','\UB3B9','\UB3BA','\UB3BB','\UB3BC','\UB3BD','\UB3BE','\UB3BF','\UB3C0','\UB3C1','\UB3C2','\UB3C3','\UB3C4','\UB3C5','\UB3C6','\UB3C7','\UB3C8','\UB3C9','\UB3CA','\UB3CB','\UB3CC','\UB3CD','\UB3CE','\UB3CF','\UB3D0','\UB3D1','\UB3D2','\UB3D3','\UB3D4','\UB3D5','\UB3D6','\UB3D7','\UB3D8','\UB3D9','\UB3DA','\UB3DB','\UB3DC','\UB3DD','\UB3DE','\UB3DF','\UB3E0','\UB3E1','\UB3E2','\UB3E3','\UB3E4','\UB3E5','\UB3E6','\UB3E7','\UB3E8','\UB3E9','\UB3EA','\UB3EB','\UB3EC','\UB3ED','\UB3EE','\UB3EF','\UB3F0','\UB3F1','\UB3F2','\UB3F3','\UB3F4','\UB3F5','\UB3F6','\UB3F7','\UB3F8','\UB3F9','\UB3FA','\UB3FB','\UB3FC','\UB3FD','\UB3FE','\UB3FF','\UB400','\UB401','\UB402','\UB403','\UB404','\UB405','\UB406','\UB407','\UB408','\UB409','\UB40A','\UB40B','\UB40C','\UB40D','\UB40E','\UB40F','\UB410','\UB411','\UB412','\UB413','\UB414','\UB415','\UB416','\UB417','\UB418','\UB419','\UB41A','\UB41B','\UB41C','\UB41D','\UB41E','\UB41F','\UB420','\UB421','\UB422','\UB423','\UB424','\UB425','\UB426','\UB427','\UB428','\UB429','\UB42A','\UB42B','\UB42C','\UB42D','\UB42E','\UB42F','\UB430','\UB431','\UB432','\UB433','\UB434','\UB435','\UB436','\UB437','\UB438','\UB439','\UB43A','\UB43B','\UB43C','\UB43D','\UB43E','\UB43F','\UB440','\UB441','\UB442','\UB443','\UB444','\UB445','\UB446','\UB447','\UB448','\UB449','\UB44A','\UB44B','\UB44C','\UB44D','\UB44E','\UB44F','\UB450','\UB451','\UB452','\UB453','\UB454','\UB455','\UB456','\UB457','\UB458','\UB459','\UB45A','\UB45B','\UB45C','\UB45D','\UB45E','\UB45F','\UB460','\UB461','\UB462','\UB463','\UB464','\UB465','\UB466','\UB467','\UB468','\UB469','\UB46A','\UB46B','\UB46C','\UB46D','\UB46E','\UB46F','\UB470','\UB471','\UB472','\UB473','\UB474','\UB475','\UB476','\UB477','\UB478','\UB479','\UB47A','\UB47B','\UB47C','\UB47D','\UB47E','\UB47F','\UB480','\UB481','\UB482','\UB483','\UB484','\UB485','\UB486','\UB487','\UB488','\UB489','\UB48A','\UB48B','\UB48C','\UB48D','\UB48E','\UB48F','\UB490','\UB491','\UB492','\UB493','\UB494','\UB495','\UB496','\UB497','\UB498','\UB499','\UB49A','\UB49B','\UB49C','\UB49D','\UB49E','\UB49F','\UB4A0','\UB4A1','\UB4A2','\UB4A3','\UB4A4','\UB4A5','\UB4A6','\UB4A7','\UB4A8','\UB4A9','\UB4AA','\UB4AB','\UB4AC','\UB4AD','\UB4AE','\UB4AF','\UB4B0','\UB4B1','\UB4B2','\UB4B3','\UB4B4','\UB4B5','\UB4B6','\UB4B7','\UB4B8','\UB4B9','\UB4BA','\UB4BB','\UB4BC','\UB4BD','\UB4BE','\UB4BF','\UB4C0','\UB4C1','\UB4C2','\UB4C3','\UB4C4','\UB4C5','\UB4C6','\UB4C7','\UB4C8','\UB4C9','\UB4CA','\UB4CB','\UB4CC','\UB4CD','\UB4CE','\UB4CF','\UB4D0','\UB4D1','\UB4D2','\UB4D3','\UB4D4','\UB4D5','\UB4D6','\UB4D7','\UB4D8','\UB4D9','\UB4DA','\UB4DB','\UB4DC','\UB4DD','\UB4DE','\UB4DF','\UB4E0','\UB4E1','\UB4E2','\UB4E3','\UB4E4','\UB4E5','\UB4E6','\UB4E7','\UB4E8','\UB4E9','\UB4EA','\UB4EB','\UB4EC','\UB4ED','\UB4EE','\UB4EF','\UB4F0','\UB4F1','\UB4F2','\UB4F3','\UB4F4','\UB4F5','\UB4F6','\UB4F7','\UB4F8','\UB4F9','\UB4FA','\UB4FB','\UB4FC','\UB4FD','\UB4FE','\UB4FF','\UB500','\UB501','\UB502','\UB503','\UB504','\UB505','\UB506','\UB507','\UB508','\UB509','\UB50A','\UB50B','\UB50C','\UB50D','\UB50E','\UB50F','\UB510','\UB511','\UB512','\UB513','\UB514','\UB515','\UB516','\UB517','\UB518','\UB519','\UB51A','\UB51B','\UB51C','\UB51D','\UB51E','\UB51F','\UB520','\UB521','\UB522','\UB523','\UB524','\UB525','\UB526','\UB527','\UB528','\UB529','\UB52A','\UB52B','\UB52C','\UB52D','\UB52E','\UB52F','\UB530','\UB531','\UB532','\UB533','\UB534','\UB535','\UB536','\UB537','\UB538','\UB539','\UB53A','\UB53B','\UB53C','\UB53D','\UB53E','\UB53F','\UB540','\UB541','\UB542','\UB543','\UB544','\UB545','\UB546','\UB547','\UB548','\UB549','\UB54A','\UB54B','\UB54C','\UB54D','\UB54E','\UB54F','\UB550','\UB551','\UB552','\UB553','\UB554','\UB555','\UB556','\UB557','\UB558','\UB559','\UB55A','\UB55B','\UB55C','\UB55D','\UB55E','\UB55F','\UB560','\UB561','\UB562','\UB563','\UB564','\UB565','\UB566','\UB567','\UB568','\UB569','\UB56A','\UB56B','\UB56C','\UB56D','\UB56E','\UB56F','\UB570','\UB571','\UB572','\UB573','\UB574','\UB575','\UB576','\UB577','\UB578','\UB579','\UB57A','\UB57B','\UB57C','\UB57D','\UB57E','\UB57F','\UB580','\UB581','\UB582','\UB583','\UB584','\UB585','\UB586','\UB587','\UB588','\UB589','\UB58A','\UB58B','\UB58C','\UB58D','\UB58E','\UB58F','\UB590','\UB591','\UB592','\UB593','\UB594','\UB595','\UB596','\UB597','\UB598','\UB599','\UB59A','\UB59B','\UB59C','\UB59D','\UB59E','\UB59F','\UB5A0','\UB5A1','\UB5A2','\UB5A3','\UB5A4','\UB5A5','\UB5A6','\UB5A7','\UB5A8','\UB5A9','\UB5AA','\UB5AB','\UB5AC','\UB5AD','\UB5AE','\UB5AF','\UB5B0','\UB5B1','\UB5B2','\UB5B3','\UB5B4','\UB5B5','\UB5B6','\UB5B7','\UB5B8','\UB5B9','\UB5BA','\UB5BB','\UB5BC','\UB5BD','\UB5BE','\UB5BF','\UB5C0','\UB5C1','\UB5C2','\UB5C3','\UB5C4','\UB5C5','\UB5C6','\UB5C7','\UB5C8','\UB5C9','\UB5CA','\UB5CB','\UB5CC','\UB5CD','\UB5CE','\UB5CF','\UB5D0','\UB5D1','\UB5D2','\UB5D3','\UB5D4','\UB5D5','\UB5D6','\UB5D7','\UB5D8','\UB5D9','\UB5DA','\UB5DB','\UB5DC','\UB5DD','\UB5DE','\UB5DF','\UB5E0','\UB5E1','\UB5E2','\UB5E3','\UB5E4','\UB5E5','\UB5E6','\UB5E7','\UB5E8','\UB5E9','\UB5EA','\UB5EB','\UB5EC','\UB5ED','\UB5EE','\UB5EF','\UB5F0','\UB5F1','\UB5F2','\UB5F3','\UB5F4','\UB5F5','\UB5F6','\UB5F7','\UB5F8','\UB5F9','\UB5FA','\UB5FB','\UB5FC','\UB5FD','\UB5FE','\UB5FF','\UB600','\UB601','\UB602','\UB603','\UB604','\UB605','\UB606','\UB607','\UB608','\UB609','\UB60A','\UB60B','\UB60C','\UB60D','\UB60E','\UB60F','\UB610','\UB611','\UB612','\UB613','\UB614','\UB615','\UB616','\UB617','\UB618','\UB619','\UB61A','\UB61B','\UB61C','\UB61D','\UB61E','\UB61F','\UB620','\UB621','\UB622','\UB623','\UB624','\UB625','\UB626','\UB627','\UB628','\UB629','\UB62A','\UB62B','\UB62C','\UB62D','\UB62E','\UB62F','\UB630','\UB631','\UB632','\UB633','\UB634','\UB635','\UB636','\UB637','\UB638','\UB639','\UB63A','\UB63B','\UB63C','\UB63D','\UB63E','\UB63F','\UB640','\UB641','\UB642','\UB643','\UB644','\UB645','\UB646','\UB647','\UB648','\UB649','\UB64A','\UB64B','\UB64C','\UB64D','\UB64E','\UB64F','\UB650','\UB651','\UB652','\UB653','\UB654','\UB655','\UB656','\UB657','\UB658','\UB659','\UB65A','\UB65B','\UB65C','\UB65D','\UB65E','\UB65F','\UB660','\UB661','\UB662','\UB663','\UB664','\UB665','\UB666','\UB667','\UB668','\UB669','\UB66A','\UB66B','\UB66C','\UB66D','\UB66E','\UB66F','\UB670','\UB671','\UB672','\UB673','\UB674','\UB675','\UB676','\UB677','\UB678','\UB679','\UB67A','\UB67B','\UB67C','\UB67D','\UB67E','\UB67F','\UB680','\UB681','\UB682','\UB683','\UB684','\UB685','\UB686','\UB687','\UB688','\UB689','\UB68A','\UB68B','\UB68C','\UB68D','\UB68E','\UB68F','\UB690','\UB691','\UB692','\UB693','\UB694','\UB695','\UB696','\UB697','\UB698','\UB699','\UB69A','\UB69B','\UB69C','\UB69D','\UB69E','\UB69F','\UB6A0','\UB6A1','\UB6A2','\UB6A3','\UB6A4','\UB6A5','\UB6A6','\UB6A7','\UB6A8','\UB6A9','\UB6AA','\UB6AB','\UB6AC','\UB6AD','\UB6AE','\UB6AF','\UB6B0','\UB6B1','\UB6B2','\UB6B3','\UB6B4','\UB6B5','\UB6B6','\UB6B7','\UB6B8','\UB6B9','\UB6BA','\UB6BB','\UB6BC','\UB6BD','\UB6BE','\UB6BF','\UB6C0','\UB6C1','\UB6C2','\UB6C3','\UB6C4','\UB6C5','\UB6C6','\UB6C7','\UB6C8','\UB6C9','\UB6CA','\UB6CB','\UB6CC','\UB6CD','\UB6CE','\UB6CF','\UB6D0','\UB6D1','\UB6D2','\UB6D3','\UB6D4','\UB6D5','\UB6D6','\UB6D7','\UB6D8','\UB6D9','\UB6DA','\UB6DB','\UB6DC','\UB6DD','\UB6DE','\UB6DF','\UB6E0','\UB6E1','\UB6E2','\UB6E3','\UB6E4','\UB6E5','\UB6E6','\UB6E7','\UB6E8','\UB6E9','\UB6EA','\UB6EB','\UB6EC','\UB6ED','\UB6EE','\UB6EF','\UB6F0','\UB6F1','\UB6F2','\UB6F3','\UB6F4','\UB6F5','\UB6F6','\UB6F7','\UB6F8','\UB6F9','\UB6FA','\UB6FB','\UB6FC','\UB6FD','\UB6FE','\UB6FF','\UB700','\UB701','\UB702','\UB703','\UB704','\UB705','\UB706','\UB707','\UB708','\UB709','\UB70A','\UB70B','\UB70C','\UB70D','\UB70E','\UB70F','\UB710','\UB711','\UB712','\UB713','\UB714','\UB715','\UB716','\UB717','\UB718','\UB719','\UB71A','\UB71B','\UB71C','\UB71D','\UB71E','\UB71F','\UB720','\UB721','\UB722','\UB723','\UB724','\UB725','\UB726','\UB727','\UB728','\UB729','\UB72A','\UB72B','\UB72C','\UB72D','\UB72E','\UB72F','\UB730','\UB731','\UB732','\UB733','\UB734','\UB735','\UB736','\UB737','\UB738','\UB739','\UB73A','\UB73B','\UB73C','\UB73D','\UB73E','\UB73F','\UB740','\UB741','\UB742','\UB743','\UB744','\UB745','\UB746','\UB747','\UB748','\UB749','\UB74A','\UB74B','\UB74C','\UB74D','\UB74E','\UB74F','\UB750','\UB751','\UB752','\UB753','\UB754','\UB755','\UB756','\UB757','\UB758','\UB759','\UB75A','\UB75B','\UB75C','\UB75D','\UB75E','\UB75F','\UB760','\UB761','\UB762','\UB763','\UB764','\UB765','\UB766','\UB767','\UB768','\UB769','\UB76A','\UB76B','\UB76C','\UB76D','\UB76E','\UB76F','\UB770','\UB771','\UB772','\UB773','\UB774','\UB775','\UB776','\UB777','\UB778','\UB779','\UB77A','\UB77B','\UB77C','\UB77D','\UB77E','\UB77F','\UB780','\UB781','\UB782','\UB783','\UB784','\UB785','\UB786','\UB787','\UB788','\UB789','\UB78A','\UB78B','\UB78C','\UB78D','\UB78E','\UB78F','\UB790','\UB791','\UB792','\UB793','\UB794','\UB795','\UB796','\UB797','\UB798','\UB799','\UB79A','\UB79B','\UB79C','\UB79D','\UB79E','\UB79F','\UB7A0','\UB7A1','\UB7A2','\UB7A3','\UB7A4','\UB7A5','\UB7A6','\UB7A7','\UB7A8','\UB7A9','\UB7AA','\UB7AB','\UB7AC','\UB7AD','\UB7AE','\UB7AF','\UB7B0','\UB7B1','\UB7B2','\UB7B3','\UB7B4','\UB7B5','\UB7B6','\UB7B7','\UB7B8','\UB7B9','\UB7BA','\UB7BB','\UB7BC','\UB7BD','\UB7BE','\UB7BF','\UB7C0','\UB7C1','\UB7C2','\UB7C3','\UB7C4','\UB7C5','\UB7C6','\UB7C7','\UB7C8','\UB7C9','\UB7CA','\UB7CB','\UB7CC','\UB7CD','\UB7CE','\UB7CF','\UB7D0','\UB7D1','\UB7D2','\UB7D3','\UB7D4','\UB7D5','\UB7D6','\UB7D7','\UB7D8','\UB7D9','\UB7DA','\UB7DB','\UB7DC','\UB7DD','\UB7DE','\UB7DF','\UB7E0','\UB7E1','\UB7E2','\UB7E3','\UB7E4','\UB7E5','\UB7E6','\UB7E7','\UB7E8','\UB7E9','\UB7EA','\UB7EB','\UB7EC','\UB7ED','\UB7EE','\UB7EF','\UB7F0','\UB7F1','\UB7F2','\UB7F3','\UB7F4','\UB7F5','\UB7F6','\UB7F7','\UB7F8','\UB7F9','\UB7FA','\UB7FB','\UB7FC','\UB7FD','\UB7FE','\UB7FF','\UB800','\UB801','\UB802','\UB803','\UB804','\UB805','\UB806','\UB807','\UB808','\UB809','\UB80A','\UB80B','\UB80C','\UB80D','\UB80E','\UB80F','\UB810','\UB811','\UB812','\UB813','\UB814','\UB815','\UB816','\UB817','\UB818','\UB819','\UB81A','\UB81B','\UB81C','\UB81D','\UB81E','\UB81F','\UB820','\UB821','\UB822','\UB823','\UB824','\UB825','\UB826','\UB827','\UB828','\UB829','\UB82A','\UB82B','\UB82C','\UB82D','\UB82E','\UB82F','\UB830','\UB831','\UB832','\UB833','\UB834','\UB835','\UB836','\UB837','\UB838','\UB839','\UB83A','\UB83B','\UB83C','\UB83D','\UB83E','\UB83F','\UB840','\UB841','\UB842','\UB843','\UB844','\UB845','\UB846','\UB847','\UB848','\UB849','\UB84A','\UB84B','\UB84C','\UB84D','\UB84E','\UB84F','\UB850','\UB851','\UB852','\UB853','\UB854','\UB855','\UB856','\UB857','\UB858','\UB859','\UB85A','\UB85B','\UB85C','\UB85D','\UB85E','\UB85F','\UB860','\UB861','\UB862','\UB863','\UB864','\UB865','\UB866','\UB867','\UB868','\UB869','\UB86A','\UB86B','\UB86C','\UB86D','\UB86E','\UB86F','\UB870','\UB871','\UB872','\UB873','\UB874','\UB875','\UB876','\UB877','\UB878','\UB879','\UB87A','\UB87B','\UB87C','\UB87D','\UB87E','\UB87F','\UB880','\UB881','\UB882','\UB883','\UB884','\UB885','\UB886','\UB887','\UB888','\UB889','\UB88A','\UB88B','\UB88C','\UB88D','\UB88E','\UB88F','\UB890','\UB891','\UB892','\UB893','\UB894','\UB895','\UB896','\UB897','\UB898','\UB899','\UB89A','\UB89B','\UB89C','\UB89D','\UB89E','\UB89F','\UB8A0','\UB8A1','\UB8A2','\UB8A3','\UB8A4','\UB8A5','\UB8A6','\UB8A7','\UB8A8','\UB8A9','\UB8AA','\UB8AB','\UB8AC','\UB8AD','\UB8AE','\UB8AF','\UB8B0','\UB8B1','\UB8B2','\UB8B3','\UB8B4','\UB8B5','\UB8B6','\UB8B7','\UB8B8','\UB8B9','\UB8BA','\UB8BB','\UB8BC','\UB8BD','\UB8BE','\UB8BF','\UB8C0','\UB8C1','\UB8C2','\UB8C3','\UB8C4','\UB8C5','\UB8C6','\UB8C7','\UB8C8','\UB8C9','\UB8CA','\UB8CB','\UB8CC','\UB8CD','\UB8CE','\UB8CF','\UB8D0','\UB8D1','\UB8D2','\UB8D3','\UB8D4','\UB8D5','\UB8D6','\UB8D7','\UB8D8','\UB8D9','\UB8DA','\UB8DB','\UB8DC','\UB8DD','\UB8DE','\UB8DF','\UB8E0','\UB8E1','\UB8E2','\UB8E3','\UB8E4','\UB8E5','\UB8E6','\UB8E7','\UB8E8','\UB8E9','\UB8EA','\UB8EB','\UB8EC','\UB8ED','\UB8EE','\UB8EF','\UB8F0','\UB8F1','\UB8F2','\UB8F3','\UB8F4','\UB8F5','\UB8F6','\UB8F7','\UB8F8','\UB8F9','\UB8FA','\UB8FB','\UB8FC','\UB8FD','\UB8FE','\UB8FF','\UB900','\UB901','\UB902','\UB903','\UB904','\UB905','\UB906','\UB907','\UB908','\UB909','\UB90A','\UB90B','\UB90C','\UB90D','\UB90E','\UB90F','\UB910','\UB911','\UB912','\UB913','\UB914','\UB915','\UB916','\UB917','\UB918','\UB919','\UB91A','\UB91B','\UB91C','\UB91D','\UB91E','\UB91F','\UB920','\UB921','\UB922','\UB923','\UB924','\UB925','\UB926','\UB927','\UB928','\UB929','\UB92A','\UB92B','\UB92C','\UB92D','\UB92E','\UB92F','\UB930','\UB931','\UB932','\UB933','\UB934','\UB935','\UB936','\UB937','\UB938','\UB939','\UB93A','\UB93B','\UB93C','\UB93D','\UB93E','\UB93F','\UB940','\UB941','\UB942','\UB943','\UB944','\UB945','\UB946','\UB947','\UB948','\UB949','\UB94A','\UB94B','\UB94C','\UB94D','\UB94E','\UB94F','\UB950','\UB951','\UB952','\UB953','\UB954','\UB955','\UB956','\UB957','\UB958','\UB959','\UB95A','\UB95B','\UB95C','\UB95D','\UB95E','\UB95F','\UB960','\UB961','\UB962','\UB963','\UB964','\UB965','\UB966','\UB967','\UB968','\UB969','\UB96A','\UB96B','\UB96C','\UB96D','\UB96E','\UB96F','\UB970','\UB971','\UB972','\UB973','\UB974','\UB975','\UB976','\UB977','\UB978','\UB979','\UB97A','\UB97B','\UB97C','\UB97D','\UB97E','\UB97F','\UB980','\UB981','\UB982','\UB983','\UB984','\UB985','\UB986','\UB987','\UB988','\UB989','\UB98A','\UB98B','\UB98C','\UB98D','\UB98E','\UB98F','\UB990','\UB991','\UB992','\UB993','\UB994','\UB995','\UB996','\UB997','\UB998','\UB999','\UB99A','\UB99B','\UB99C','\UB99D','\UB99E','\UB99F','\UB9A0','\UB9A1','\UB9A2','\UB9A3','\UB9A4','\UB9A5','\UB9A6','\UB9A7','\UB9A8','\UB9A9','\UB9AA','\UB9AB','\UB9AC','\UB9AD','\UB9AE','\UB9AF','\UB9B0','\UB9B1','\UB9B2','\UB9B3','\UB9B4','\UB9B5','\UB9B6','\UB9B7','\UB9B8','\UB9B9','\UB9BA','\UB9BB','\UB9BC','\UB9BD','\UB9BE','\UB9BF','\UB9C0','\UB9C1','\UB9C2','\UB9C3','\UB9C4','\UB9C5','\UB9C6','\UB9C7','\UB9C8','\UB9C9','\UB9CA','\UB9CB','\UB9CC','\UB9CD','\UB9CE','\UB9CF','\UB9D0','\UB9D1','\UB9D2','\UB9D3','\UB9D4','\UB9D5','\UB9D6','\UB9D7','\UB9D8','\UB9D9','\UB9DA','\UB9DB','\UB9DC','\UB9DD','\UB9DE','\UB9DF','\UB9E0','\UB9E1','\UB9E2','\UB9E3','\UB9E4','\UB9E5','\UB9E6','\UB9E7','\UB9E8','\UB9E9','\UB9EA','\UB9EB','\UB9EC','\UB9ED','\UB9EE','\UB9EF','\UB9F0','\UB9F1','\UB9F2','\UB9F3','\UB9F4','\UB9F5','\UB9F6','\UB9F7','\UB9F8','\UB9F9','\UB9FA','\UB9FB','\UB9FC','\UB9FD','\UB9FE','\UB9FF','\UBA00','\UBA01','\UBA02','\UBA03','\UBA04','\UBA05','\UBA06','\UBA07','\UBA08','\UBA09','\UBA0A','\UBA0B','\UBA0C','\UBA0D','\UBA0E','\UBA0F','\UBA10','\UBA11','\UBA12','\UBA13','\UBA14','\UBA15','\UBA16','\UBA17','\UBA18','\UBA19','\UBA1A','\UBA1B','\UBA1C','\UBA1D','\UBA1E','\UBA1F','\UBA20','\UBA21','\UBA22','\UBA23','\UBA24','\UBA25','\UBA26','\UBA27','\UBA28','\UBA29','\UBA2A','\UBA2B','\UBA2C','\UBA2D','\UBA2E','\UBA2F','\UBA30','\UBA31','\UBA32','\UBA33','\UBA34','\UBA35','\UBA36','\UBA37','\UBA38','\UBA39','\UBA3A','\UBA3B','\UBA3C','\UBA3D','\UBA3E','\UBA3F','\UBA40','\UBA41','\UBA42','\UBA43','\UBA44','\UBA45','\UBA46','\UBA47','\UBA48','\UBA49','\UBA4A','\UBA4B','\UBA4C','\UBA4D','\UBA4E','\UBA4F','\UBA50','\UBA51','\UBA52','\UBA53','\UBA54','\UBA55','\UBA56','\UBA57','\UBA58','\UBA59','\UBA5A','\UBA5B','\UBA5C','\UBA5D','\UBA5E','\UBA5F','\UBA60','\UBA61','\UBA62','\UBA63','\UBA64','\UBA65','\UBA66','\UBA67','\UBA68','\UBA69','\UBA6A','\UBA6B','\UBA6C','\UBA6D','\UBA6E','\UBA6F','\UBA70','\UBA71','\UBA72','\UBA73','\UBA74','\UBA75','\UBA76','\UBA77','\UBA78','\UBA79','\UBA7A','\UBA7B','\UBA7C','\UBA7D','\UBA7E','\UBA7F','\UBA80','\UBA81','\UBA82','\UBA83','\UBA84','\UBA85','\UBA86','\UBA87','\UBA88','\UBA89','\UBA8A','\UBA8B','\UBA8C','\UBA8D','\UBA8E','\UBA8F','\UBA90','\UBA91','\UBA92','\UBA93','\UBA94','\UBA95','\UBA96','\UBA97','\UBA98','\UBA99','\UBA9A','\UBA9B','\UBA9C','\UBA9D','\UBA9E','\UBA9F','\UBAA0','\UBAA1','\UBAA2','\UBAA3','\UBAA4','\UBAA5','\UBAA6','\UBAA7','\UBAA8','\UBAA9','\UBAAA','\UBAAB','\UBAAC','\UBAAD','\UBAAE','\UBAAF','\UBAB0','\UBAB1','\UBAB2','\UBAB3','\UBAB4','\UBAB5','\UBAB6','\UBAB7','\UBAB8','\UBAB9','\UBABA','\UBABB','\UBABC','\UBABD','\UBABE','\UBABF','\UBAC0','\UBAC1','\UBAC2','\UBAC3','\UBAC4','\UBAC5','\UBAC6','\UBAC7','\UBAC8','\UBAC9','\UBACA','\UBACB','\UBACC','\UBACD','\UBACE','\UBACF','\UBAD0','\UBAD1','\UBAD2','\UBAD3','\UBAD4','\UBAD5','\UBAD6','\UBAD7','\UBAD8','\UBAD9','\UBADA','\UBADB','\UBADC','\UBADD','\UBADE','\UBADF','\UBAE0','\UBAE1','\UBAE2','\UBAE3','\UBAE4','\UBAE5','\UBAE6','\UBAE7','\UBAE8','\UBAE9','\UBAEA','\UBAEB','\UBAEC','\UBAED','\UBAEE','\UBAEF','\UBAF0','\UBAF1','\UBAF2','\UBAF3','\UBAF4','\UBAF5','\UBAF6','\UBAF7','\UBAF8','\UBAF9','\UBAFA','\UBAFB','\UBAFC','\UBAFD','\UBAFE','\UBAFF','\UBB00','\UBB01','\UBB02','\UBB03','\UBB04','\UBB05','\UBB06','\UBB07','\UBB08','\UBB09','\UBB0A','\UBB0B','\UBB0C','\UBB0D','\UBB0E','\UBB0F','\UBB10','\UBB11','\UBB12','\UBB13','\UBB14','\UBB15','\UBB16','\UBB17','\UBB18','\UBB19','\UBB1A','\UBB1B','\UBB1C','\UBB1D','\UBB1E','\UBB1F','\UBB20','\UBB21','\UBB22','\UBB23','\UBB24','\UBB25','\UBB26','\UBB27','\UBB28','\UBB29','\UBB2A','\UBB2B','\UBB2C','\UBB2D','\UBB2E','\UBB2F','\UBB30','\UBB31','\UBB32','\UBB33','\UBB34','\UBB35','\UBB36','\UBB37','\UBB38','\UBB39','\UBB3A','\UBB3B','\UBB3C','\UBB3D','\UBB3E','\UBB3F','\UBB40','\UBB41','\UBB42','\UBB43','\UBB44','\UBB45','\UBB46','\UBB47','\UBB48','\UBB49','\UBB4A','\UBB4B','\UBB4C','\UBB4D','\UBB4E','\UBB4F','\UBB50','\UBB51','\UBB52','\UBB53','\UBB54','\UBB55','\UBB56','\UBB57','\UBB58','\UBB59','\UBB5A','\UBB5B','\UBB5C','\UBB5D','\UBB5E','\UBB5F','\UBB60','\UBB61','\UBB62','\UBB63','\UBB64','\UBB65','\UBB66','\UBB67','\UBB68','\UBB69','\UBB6A','\UBB6B','\UBB6C','\UBB6D','\UBB6E','\UBB6F','\UBB70','\UBB71','\UBB72','\UBB73','\UBB74','\UBB75','\UBB76','\UBB77','\UBB78','\UBB79','\UBB7A','\UBB7B','\UBB7C','\UBB7D','\UBB7E','\UBB7F','\UBB80','\UBB81','\UBB82','\UBB83','\UBB84','\UBB85','\UBB86','\UBB87','\UBB88','\UBB89','\UBB8A','\UBB8B','\UBB8C','\UBB8D','\UBB8E','\UBB8F','\UBB90','\UBB91','\UBB92','\UBB93','\UBB94','\UBB95','\UBB96','\UBB97','\UBB98','\UBB99','\UBB9A','\UBB9B','\UBB9C','\UBB9D','\UBB9E','\UBB9F','\UBBA0','\UBBA1','\UBBA2','\UBBA3','\UBBA4','\UBBA5','\UBBA6','\UBBA7','\UBBA8','\UBBA9','\UBBAA','\UBBAB','\UBBAC','\UBBAD','\UBBAE','\UBBAF','\UBBB0','\UBBB1','\UBBB2','\UBBB3','\UBBB4','\UBBB5','\UBBB6','\UBBB7','\UBBB8','\UBBB9','\UBBBA','\UBBBB','\UBBBC','\UBBBD','\UBBBE','\UBBBF','\UBBC0','\UBBC1','\UBBC2','\UBBC3','\UBBC4','\UBBC5','\UBBC6','\UBBC7','\UBBC8','\UBBC9','\UBBCA','\UBBCB','\UBBCC','\UBBCD','\UBBCE','\UBBCF','\UBBD0','\UBBD1','\UBBD2','\UBBD3','\UBBD4','\UBBD5','\UBBD6','\UBBD7','\UBBD8','\UBBD9','\UBBDA','\UBBDB','\UBBDC','\UBBDD','\UBBDE','\UBBDF','\UBBE0','\UBBE1','\UBBE2','\UBBE3','\UBBE4','\UBBE5','\UBBE6','\UBBE7','\UBBE8','\UBBE9','\UBBEA','\UBBEB','\UBBEC','\UBBED','\UBBEE','\UBBEF','\UBBF0','\UBBF1','\UBBF2','\UBBF3','\UBBF4','\UBBF5','\UBBF6','\UBBF7','\UBBF8','\UBBF9','\UBBFA','\UBBFB','\UBBFC','\UBBFD','\UBBFE','\UBBFF','\UBC00','\UBC01','\UBC02','\UBC03','\UBC04','\UBC05','\UBC06','\UBC07','\UBC08','\UBC09','\UBC0A','\UBC0B','\UBC0C','\UBC0D','\UBC0E','\UBC0F','\UBC10','\UBC11','\UBC12','\UBC13','\UBC14','\UBC15','\UBC16','\UBC17','\UBC18','\UBC19','\UBC1A','\UBC1B','\UBC1C','\UBC1D','\UBC1E','\UBC1F','\UBC20','\UBC21','\UBC22','\UBC23','\UBC24','\UBC25','\UBC26','\UBC27','\UBC28','\UBC29','\UBC2A','\UBC2B','\UBC2C','\UBC2D','\UBC2E','\UBC2F','\UBC30','\UBC31','\UBC32','\UBC33','\UBC34','\UBC35','\UBC36','\UBC37','\UBC38','\UBC39','\UBC3A','\UBC3B','\UBC3C','\UBC3D','\UBC3E','\UBC3F','\UBC40','\UBC41','\UBC42','\UBC43','\UBC44','\UBC45','\UBC46','\UBC47','\UBC48','\UBC49','\UBC4A','\UBC4B','\UBC4C','\UBC4D','\UBC4E','\UBC4F','\UBC50','\UBC51','\UBC52','\UBC53','\UBC54','\UBC55','\UBC56','\UBC57','\UBC58','\UBC59','\UBC5A','\UBC5B','\UBC5C','\UBC5D','\UBC5E','\UBC5F','\UBC60','\UBC61','\UBC62','\UBC63','\UBC64','\UBC65','\UBC66','\UBC67','\UBC68','\UBC69','\UBC6A','\UBC6B','\UBC6C','\UBC6D','\UBC6E','\UBC6F','\UBC70','\UBC71','\UBC72','\UBC73','\UBC74','\UBC75','\UBC76','\UBC77','\UBC78','\UBC79','\UBC7A','\UBC7B','\UBC7C','\UBC7D','\UBC7E','\UBC7F','\UBC80','\UBC81','\UBC82','\UBC83','\UBC84','\UBC85','\UBC86','\UBC87','\UBC88','\UBC89','\UBC8A','\UBC8B','\UBC8C','\UBC8D','\UBC8E','\UBC8F','\UBC90','\UBC91','\UBC92','\UBC93','\UBC94','\UBC95','\UBC96','\UBC97','\UBC98','\UBC99','\UBC9A','\UBC9B','\UBC9C','\UBC9D','\UBC9E','\UBC9F','\UBCA0','\UBCA1','\UBCA2','\UBCA3','\UBCA4','\UBCA5','\UBCA6','\UBCA7','\UBCA8','\UBCA9','\UBCAA','\UBCAB','\UBCAC','\UBCAD','\UBCAE','\UBCAF','\UBCB0','\UBCB1','\UBCB2','\UBCB3','\UBCB4','\UBCB5','\UBCB6','\UBCB7','\UBCB8','\UBCB9','\UBCBA','\UBCBB','\UBCBC','\UBCBD','\UBCBE','\UBCBF','\UBCC0','\UBCC1','\UBCC2','\UBCC3','\UBCC4','\UBCC5','\UBCC6','\UBCC7','\UBCC8','\UBCC9','\UBCCA','\UBCCB','\UBCCC','\UBCCD','\UBCCE','\UBCCF','\UBCD0','\UBCD1','\UBCD2','\UBCD3','\UBCD4','\UBCD5','\UBCD6','\UBCD7','\UBCD8','\UBCD9','\UBCDA','\UBCDB','\UBCDC','\UBCDD','\UBCDE','\UBCDF','\UBCE0','\UBCE1','\UBCE2','\UBCE3','\UBCE4','\UBCE5','\UBCE6','\UBCE7','\UBCE8','\UBCE9','\UBCEA','\UBCEB','\UBCEC','\UBCED','\UBCEE','\UBCEF','\UBCF0','\UBCF1','\UBCF2','\UBCF3','\UBCF4','\UBCF5','\UBCF6','\UBCF7','\UBCF8','\UBCF9','\UBCFA','\UBCFB','\UBCFC','\UBCFD','\UBCFE','\UBCFF','\UBD00','\UBD01','\UBD02','\UBD03','\UBD04','\UBD05','\UBD06','\UBD07','\UBD08','\UBD09','\UBD0A','\UBD0B','\UBD0C','\UBD0D','\UBD0E','\UBD0F','\UBD10','\UBD11','\UBD12','\UBD13','\UBD14','\UBD15','\UBD16','\UBD17','\UBD18','\UBD19','\UBD1A','\UBD1B','\UBD1C','\UBD1D','\UBD1E','\UBD1F','\UBD20','\UBD21','\UBD22','\UBD23','\UBD24','\UBD25','\UBD26','\UBD27','\UBD28','\UBD29','\UBD2A','\UBD2B','\UBD2C','\UBD2D','\UBD2E','\UBD2F','\UBD30','\UBD31','\UBD32','\UBD33','\UBD34','\UBD35','\UBD36','\UBD37','\UBD38','\UBD39','\UBD3A','\UBD3B','\UBD3C','\UBD3D','\UBD3E','\UBD3F','\UBD40','\UBD41','\UBD42','\UBD43','\UBD44','\UBD45','\UBD46','\UBD47','\UBD48','\UBD49','\UBD4A','\UBD4B','\UBD4C','\UBD4D','\UBD4E','\UBD4F','\UBD50','\UBD51','\UBD52','\UBD53','\UBD54','\UBD55','\UBD56','\UBD57','\UBD58','\UBD59','\UBD5A','\UBD5B','\UBD5C','\UBD5D','\UBD5E','\UBD5F','\UBD60','\UBD61','\UBD62','\UBD63','\UBD64','\UBD65','\UBD66','\UBD67','\UBD68','\UBD69','\UBD6A','\UBD6B','\UBD6C','\UBD6D','\UBD6E','\UBD6F','\UBD70','\UBD71','\UBD72','\UBD73','\UBD74','\UBD75','\UBD76','\UBD77','\UBD78','\UBD79','\UBD7A','\UBD7B','\UBD7C','\UBD7D','\UBD7E','\UBD7F','\UBD80','\UBD81','\UBD82','\UBD83','\UBD84','\UBD85','\UBD86','\UBD87','\UBD88','\UBD89','\UBD8A','\UBD8B','\UBD8C','\UBD8D','\UBD8E','\UBD8F','\UBD90','\UBD91','\UBD92','\UBD93','\UBD94','\UBD95','\UBD96','\UBD97','\UBD98','\UBD99','\UBD9A','\UBD9B','\UBD9C','\UBD9D','\UBD9E','\UBD9F','\UBDA0','\UBDA1','\UBDA2','\UBDA3','\UBDA4','\UBDA5','\UBDA6','\UBDA7','\UBDA8','\UBDA9','\UBDAA','\UBDAB','\UBDAC','\UBDAD','\UBDAE','\UBDAF','\UBDB0','\UBDB1','\UBDB2','\UBDB3','\UBDB4','\UBDB5','\UBDB6','\UBDB7','\UBDB8','\UBDB9','\UBDBA','\UBDBB','\UBDBC','\UBDBD','\UBDBE','\UBDBF','\UBDC0','\UBDC1','\UBDC2','\UBDC3','\UBDC4','\UBDC5','\UBDC6','\UBDC7','\UBDC8','\UBDC9','\UBDCA','\UBDCB','\UBDCC','\UBDCD','\UBDCE','\UBDCF','\UBDD0','\UBDD1','\UBDD2','\UBDD3','\UBDD4','\UBDD5','\UBDD6','\UBDD7','\UBDD8','\UBDD9','\UBDDA','\UBDDB','\UBDDC','\UBDDD','\UBDDE','\UBDDF','\UBDE0','\UBDE1','\UBDE2','\UBDE3','\UBDE4','\UBDE5','\UBDE6','\UBDE7','\UBDE8','\UBDE9','\UBDEA','\UBDEB','\UBDEC','\UBDED','\UBDEE','\UBDEF','\UBDF0','\UBDF1','\UBDF2','\UBDF3','\UBDF4','\UBDF5','\UBDF6','\UBDF7','\UBDF8','\UBDF9','\UBDFA','\UBDFB','\UBDFC','\UBDFD','\UBDFE','\UBDFF','\UBE00','\UBE01','\UBE02','\UBE03','\UBE04','\UBE05','\UBE06','\UBE07','\UBE08','\UBE09','\UBE0A','\UBE0B','\UBE0C','\UBE0D','\UBE0E','\UBE0F','\UBE10','\UBE11','\UBE12','\UBE13','\UBE14','\UBE15','\UBE16','\UBE17','\UBE18','\UBE19','\UBE1A','\UBE1B','\UBE1C','\UBE1D','\UBE1E','\UBE1F','\UBE20','\UBE21','\UBE22','\UBE23','\UBE24','\UBE25','\UBE26','\UBE27','\UBE28','\UBE29','\UBE2A','\UBE2B','\UBE2C','\UBE2D','\UBE2E','\UBE2F','\UBE30','\UBE31','\UBE32','\UBE33','\UBE34','\UBE35','\UBE36','\UBE37','\UBE38','\UBE39','\UBE3A','\UBE3B','\UBE3C','\UBE3D','\UBE3E','\UBE3F','\UBE40','\UBE41','\UBE42','\UBE43','\UBE44','\UBE45','\UBE46','\UBE47','\UBE48','\UBE49','\UBE4A','\UBE4B','\UBE4C','\UBE4D','\UBE4E','\UBE4F','\UBE50','\UBE51','\UBE52','\UBE53','\UBE54','\UBE55','\UBE56','\UBE57','\UBE58','\UBE59','\UBE5A','\UBE5B','\UBE5C','\UBE5D','\UBE5E','\UBE5F','\UBE60','\UBE61','\UBE62','\UBE63','\UBE64','\UBE65','\UBE66','\UBE67','\UBE68','\UBE69','\UBE6A','\UBE6B','\UBE6C','\UBE6D','\UBE6E','\UBE6F','\UBE70','\UBE71','\UBE72','\UBE73','\UBE74','\UBE75','\UBE76','\UBE77','\UBE78','\UBE79','\UBE7A','\UBE7B','\UBE7C','\UBE7D','\UBE7E','\UBE7F','\UBE80','\UBE81','\UBE82','\UBE83','\UBE84','\UBE85','\UBE86','\UBE87','\UBE88','\UBE89','\UBE8A','\UBE8B','\UBE8C','\UBE8D','\UBE8E','\UBE8F','\UBE90','\UBE91','\UBE92','\UBE93','\UBE94','\UBE95','\UBE96','\UBE97','\UBE98','\UBE99','\UBE9A','\UBE9B','\UBE9C','\UBE9D','\UBE9E','\UBE9F','\UBEA0','\UBEA1','\UBEA2','\UBEA3','\UBEA4','\UBEA5','\UBEA6','\UBEA7','\UBEA8','\UBEA9','\UBEAA','\UBEAB','\UBEAC','\UBEAD','\UBEAE','\UBEAF','\UBEB0','\UBEB1','\UBEB2','\UBEB3','\UBEB4','\UBEB5','\UBEB6','\UBEB7','\UBEB8','\UBEB9','\UBEBA','\UBEBB','\UBEBC','\UBEBD','\UBEBE','\UBEBF','\UBEC0','\UBEC1','\UBEC2','\UBEC3','\UBEC4','\UBEC5','\UBEC6','\UBEC7','\UBEC8','\UBEC9','\UBECA','\UBECB','\UBECC','\UBECD','\UBECE','\UBECF','\UBED0','\UBED1','\UBED2','\UBED3','\UBED4','\UBED5','\UBED6','\UBED7','\UBED8','\UBED9','\UBEDA','\UBEDB','\UBEDC','\UBEDD','\UBEDE','\UBEDF','\UBEE0','\UBEE1','\UBEE2','\UBEE3','\UBEE4','\UBEE5','\UBEE6','\UBEE7','\UBEE8','\UBEE9','\UBEEA','\UBEEB','\UBEEC','\UBEED','\UBEEE','\UBEEF','\UBEF0','\UBEF1','\UBEF2','\UBEF3','\UBEF4','\UBEF5','\UBEF6','\UBEF7','\UBEF8','\UBEF9','\UBEFA','\UBEFB','\UBEFC','\UBEFD','\UBEFE','\UBEFF','\UBF00','\UBF01','\UBF02','\UBF03','\UBF04','\UBF05','\UBF06','\UBF07','\UBF08','\UBF09','\UBF0A','\UBF0B','\UBF0C','\UBF0D','\UBF0E','\UBF0F','\UBF10','\UBF11','\UBF12','\UBF13','\UBF14','\UBF15','\UBF16','\UBF17','\UBF18','\UBF19','\UBF1A','\UBF1B','\UBF1C','\UBF1D','\UBF1E','\UBF1F','\UBF20','\UBF21','\UBF22','\UBF23','\UBF24','\UBF25','\UBF26','\UBF27','\UBF28','\UBF29','\UBF2A','\UBF2B','\UBF2C','\UBF2D','\UBF2E','\UBF2F','\UBF30','\UBF31','\UBF32','\UBF33','\UBF34','\UBF35','\UBF36','\UBF37','\UBF38','\UBF39','\UBF3A','\UBF3B','\UBF3C','\UBF3D','\UBF3E','\UBF3F','\UBF40','\UBF41','\UBF42','\UBF43','\UBF44','\UBF45','\UBF46','\UBF47','\UBF48','\UBF49','\UBF4A','\UBF4B','\UBF4C','\UBF4D','\UBF4E','\UBF4F','\UBF50','\UBF51','\UBF52','\UBF53','\UBF54','\UBF55','\UBF56','\UBF57','\UBF58','\UBF59','\UBF5A','\UBF5B','\UBF5C','\UBF5D','\UBF5E','\UBF5F','\UBF60','\UBF61','\UBF62','\UBF63','\UBF64','\UBF65','\UBF66','\UBF67','\UBF68','\UBF69','\UBF6A','\UBF6B','\UBF6C','\UBF6D','\UBF6E','\UBF6F','\UBF70','\UBF71','\UBF72','\UBF73','\UBF74','\UBF75','\UBF76','\UBF77','\UBF78','\UBF79','\UBF7A','\UBF7B','\UBF7C','\UBF7D','\UBF7E','\UBF7F','\UBF80','\UBF81','\UBF82','\UBF83','\UBF84','\UBF85','\UBF86','\UBF87','\UBF88','\UBF89','\UBF8A','\UBF8B','\UBF8C','\UBF8D','\UBF8E','\UBF8F','\UBF90','\UBF91','\UBF92','\UBF93','\UBF94','\UBF95','\UBF96','\UBF97','\UBF98','\UBF99','\UBF9A','\UBF9B','\UBF9C','\UBF9D','\UBF9E','\UBF9F','\UBFA0','\UBFA1','\UBFA2','\UBFA3','\UBFA4','\UBFA5','\UBFA6','\UBFA7','\UBFA8','\UBFA9','\UBFAA','\UBFAB','\UBFAC','\UBFAD','\UBFAE','\UBFAF','\UBFB0','\UBFB1','\UBFB2','\UBFB3','\UBFB4','\UBFB5','\UBFB6','\UBFB7','\UBFB8','\UBFB9','\UBFBA','\UBFBB','\UBFBC','\UBFBD','\UBFBE','\UBFBF','\UBFC0','\UBFC1','\UBFC2','\UBFC3','\UBFC4','\UBFC5','\UBFC6','\UBFC7','\UBFC8','\UBFC9','\UBFCA','\UBFCB','\UBFCC','\UBFCD','\UBFCE','\UBFCF','\UBFD0','\UBFD1','\UBFD2','\UBFD3','\UBFD4','\UBFD5','\UBFD6','\UBFD7','\UBFD8','\UBFD9','\UBFDA','\UBFDB','\UBFDC','\UBFDD','\UBFDE','\UBFDF','\UBFE0','\UBFE1','\UBFE2','\UBFE3','\UBFE4','\UBFE5','\UBFE6','\UBFE7','\UBFE8','\UBFE9','\UBFEA','\UBFEB','\UBFEC','\UBFED','\UBFEE','\UBFEF','\UBFF0','\UBFF1','\UBFF2','\UBFF3','\UBFF4','\UBFF5','\UBFF6','\UBFF7','\UBFF8','\UBFF9','\UBFFA','\UBFFB','\UBFFC','\UBFFD','\UBFFE','\UBFFF','\UC000','\UC001','\UC002','\UC003','\UC004','\UC005','\UC006','\UC007','\UC008','\UC009','\UC00A','\UC00B','\UC00C','\UC00D','\UC00E','\UC00F','\UC010','\UC011','\UC012','\UC013','\UC014','\UC015','\UC016','\UC017','\UC018','\UC019','\UC01A','\UC01B','\UC01C','\UC01D','\UC01E','\UC01F','\UC020','\UC021','\UC022','\UC023','\UC024','\UC025','\UC026','\UC027','\UC028','\UC029','\UC02A','\UC02B','\UC02C','\UC02D','\UC02E','\UC02F','\UC030','\UC031','\UC032','\UC033','\UC034','\UC035','\UC036','\UC037','\UC038','\UC039','\UC03A','\UC03B','\UC03C','\UC03D','\UC03E','\UC03F','\UC040','\UC041','\UC042','\UC043','\UC044','\UC045','\UC046','\UC047','\UC048','\UC049','\UC04A','\UC04B','\UC04C','\UC04D','\UC04E','\UC04F','\UC050','\UC051','\UC052','\UC053','\UC054','\UC055','\UC056','\UC057','\UC058','\UC059','\UC05A','\UC05B','\UC05C','\UC05D','\UC05E','\UC05F','\UC060','\UC061','\UC062','\UC063','\UC064','\UC065','\UC066','\UC067','\UC068','\UC069','\UC06A','\UC06B','\UC06C','\UC06D','\UC06E','\UC06F','\UC070','\UC071','\UC072','\UC073','\UC074','\UC075','\UC076','\UC077','\UC078','\UC079','\UC07A','\UC07B','\UC07C','\UC07D','\UC07E','\UC07F','\UC080','\UC081','\UC082','\UC083','\UC084','\UC085','\UC086','\UC087','\UC088','\UC089','\UC08A','\UC08B','\UC08C','\UC08D','\UC08E','\UC08F','\UC090','\UC091','\UC092','\UC093','\UC094','\UC095','\UC096','\UC097','\UC098','\UC099','\UC09A','\UC09B','\UC09C','\UC09D','\UC09E','\UC09F','\UC0A0','\UC0A1','\UC0A2','\UC0A3','\UC0A4','\UC0A5','\UC0A6','\UC0A7','\UC0A8','\UC0A9','\UC0AA','\UC0AB','\UC0AC','\UC0AD','\UC0AE','\UC0AF','\UC0B0','\UC0B1','\UC0B2','\UC0B3','\UC0B4','\UC0B5','\UC0B6','\UC0B7','\UC0B8','\UC0B9','\UC0BA','\UC0BB','\UC0BC','\UC0BD','\UC0BE','\UC0BF','\UC0C0','\UC0C1','\UC0C2','\UC0C3','\UC0C4','\UC0C5','\UC0C6','\UC0C7','\UC0C8','\UC0C9','\UC0CA','\UC0CB','\UC0CC','\UC0CD','\UC0CE','\UC0CF','\UC0D0','\UC0D1','\UC0D2','\UC0D3','\UC0D4','\UC0D5','\UC0D6','\UC0D7','\UC0D8','\UC0D9','\UC0DA','\UC0DB','\UC0DC','\UC0DD','\UC0DE','\UC0DF','\UC0E0','\UC0E1','\UC0E2','\UC0E3','\UC0E4','\UC0E5','\UC0E6','\UC0E7','\UC0E8','\UC0E9','\UC0EA','\UC0EB','\UC0EC','\UC0ED','\UC0EE','\UC0EF','\UC0F0','\UC0F1','\UC0F2','\UC0F3','\UC0F4','\UC0F5','\UC0F6','\UC0F7','\UC0F8','\UC0F9','\UC0FA','\UC0FB','\UC0FC','\UC0FD','\UC0FE','\UC0FF','\UC100','\UC101','\UC102','\UC103','\UC104','\UC105','\UC106','\UC107','\UC108','\UC109','\UC10A','\UC10B','\UC10C','\UC10D','\UC10E','\UC10F','\UC110','\UC111','\UC112','\UC113','\UC114','\UC115','\UC116','\UC117','\UC118','\UC119','\UC11A','\UC11B','\UC11C','\UC11D','\UC11E','\UC11F','\UC120','\UC121','\UC122','\UC123','\UC124','\UC125','\UC126','\UC127','\UC128','\UC129','\UC12A','\UC12B','\UC12C','\UC12D','\UC12E','\UC12F','\UC130','\UC131','\UC132','\UC133','\UC134','\UC135','\UC136','\UC137','\UC138','\UC139','\UC13A','\UC13B','\UC13C','\UC13D','\UC13E','\UC13F','\UC140','\UC141','\UC142','\UC143','\UC144','\UC145','\UC146','\UC147','\UC148','\UC149','\UC14A','\UC14B','\UC14C','\UC14D','\UC14E','\UC14F','\UC150','\UC151','\UC152','\UC153','\UC154','\UC155','\UC156','\UC157','\UC158','\UC159','\UC15A','\UC15B','\UC15C','\UC15D','\UC15E','\UC15F','\UC160','\UC161','\UC162','\UC163','\UC164','\UC165','\UC166','\UC167','\UC168','\UC169','\UC16A','\UC16B','\UC16C','\UC16D','\UC16E','\UC16F','\UC170','\UC171','\UC172','\UC173','\UC174','\UC175','\UC176','\UC177','\UC178','\UC179','\UC17A','\UC17B','\UC17C','\UC17D','\UC17E','\UC17F','\UC180','\UC181','\UC182','\UC183','\UC184','\UC185','\UC186','\UC187','\UC188','\UC189','\UC18A','\UC18B','\UC18C','\UC18D','\UC18E','\UC18F','\UC190','\UC191','\UC192','\UC193','\UC194','\UC195','\UC196','\UC197','\UC198','\UC199','\UC19A','\UC19B','\UC19C','\UC19D','\UC19E','\UC19F','\UC1A0','\UC1A1','\UC1A2','\UC1A3','\UC1A4','\UC1A5','\UC1A6','\UC1A7','\UC1A8','\UC1A9','\UC1AA','\UC1AB','\UC1AC','\UC1AD','\UC1AE','\UC1AF','\UC1B0','\UC1B1','\UC1B2','\UC1B3','\UC1B4','\UC1B5','\UC1B6','\UC1B7','\UC1B8','\UC1B9','\UC1BA','\UC1BB','\UC1BC','\UC1BD','\UC1BE','\UC1BF','\UC1C0','\UC1C1','\UC1C2','\UC1C3','\UC1C4','\UC1C5','\UC1C6','\UC1C7','\UC1C8','\UC1C9','\UC1CA','\UC1CB','\UC1CC','\UC1CD','\UC1CE','\UC1CF','\UC1D0','\UC1D1','\UC1D2','\UC1D3','\UC1D4','\UC1D5','\UC1D6','\UC1D7','\UC1D8','\UC1D9','\UC1DA','\UC1DB','\UC1DC','\UC1DD','\UC1DE','\UC1DF','\UC1E0','\UC1E1','\UC1E2','\UC1E3','\UC1E4','\UC1E5','\UC1E6','\UC1E7','\UC1E8','\UC1E9','\UC1EA','\UC1EB','\UC1EC','\UC1ED','\UC1EE','\UC1EF','\UC1F0','\UC1F1','\UC1F2','\UC1F3','\UC1F4','\UC1F5','\UC1F6','\UC1F7','\UC1F8','\UC1F9','\UC1FA','\UC1FB','\UC1FC','\UC1FD','\UC1FE','\UC1FF','\UC200','\UC201','\UC202','\UC203','\UC204','\UC205','\UC206','\UC207','\UC208','\UC209','\UC20A','\UC20B','\UC20C','\UC20D','\UC20E','\UC20F','\UC210','\UC211','\UC212','\UC213','\UC214','\UC215','\UC216','\UC217','\UC218','\UC219','\UC21A','\UC21B','\UC21C','\UC21D','\UC21E','\UC21F','\UC220','\UC221','\UC222','\UC223','\UC224','\UC225','\UC226','\UC227','\UC228','\UC229','\UC22A','\UC22B','\UC22C','\UC22D','\UC22E','\UC22F','\UC230','\UC231','\UC232','\UC233','\UC234','\UC235','\UC236','\UC237','\UC238','\UC239','\UC23A','\UC23B','\UC23C','\UC23D','\UC23E','\UC23F','\UC240','\UC241','\UC242','\UC243','\UC244','\UC245','\UC246','\UC247','\UC248','\UC249','\UC24A','\UC24B','\UC24C','\UC24D','\UC24E','\UC24F','\UC250','\UC251','\UC252','\UC253','\UC254','\UC255','\UC256','\UC257','\UC258','\UC259','\UC25A','\UC25B','\UC25C','\UC25D','\UC25E','\UC25F','\UC260','\UC261','\UC262','\UC263','\UC264','\UC265','\UC266','\UC267','\UC268','\UC269','\UC26A','\UC26B','\UC26C','\UC26D','\UC26E','\UC26F','\UC270','\UC271','\UC272','\UC273','\UC274','\UC275','\UC276','\UC277','\UC278','\UC279','\UC27A','\UC27B','\UC27C','\UC27D','\UC27E','\UC27F','\UC280','\UC281','\UC282','\UC283','\UC284','\UC285','\UC286','\UC287','\UC288','\UC289','\UC28A','\UC28B','\UC28C','\UC28D','\UC28E','\UC28F','\UC290','\UC291','\UC292','\UC293','\UC294','\UC295','\UC296','\UC297','\UC298','\UC299','\UC29A','\UC29B','\UC29C','\UC29D','\UC29E','\UC29F','\UC2A0','\UC2A1','\UC2A2','\UC2A3','\UC2A4','\UC2A5','\UC2A6','\UC2A7','\UC2A8','\UC2A9','\UC2AA','\UC2AB','\UC2AC','\UC2AD','\UC2AE','\UC2AF','\UC2B0','\UC2B1','\UC2B2','\UC2B3','\UC2B4','\UC2B5','\UC2B6','\UC2B7','\UC2B8','\UC2B9','\UC2BA','\UC2BB','\UC2BC','\UC2BD','\UC2BE','\UC2BF','\UC2C0','\UC2C1','\UC2C2','\UC2C3','\UC2C4','\UC2C5','\UC2C6','\UC2C7','\UC2C8','\UC2C9','\UC2CA','\UC2CB','\UC2CC','\UC2CD','\UC2CE','\UC2CF','\UC2D0','\UC2D1','\UC2D2','\UC2D3','\UC2D4','\UC2D5','\UC2D6','\UC2D7','\UC2D8','\UC2D9','\UC2DA','\UC2DB','\UC2DC','\UC2DD','\UC2DE','\UC2DF','\UC2E0','\UC2E1','\UC2E2','\UC2E3','\UC2E4','\UC2E5','\UC2E6','\UC2E7','\UC2E8','\UC2E9','\UC2EA','\UC2EB','\UC2EC','\UC2ED','\UC2EE','\UC2EF','\UC2F0','\UC2F1','\UC2F2','\UC2F3','\UC2F4','\UC2F5','\UC2F6','\UC2F7','\UC2F8','\UC2F9','\UC2FA','\UC2FB','\UC2FC','\UC2FD','\UC2FE','\UC2FF','\UC300','\UC301','\UC302','\UC303','\UC304','\UC305','\UC306','\UC307','\UC308','\UC309','\UC30A','\UC30B','\UC30C','\UC30D','\UC30E','\UC30F','\UC310','\UC311','\UC312','\UC313','\UC314','\UC315','\UC316','\UC317','\UC318','\UC319','\UC31A','\UC31B','\UC31C','\UC31D','\UC31E','\UC31F','\UC320','\UC321','\UC322','\UC323','\UC324','\UC325','\UC326','\UC327','\UC328','\UC329','\UC32A','\UC32B','\UC32C','\UC32D','\UC32E','\UC32F','\UC330','\UC331','\UC332','\UC333','\UC334','\UC335','\UC336','\UC337','\UC338','\UC339','\UC33A','\UC33B','\UC33C','\UC33D','\UC33E','\UC33F','\UC340','\UC341','\UC342','\UC343','\UC344','\UC345','\UC346','\UC347','\UC348','\UC349','\UC34A','\UC34B','\UC34C','\UC34D','\UC34E','\UC34F','\UC350','\UC351','\UC352','\UC353','\UC354','\UC355','\UC356','\UC357','\UC358','\UC359','\UC35A','\UC35B','\UC35C','\UC35D','\UC35E','\UC35F','\UC360','\UC361','\UC362','\UC363','\UC364','\UC365','\UC366','\UC367','\UC368','\UC369','\UC36A','\UC36B','\UC36C','\UC36D','\UC36E','\UC36F','\UC370','\UC371','\UC372','\UC373','\UC374','\UC375','\UC376','\UC377','\UC378','\UC379','\UC37A','\UC37B','\UC37C','\UC37D','\UC37E','\UC37F','\UC380','\UC381','\UC382','\UC383','\UC384','\UC385','\UC386','\UC387','\UC388','\UC389','\UC38A','\UC38B','\UC38C','\UC38D','\UC38E','\UC38F','\UC390','\UC391','\UC392','\UC393','\UC394','\UC395','\UC396','\UC397','\UC398','\UC399','\UC39A','\UC39B','\UC39C','\UC39D','\UC39E','\UC39F','\UC3A0','\UC3A1','\UC3A2','\UC3A3','\UC3A4','\UC3A5','\UC3A6','\UC3A7','\UC3A8','\UC3A9','\UC3AA','\UC3AB','\UC3AC','\UC3AD','\UC3AE','\UC3AF','\UC3B0','\UC3B1','\UC3B2','\UC3B3','\UC3B4','\UC3B5','\UC3B6','\UC3B7','\UC3B8','\UC3B9','\UC3BA','\UC3BB','\UC3BC','\UC3BD','\UC3BE','\UC3BF','\UC3C0','\UC3C1','\UC3C2','\UC3C3','\UC3C4','\UC3C5','\UC3C6','\UC3C7','\UC3C8','\UC3C9','\UC3CA','\UC3CB','\UC3CC','\UC3CD','\UC3CE','\UC3CF','\UC3D0','\UC3D1','\UC3D2','\UC3D3','\UC3D4','\UC3D5','\UC3D6','\UC3D7','\UC3D8','\UC3D9','\UC3DA','\UC3DB','\UC3DC','\UC3DD','\UC3DE','\UC3DF','\UC3E0','\UC3E1','\UC3E2','\UC3E3','\UC3E4','\UC3E5','\UC3E6','\UC3E7','\UC3E8','\UC3E9','\UC3EA','\UC3EB','\UC3EC','\UC3ED','\UC3EE','\UC3EF','\UC3F0','\UC3F1','\UC3F2','\UC3F3','\UC3F4','\UC3F5','\UC3F6','\UC3F7','\UC3F8','\UC3F9','\UC3FA','\UC3FB','\UC3FC','\UC3FD','\UC3FE','\UC3FF','\UC400','\UC401','\UC402','\UC403','\UC404','\UC405','\UC406','\UC407','\UC408','\UC409','\UC40A','\UC40B','\UC40C','\UC40D','\UC40E','\UC40F','\UC410','\UC411','\UC412','\UC413','\UC414','\UC415','\UC416','\UC417','\UC418','\UC419','\UC41A','\UC41B','\UC41C','\UC41D','\UC41E','\UC41F','\UC420','\UC421','\UC422','\UC423','\UC424','\UC425','\UC426','\UC427','\UC428','\UC429','\UC42A','\UC42B','\UC42C','\UC42D','\UC42E','\UC42F','\UC430','\UC431','\UC432','\UC433','\UC434','\UC435','\UC436','\UC437','\UC438','\UC439','\UC43A','\UC43B','\UC43C','\UC43D','\UC43E','\UC43F','\UC440','\UC441','\UC442','\UC443','\UC444','\UC445','\UC446','\UC447','\UC448','\UC449','\UC44A','\UC44B','\UC44C','\UC44D','\UC44E','\UC44F','\UC450','\UC451','\UC452','\UC453','\UC454','\UC455','\UC456','\UC457','\UC458','\UC459','\UC45A','\UC45B','\UC45C','\UC45D','\UC45E','\UC45F','\UC460','\UC461','\UC462','\UC463','\UC464','\UC465','\UC466','\UC467','\UC468','\UC469','\UC46A','\UC46B','\UC46C','\UC46D','\UC46E','\UC46F','\UC470','\UC471','\UC472','\UC473','\UC474','\UC475','\UC476','\UC477','\UC478','\UC479','\UC47A','\UC47B','\UC47C','\UC47D','\UC47E','\UC47F','\UC480','\UC481','\UC482','\UC483','\UC484','\UC485','\UC486','\UC487','\UC488','\UC489','\UC48A','\UC48B','\UC48C','\UC48D','\UC48E','\UC48F','\UC490','\UC491','\UC492','\UC493','\UC494','\UC495','\UC496','\UC497','\UC498','\UC499','\UC49A','\UC49B','\UC49C','\UC49D','\UC49E','\UC49F','\UC4A0','\UC4A1','\UC4A2','\UC4A3','\UC4A4','\UC4A5','\UC4A6','\UC4A7','\UC4A8','\UC4A9','\UC4AA','\UC4AB','\UC4AC','\UC4AD','\UC4AE','\UC4AF','\UC4B0','\UC4B1','\UC4B2','\UC4B3','\UC4B4','\UC4B5','\UC4B6','\UC4B7','\UC4B8','\UC4B9','\UC4BA','\UC4BB','\UC4BC','\UC4BD','\UC4BE','\UC4BF','\UC4C0','\UC4C1','\UC4C2','\UC4C3','\UC4C4','\UC4C5','\UC4C6','\UC4C7','\UC4C8','\UC4C9','\UC4CA','\UC4CB','\UC4CC','\UC4CD','\UC4CE','\UC4CF','\UC4D0','\UC4D1','\UC4D2','\UC4D3','\UC4D4','\UC4D5','\UC4D6','\UC4D7','\UC4D8','\UC4D9','\UC4DA','\UC4DB','\UC4DC','\UC4DD','\UC4DE','\UC4DF','\UC4E0','\UC4E1','\UC4E2','\UC4E3','\UC4E4','\UC4E5','\UC4E6','\UC4E7','\UC4E8','\UC4E9','\UC4EA','\UC4EB','\UC4EC','\UC4ED','\UC4EE','\UC4EF','\UC4F0','\UC4F1','\UC4F2','\UC4F3','\UC4F4','\UC4F5','\UC4F6','\UC4F7','\UC4F8','\UC4F9','\UC4FA','\UC4FB','\UC4FC','\UC4FD','\UC4FE','\UC4FF','\UC500','\UC501','\UC502','\UC503','\UC504','\UC505','\UC506','\UC507','\UC508','\UC509','\UC50A','\UC50B','\UC50C','\UC50D','\UC50E','\UC50F','\UC510','\UC511','\UC512','\UC513','\UC514','\UC515','\UC516','\UC517','\UC518','\UC519','\UC51A','\UC51B','\UC51C','\UC51D','\UC51E','\UC51F','\UC520','\UC521','\UC522','\UC523','\UC524','\UC525','\UC526','\UC527','\UC528','\UC529','\UC52A','\UC52B','\UC52C','\UC52D','\UC52E','\UC52F','\UC530','\UC531','\UC532','\UC533','\UC534','\UC535','\UC536','\UC537','\UC538','\UC539','\UC53A','\UC53B','\UC53C','\UC53D','\UC53E','\UC53F','\UC540','\UC541','\UC542','\UC543','\UC544','\UC545','\UC546','\UC547','\UC548','\UC549','\UC54A','\UC54B','\UC54C','\UC54D','\UC54E','\UC54F','\UC550','\UC551','\UC552','\UC553','\UC554','\UC555','\UC556','\UC557','\UC558','\UC559','\UC55A','\UC55B','\UC55C','\UC55D','\UC55E','\UC55F','\UC560','\UC561','\UC562','\UC563','\UC564','\UC565','\UC566','\UC567','\UC568','\UC569','\UC56A','\UC56B','\UC56C','\UC56D','\UC56E','\UC56F','\UC570','\UC571','\UC572','\UC573','\UC574','\UC575','\UC576','\UC577','\UC578','\UC579','\UC57A','\UC57B','\UC57C','\UC57D','\UC57E','\UC57F','\UC580','\UC581','\UC582','\UC583','\UC584','\UC585','\UC586','\UC587','\UC588','\UC589','\UC58A','\UC58B','\UC58C','\UC58D','\UC58E','\UC58F','\UC590','\UC591','\UC592','\UC593','\UC594','\UC595','\UC596','\UC597','\UC598','\UC599','\UC59A','\UC59B','\UC59C','\UC59D','\UC59E','\UC59F','\UC5A0','\UC5A1','\UC5A2','\UC5A3','\UC5A4','\UC5A5','\UC5A6','\UC5A7','\UC5A8','\UC5A9','\UC5AA','\UC5AB','\UC5AC','\UC5AD','\UC5AE','\UC5AF','\UC5B0','\UC5B1','\UC5B2','\UC5B3','\UC5B4','\UC5B5','\UC5B6','\UC5B7','\UC5B8','\UC5B9','\UC5BA','\UC5BB','\UC5BC','\UC5BD','\UC5BE','\UC5BF','\UC5C0','\UC5C1','\UC5C2','\UC5C3','\UC5C4','\UC5C5','\UC5C6','\UC5C7','\UC5C8','\UC5C9','\UC5CA','\UC5CB','\UC5CC','\UC5CD','\UC5CE','\UC5CF','\UC5D0','\UC5D1','\UC5D2','\UC5D3','\UC5D4','\UC5D5','\UC5D6','\UC5D7','\UC5D8','\UC5D9','\UC5DA','\UC5DB','\UC5DC','\UC5DD','\UC5DE','\UC5DF','\UC5E0','\UC5E1','\UC5E2','\UC5E3','\UC5E4','\UC5E5','\UC5E6','\UC5E7','\UC5E8','\UC5E9','\UC5EA','\UC5EB','\UC5EC','\UC5ED','\UC5EE','\UC5EF','\UC5F0','\UC5F1','\UC5F2','\UC5F3','\UC5F4','\UC5F5','\UC5F6','\UC5F7','\UC5F8','\UC5F9','\UC5FA','\UC5FB','\UC5FC','\UC5FD','\UC5FE','\UC5FF','\UC600','\UC601','\UC602','\UC603','\UC604','\UC605','\UC606','\UC607','\UC608','\UC609','\UC60A','\UC60B','\UC60C','\UC60D','\UC60E','\UC60F','\UC610','\UC611','\UC612','\UC613','\UC614','\UC615','\UC616','\UC617','\UC618','\UC619','\UC61A','\UC61B','\UC61C','\UC61D','\UC61E','\UC61F','\UC620','\UC621','\UC622','\UC623','\UC624','\UC625','\UC626','\UC627','\UC628','\UC629','\UC62A','\UC62B','\UC62C','\UC62D','\UC62E','\UC62F','\UC630','\UC631','\UC632','\UC633','\UC634','\UC635','\UC636','\UC637','\UC638','\UC639','\UC63A','\UC63B','\UC63C','\UC63D','\UC63E','\UC63F','\UC640','\UC641','\UC642','\UC643','\UC644','\UC645','\UC646','\UC647','\UC648','\UC649','\UC64A','\UC64B','\UC64C','\UC64D','\UC64E','\UC64F','\UC650','\UC651','\UC652','\UC653','\UC654','\UC655','\UC656','\UC657','\UC658','\UC659','\UC65A','\UC65B','\UC65C','\UC65D','\UC65E','\UC65F','\UC660','\UC661','\UC662','\UC663','\UC664','\UC665','\UC666','\UC667','\UC668','\UC669','\UC66A','\UC66B','\UC66C','\UC66D','\UC66E','\UC66F','\UC670','\UC671','\UC672','\UC673','\UC674','\UC675','\UC676','\UC677','\UC678','\UC679','\UC67A','\UC67B','\UC67C','\UC67D','\UC67E','\UC67F','\UC680','\UC681','\UC682','\UC683','\UC684','\UC685','\UC686','\UC687','\UC688','\UC689','\UC68A','\UC68B','\UC68C','\UC68D','\UC68E','\UC68F','\UC690','\UC691','\UC692','\UC693','\UC694','\UC695','\UC696','\UC697','\UC698','\UC699','\UC69A','\UC69B','\UC69C','\UC69D','\UC69E','\UC69F','\UC6A0','\UC6A1','\UC6A2','\UC6A3','\UC6A4','\UC6A5','\UC6A6','\UC6A7','\UC6A8','\UC6A9','\UC6AA','\UC6AB','\UC6AC','\UC6AD','\UC6AE','\UC6AF','\UC6B0','\UC6B1','\UC6B2','\UC6B3','\UC6B4','\UC6B5','\UC6B6','\UC6B7','\UC6B8','\UC6B9','\UC6BA','\UC6BB','\UC6BC','\UC6BD','\UC6BE','\UC6BF','\UC6C0','\UC6C1','\UC6C2','\UC6C3','\UC6C4','\UC6C5','\UC6C6','\UC6C7','\UC6C8','\UC6C9','\UC6CA','\UC6CB','\UC6CC','\UC6CD','\UC6CE','\UC6CF','\UC6D0','\UC6D1','\UC6D2','\UC6D3','\UC6D4','\UC6D5','\UC6D6','\UC6D7','\UC6D8','\UC6D9','\UC6DA','\UC6DB','\UC6DC','\UC6DD','\UC6DE','\UC6DF','\UC6E0','\UC6E1','\UC6E2','\UC6E3','\UC6E4','\UC6E5','\UC6E6','\UC6E7','\UC6E8','\UC6E9','\UC6EA','\UC6EB','\UC6EC','\UC6ED','\UC6EE','\UC6EF','\UC6F0','\UC6F1','\UC6F2','\UC6F3','\UC6F4','\UC6F5','\UC6F6','\UC6F7','\UC6F8','\UC6F9','\UC6FA','\UC6FB','\UC6FC','\UC6FD','\UC6FE','\UC6FF','\UC700','\UC701','\UC702','\UC703','\UC704','\UC705','\UC706','\UC707','\UC708','\UC709','\UC70A','\UC70B','\UC70C','\UC70D','\UC70E','\UC70F','\UC710','\UC711','\UC712','\UC713','\UC714','\UC715','\UC716','\UC717','\UC718','\UC719','\UC71A','\UC71B','\UC71C','\UC71D','\UC71E','\UC71F','\UC720','\UC721','\UC722','\UC723','\UC724','\UC725','\UC726','\UC727','\UC728','\UC729','\UC72A','\UC72B','\UC72C','\UC72D','\UC72E','\UC72F','\UC730','\UC731','\UC732','\UC733','\UC734','\UC735','\UC736','\UC737','\UC738','\UC739','\UC73A','\UC73B','\UC73C','\UC73D','\UC73E','\UC73F','\UC740','\UC741','\UC742','\UC743','\UC744','\UC745','\UC746','\UC747','\UC748','\UC749','\UC74A','\UC74B','\UC74C','\UC74D','\UC74E','\UC74F','\UC750','\UC751','\UC752','\UC753','\UC754','\UC755','\UC756','\UC757','\UC758','\UC759','\UC75A','\UC75B','\UC75C','\UC75D','\UC75E','\UC75F','\UC760','\UC761','\UC762','\UC763','\UC764','\UC765','\UC766','\UC767','\UC768','\UC769','\UC76A','\UC76B','\UC76C','\UC76D','\UC76E','\UC76F','\UC770','\UC771','\UC772','\UC773','\UC774','\UC775','\UC776','\UC777','\UC778','\UC779','\UC77A','\UC77B','\UC77C','\UC77D','\UC77E','\UC77F','\UC780','\UC781','\UC782','\UC783','\UC784','\UC785','\UC786','\UC787','\UC788','\UC789','\UC78A','\UC78B','\UC78C','\UC78D','\UC78E','\UC78F','\UC790','\UC791','\UC792','\UC793','\UC794','\UC795','\UC796','\UC797','\UC798','\UC799','\UC79A','\UC79B','\UC79C','\UC79D','\UC79E','\UC79F','\UC7A0','\UC7A1','\UC7A2','\UC7A3','\UC7A4','\UC7A5','\UC7A6','\UC7A7','\UC7A8','\UC7A9','\UC7AA','\UC7AB','\UC7AC','\UC7AD','\UC7AE','\UC7AF','\UC7B0','\UC7B1','\UC7B2','\UC7B3','\UC7B4','\UC7B5','\UC7B6','\UC7B7','\UC7B8','\UC7B9','\UC7BA','\UC7BB','\UC7BC','\UC7BD','\UC7BE','\UC7BF','\UC7C0','\UC7C1','\UC7C2','\UC7C3','\UC7C4','\UC7C5','\UC7C6','\UC7C7','\UC7C8','\UC7C9','\UC7CA','\UC7CB','\UC7CC','\UC7CD','\UC7CE','\UC7CF','\UC7D0','\UC7D1','\UC7D2','\UC7D3','\UC7D4','\UC7D5','\UC7D6','\UC7D7','\UC7D8','\UC7D9','\UC7DA','\UC7DB','\UC7DC','\UC7DD','\UC7DE','\UC7DF','\UC7E0','\UC7E1','\UC7E2','\UC7E3','\UC7E4','\UC7E5','\UC7E6','\UC7E7','\UC7E8','\UC7E9','\UC7EA','\UC7EB','\UC7EC','\UC7ED','\UC7EE','\UC7EF','\UC7F0','\UC7F1','\UC7F2','\UC7F3','\UC7F4','\UC7F5','\UC7F6','\UC7F7','\UC7F8','\UC7F9','\UC7FA','\UC7FB','\UC7FC','\UC7FD','\UC7FE','\UC7FF','\UC800','\UC801','\UC802','\UC803','\UC804','\UC805','\UC806','\UC807','\UC808','\UC809','\UC80A','\UC80B','\UC80C','\UC80D','\UC80E','\UC80F','\UC810','\UC811','\UC812','\UC813','\UC814','\UC815','\UC816','\UC817','\UC818','\UC819','\UC81A','\UC81B','\UC81C','\UC81D','\UC81E','\UC81F','\UC820','\UC821','\UC822','\UC823','\UC824','\UC825','\UC826','\UC827','\UC828','\UC829','\UC82A','\UC82B','\UC82C','\UC82D','\UC82E','\UC82F','\UC830','\UC831','\UC832','\UC833','\UC834','\UC835','\UC836','\UC837','\UC838','\UC839','\UC83A','\UC83B','\UC83C','\UC83D','\UC83E','\UC83F','\UC840','\UC841','\UC842','\UC843','\UC844','\UC845','\UC846','\UC847','\UC848','\UC849','\UC84A','\UC84B','\UC84C','\UC84D','\UC84E','\UC84F','\UC850','\UC851','\UC852','\UC853','\UC854','\UC855','\UC856','\UC857','\UC858','\UC859','\UC85A','\UC85B','\UC85C','\UC85D','\UC85E','\UC85F','\UC860','\UC861','\UC862','\UC863','\UC864','\UC865','\UC866','\UC867','\UC868','\UC869','\UC86A','\UC86B','\UC86C','\UC86D','\UC86E','\UC86F','\UC870','\UC871','\UC872','\UC873','\UC874','\UC875','\UC876','\UC877','\UC878','\UC879','\UC87A','\UC87B','\UC87C','\UC87D','\UC87E','\UC87F','\UC880','\UC881','\UC882','\UC883','\UC884','\UC885','\UC886','\UC887','\UC888','\UC889','\UC88A','\UC88B','\UC88C','\UC88D','\UC88E','\UC88F','\UC890','\UC891','\UC892','\UC893','\UC894','\UC895','\UC896','\UC897','\UC898','\UC899','\UC89A','\UC89B','\UC89C','\UC89D','\UC89E','\UC89F','\UC8A0','\UC8A1','\UC8A2','\UC8A3','\UC8A4','\UC8A5','\UC8A6','\UC8A7','\UC8A8','\UC8A9','\UC8AA','\UC8AB','\UC8AC','\UC8AD','\UC8AE','\UC8AF','\UC8B0','\UC8B1','\UC8B2','\UC8B3','\UC8B4','\UC8B5','\UC8B6','\UC8B7','\UC8B8','\UC8B9','\UC8BA','\UC8BB','\UC8BC','\UC8BD','\UC8BE','\UC8BF','\UC8C0','\UC8C1','\UC8C2','\UC8C3','\UC8C4','\UC8C5','\UC8C6','\UC8C7','\UC8C8','\UC8C9','\UC8CA','\UC8CB','\UC8CC','\UC8CD','\UC8CE','\UC8CF','\UC8D0','\UC8D1','\UC8D2','\UC8D3','\UC8D4','\UC8D5','\UC8D6','\UC8D7','\UC8D8','\UC8D9','\UC8DA','\UC8DB','\UC8DC','\UC8DD','\UC8DE','\UC8DF','\UC8E0','\UC8E1','\UC8E2','\UC8E3','\UC8E4','\UC8E5','\UC8E6','\UC8E7','\UC8E8','\UC8E9','\UC8EA','\UC8EB','\UC8EC','\UC8ED','\UC8EE','\UC8EF','\UC8F0','\UC8F1','\UC8F2','\UC8F3','\UC8F4','\UC8F5','\UC8F6','\UC8F7','\UC8F8','\UC8F9','\UC8FA','\UC8FB','\UC8FC','\UC8FD','\UC8FE','\UC8FF','\UC900','\UC901','\UC902','\UC903','\UC904','\UC905','\UC906','\UC907','\UC908','\UC909','\UC90A','\UC90B','\UC90C','\UC90D','\UC90E','\UC90F','\UC910','\UC911','\UC912','\UC913','\UC914','\UC915','\UC916','\UC917','\UC918','\UC919','\UC91A','\UC91B','\UC91C','\UC91D','\UC91E','\UC91F','\UC920','\UC921','\UC922','\UC923','\UC924','\UC925','\UC926','\UC927','\UC928','\UC929','\UC92A','\UC92B','\UC92C','\UC92D','\UC92E','\UC92F','\UC930','\UC931','\UC932','\UC933','\UC934','\UC935','\UC936','\UC937','\UC938','\UC939','\UC93A','\UC93B','\UC93C','\UC93D','\UC93E','\UC93F','\UC940','\UC941','\UC942','\UC943','\UC944','\UC945','\UC946','\UC947','\UC948','\UC949','\UC94A','\UC94B','\UC94C','\UC94D','\UC94E','\UC94F','\UC950','\UC951','\UC952','\UC953','\UC954','\UC955','\UC956','\UC957','\UC958','\UC959','\UC95A','\UC95B','\UC95C','\UC95D','\UC95E','\UC95F','\UC960','\UC961','\UC962','\UC963','\UC964','\UC965','\UC966','\UC967','\UC968','\UC969','\UC96A','\UC96B','\UC96C','\UC96D','\UC96E','\UC96F','\UC970','\UC971','\UC972','\UC973','\UC974','\UC975','\UC976','\UC977','\UC978','\UC979','\UC97A','\UC97B','\UC97C','\UC97D','\UC97E','\UC97F','\UC980','\UC981','\UC982','\UC983','\UC984','\UC985','\UC986','\UC987','\UC988','\UC989','\UC98A','\UC98B','\UC98C','\UC98D','\UC98E','\UC98F','\UC990','\UC991','\UC992','\UC993','\UC994','\UC995','\UC996','\UC997','\UC998','\UC999','\UC99A','\UC99B','\UC99C','\UC99D','\UC99E','\UC99F','\UC9A0','\UC9A1','\UC9A2','\UC9A3','\UC9A4','\UC9A5','\UC9A6','\UC9A7','\UC9A8','\UC9A9','\UC9AA','\UC9AB','\UC9AC','\UC9AD','\UC9AE','\UC9AF','\UC9B0','\UC9B1','\UC9B2','\UC9B3','\UC9B4','\UC9B5','\UC9B6','\UC9B7','\UC9B8','\UC9B9','\UC9BA','\UC9BB','\UC9BC','\UC9BD','\UC9BE','\UC9BF','\UC9C0','\UC9C1','\UC9C2','\UC9C3','\UC9C4','\UC9C5','\UC9C6','\UC9C7','\UC9C8','\UC9C9','\UC9CA','\UC9CB','\UC9CC','\UC9CD','\UC9CE','\UC9CF','\UC9D0','\UC9D1','\UC9D2','\UC9D3','\UC9D4','\UC9D5','\UC9D6','\UC9D7','\UC9D8','\UC9D9','\UC9DA','\UC9DB','\UC9DC','\UC9DD','\UC9DE','\UC9DF','\UC9E0','\UC9E1','\UC9E2','\UC9E3','\UC9E4','\UC9E5','\UC9E6','\UC9E7','\UC9E8','\UC9E9','\UC9EA','\UC9EB','\UC9EC','\UC9ED','\UC9EE','\UC9EF','\UC9F0','\UC9F1','\UC9F2','\UC9F3','\UC9F4','\UC9F5','\UC9F6','\UC9F7','\UC9F8','\UC9F9','\UC9FA','\UC9FB','\UC9FC','\UC9FD','\UC9FE','\UC9FF','\UCA00','\UCA01','\UCA02','\UCA03','\UCA04','\UCA05','\UCA06','\UCA07','\UCA08','\UCA09','\UCA0A','\UCA0B','\UCA0C','\UCA0D','\UCA0E','\UCA0F','\UCA10','\UCA11','\UCA12','\UCA13','\UCA14','\UCA15','\UCA16','\UCA17','\UCA18','\UCA19','\UCA1A','\UCA1B','\UCA1C','\UCA1D','\UCA1E','\UCA1F','\UCA20','\UCA21','\UCA22','\UCA23','\UCA24','\UCA25','\UCA26','\UCA27','\UCA28','\UCA29','\UCA2A','\UCA2B','\UCA2C','\UCA2D','\UCA2E','\UCA2F','\UCA30','\UCA31','\UCA32','\UCA33','\UCA34','\UCA35','\UCA36','\UCA37','\UCA38','\UCA39','\UCA3A','\UCA3B','\UCA3C','\UCA3D','\UCA3E','\UCA3F','\UCA40','\UCA41','\UCA42','\UCA43','\UCA44','\UCA45','\UCA46','\UCA47','\UCA48','\UCA49','\UCA4A','\UCA4B','\UCA4C','\UCA4D','\UCA4E','\UCA4F','\UCA50','\UCA51','\UCA52','\UCA53','\UCA54','\UCA55','\UCA56','\UCA57','\UCA58','\UCA59','\UCA5A','\UCA5B','\UCA5C','\UCA5D','\UCA5E','\UCA5F','\UCA60','\UCA61','\UCA62','\UCA63','\UCA64','\UCA65','\UCA66','\UCA67','\UCA68','\UCA69','\UCA6A','\UCA6B','\UCA6C','\UCA6D','\UCA6E','\UCA6F','\UCA70','\UCA71','\UCA72','\UCA73','\UCA74','\UCA75','\UCA76','\UCA77','\UCA78','\UCA79','\UCA7A','\UCA7B','\UCA7C','\UCA7D','\UCA7E','\UCA7F','\UCA80','\UCA81','\UCA82','\UCA83','\UCA84','\UCA85','\UCA86','\UCA87','\UCA88','\UCA89','\UCA8A','\UCA8B','\UCA8C','\UCA8D','\UCA8E','\UCA8F','\UCA90','\UCA91','\UCA92','\UCA93','\UCA94','\UCA95','\UCA96','\UCA97','\UCA98','\UCA99','\UCA9A','\UCA9B','\UCA9C','\UCA9D','\UCA9E','\UCA9F','\UCAA0','\UCAA1','\UCAA2','\UCAA3','\UCAA4','\UCAA5','\UCAA6','\UCAA7','\UCAA8','\UCAA9','\UCAAA','\UCAAB','\UCAAC','\UCAAD','\UCAAE','\UCAAF','\UCAB0','\UCAB1','\UCAB2','\UCAB3','\UCAB4','\UCAB5','\UCAB6','\UCAB7','\UCAB8','\UCAB9','\UCABA','\UCABB','\UCABC','\UCABD','\UCABE','\UCABF','\UCAC0','\UCAC1','\UCAC2','\UCAC3','\UCAC4','\UCAC5','\UCAC6','\UCAC7','\UCAC8','\UCAC9','\UCACA','\UCACB','\UCACC','\UCACD','\UCACE','\UCACF','\UCAD0','\UCAD1','\UCAD2','\UCAD3','\UCAD4','\UCAD5','\UCAD6','\UCAD7','\UCAD8','\UCAD9','\UCADA','\UCADB','\UCADC','\UCADD','\UCADE','\UCADF','\UCAE0','\UCAE1','\UCAE2','\UCAE3','\UCAE4','\UCAE5','\UCAE6','\UCAE7','\UCAE8','\UCAE9','\UCAEA','\UCAEB','\UCAEC','\UCAED','\UCAEE','\UCAEF','\UCAF0','\UCAF1','\UCAF2','\UCAF3','\UCAF4','\UCAF5','\UCAF6','\UCAF7','\UCAF8','\UCAF9','\UCAFA','\UCAFB','\UCAFC','\UCAFD','\UCAFE','\UCAFF','\UCB00','\UCB01','\UCB02','\UCB03','\UCB04','\UCB05','\UCB06','\UCB07','\UCB08','\UCB09','\UCB0A','\UCB0B','\UCB0C','\UCB0D','\UCB0E','\UCB0F','\UCB10','\UCB11','\UCB12','\UCB13','\UCB14','\UCB15','\UCB16','\UCB17','\UCB18','\UCB19','\UCB1A','\UCB1B','\UCB1C','\UCB1D','\UCB1E','\UCB1F','\UCB20','\UCB21','\UCB22','\UCB23','\UCB24','\UCB25','\UCB26','\UCB27','\UCB28','\UCB29','\UCB2A','\UCB2B','\UCB2C','\UCB2D','\UCB2E','\UCB2F','\UCB30','\UCB31','\UCB32','\UCB33','\UCB34','\UCB35','\UCB36','\UCB37','\UCB38','\UCB39','\UCB3A','\UCB3B','\UCB3C','\UCB3D','\UCB3E','\UCB3F','\UCB40','\UCB41','\UCB42','\UCB43','\UCB44','\UCB45','\UCB46','\UCB47','\UCB48','\UCB49','\UCB4A','\UCB4B','\UCB4C','\UCB4D','\UCB4E','\UCB4F','\UCB50','\UCB51','\UCB52','\UCB53','\UCB54','\UCB55','\UCB56','\UCB57','\UCB58','\UCB59','\UCB5A','\UCB5B','\UCB5C','\UCB5D','\UCB5E','\UCB5F','\UCB60','\UCB61','\UCB62','\UCB63','\UCB64','\UCB65','\UCB66','\UCB67','\UCB68','\UCB69','\UCB6A','\UCB6B','\UCB6C','\UCB6D','\UCB6E','\UCB6F','\UCB70','\UCB71','\UCB72','\UCB73','\UCB74','\UCB75','\UCB76','\UCB77','\UCB78','\UCB79','\UCB7A','\UCB7B','\UCB7C','\UCB7D','\UCB7E','\UCB7F','\UCB80','\UCB81','\UCB82','\UCB83','\UCB84','\UCB85','\UCB86','\UCB87','\UCB88','\UCB89','\UCB8A','\UCB8B','\UCB8C','\UCB8D','\UCB8E','\UCB8F','\UCB90','\UCB91','\UCB92','\UCB93','\UCB94','\UCB95','\UCB96','\UCB97','\UCB98','\UCB99','\UCB9A','\UCB9B','\UCB9C','\UCB9D','\UCB9E','\UCB9F','\UCBA0','\UCBA1','\UCBA2','\UCBA3','\UCBA4','\UCBA5','\UCBA6','\UCBA7','\UCBA8','\UCBA9','\UCBAA','\UCBAB','\UCBAC','\UCBAD','\UCBAE','\UCBAF','\UCBB0','\UCBB1','\UCBB2','\UCBB3','\UCBB4','\UCBB5','\UCBB6','\UCBB7','\UCBB8','\UCBB9','\UCBBA','\UCBBB','\UCBBC','\UCBBD','\UCBBE','\UCBBF','\UCBC0','\UCBC1','\UCBC2','\UCBC3','\UCBC4','\UCBC5','\UCBC6','\UCBC7','\UCBC8','\UCBC9','\UCBCA','\UCBCB','\UCBCC','\UCBCD','\UCBCE','\UCBCF','\UCBD0','\UCBD1','\UCBD2','\UCBD3','\UCBD4','\UCBD5','\UCBD6','\UCBD7','\UCBD8','\UCBD9','\UCBDA','\UCBDB','\UCBDC','\UCBDD','\UCBDE','\UCBDF','\UCBE0','\UCBE1','\UCBE2','\UCBE3','\UCBE4','\UCBE5','\UCBE6','\UCBE7','\UCBE8','\UCBE9','\UCBEA','\UCBEB','\UCBEC','\UCBED','\UCBEE','\UCBEF','\UCBF0','\UCBF1','\UCBF2','\UCBF3','\UCBF4','\UCBF5','\UCBF6','\UCBF7','\UCBF8','\UCBF9','\UCBFA','\UCBFB','\UCBFC','\UCBFD','\UCBFE','\UCBFF','\UCC00','\UCC01','\UCC02','\UCC03','\UCC04','\UCC05','\UCC06','\UCC07','\UCC08','\UCC09','\UCC0A','\UCC0B','\UCC0C','\UCC0D','\UCC0E','\UCC0F','\UCC10','\UCC11','\UCC12','\UCC13','\UCC14','\UCC15','\UCC16','\UCC17','\UCC18','\UCC19','\UCC1A','\UCC1B','\UCC1C','\UCC1D','\UCC1E','\UCC1F','\UCC20','\UCC21','\UCC22','\UCC23','\UCC24','\UCC25','\UCC26','\UCC27','\UCC28','\UCC29','\UCC2A','\UCC2B','\UCC2C','\UCC2D','\UCC2E','\UCC2F','\UCC30','\UCC31','\UCC32','\UCC33','\UCC34','\UCC35','\UCC36','\UCC37','\UCC38','\UCC39','\UCC3A','\UCC3B','\UCC3C','\UCC3D','\UCC3E','\UCC3F','\UCC40','\UCC41','\UCC42','\UCC43','\UCC44','\UCC45','\UCC46','\UCC47','\UCC48','\UCC49','\UCC4A','\UCC4B','\UCC4C','\UCC4D','\UCC4E','\UCC4F','\UCC50','\UCC51','\UCC52','\UCC53','\UCC54','\UCC55','\UCC56','\UCC57','\UCC58','\UCC59','\UCC5A','\UCC5B','\UCC5C','\UCC5D','\UCC5E','\UCC5F','\UCC60','\UCC61','\UCC62','\UCC63','\UCC64','\UCC65','\UCC66','\UCC67','\UCC68','\UCC69','\UCC6A','\UCC6B','\UCC6C','\UCC6D','\UCC6E','\UCC6F','\UCC70','\UCC71','\UCC72','\UCC73','\UCC74','\UCC75','\UCC76','\UCC77','\UCC78','\UCC79','\UCC7A','\UCC7B','\UCC7C','\UCC7D','\UCC7E','\UCC7F','\UCC80','\UCC81','\UCC82','\UCC83','\UCC84','\UCC85','\UCC86','\UCC87','\UCC88','\UCC89','\UCC8A','\UCC8B','\UCC8C','\UCC8D','\UCC8E','\UCC8F','\UCC90','\UCC91','\UCC92','\UCC93','\UCC94','\UCC95','\UCC96','\UCC97','\UCC98','\UCC99','\UCC9A','\UCC9B','\UCC9C','\UCC9D','\UCC9E','\UCC9F','\UCCA0','\UCCA1','\UCCA2','\UCCA3','\UCCA4','\UCCA5','\UCCA6','\UCCA7','\UCCA8','\UCCA9','\UCCAA','\UCCAB','\UCCAC','\UCCAD','\UCCAE','\UCCAF','\UCCB0','\UCCB1','\UCCB2','\UCCB3','\UCCB4','\UCCB5','\UCCB6','\UCCB7','\UCCB8','\UCCB9','\UCCBA','\UCCBB','\UCCBC','\UCCBD','\UCCBE','\UCCBF','\UCCC0','\UCCC1','\UCCC2','\UCCC3','\UCCC4','\UCCC5','\UCCC6','\UCCC7','\UCCC8','\UCCC9','\UCCCA','\UCCCB','\UCCCC','\UCCCD','\UCCCE','\UCCCF','\UCCD0','\UCCD1','\UCCD2','\UCCD3','\UCCD4','\UCCD5','\UCCD6','\UCCD7','\UCCD8','\UCCD9','\UCCDA','\UCCDB','\UCCDC','\UCCDD','\UCCDE','\UCCDF','\UCCE0','\UCCE1','\UCCE2','\UCCE3','\UCCE4','\UCCE5','\UCCE6','\UCCE7','\UCCE8','\UCCE9','\UCCEA','\UCCEB','\UCCEC','\UCCED','\UCCEE','\UCCEF','\UCCF0','\UCCF1','\UCCF2','\UCCF3','\UCCF4','\UCCF5','\UCCF6','\UCCF7','\UCCF8','\UCCF9','\UCCFA','\UCCFB','\UCCFC','\UCCFD','\UCCFE','\UCCFF','\UCD00','\UCD01','\UCD02','\UCD03','\UCD04','\UCD05','\UCD06','\UCD07','\UCD08','\UCD09','\UCD0A','\UCD0B','\UCD0C','\UCD0D','\UCD0E','\UCD0F','\UCD10','\UCD11','\UCD12','\UCD13','\UCD14','\UCD15','\UCD16','\UCD17','\UCD18','\UCD19','\UCD1A','\UCD1B','\UCD1C','\UCD1D','\UCD1E','\UCD1F','\UCD20','\UCD21','\UCD22','\UCD23','\UCD24','\UCD25','\UCD26','\UCD27','\UCD28','\UCD29','\UCD2A','\UCD2B','\UCD2C','\UCD2D','\UCD2E','\UCD2F','\UCD30','\UCD31','\UCD32','\UCD33','\UCD34','\UCD35','\UCD36','\UCD37','\UCD38','\UCD39','\UCD3A','\UCD3B','\UCD3C','\UCD3D','\UCD3E','\UCD3F','\UCD40','\UCD41','\UCD42','\UCD43','\UCD44','\UCD45','\UCD46','\UCD47','\UCD48','\UCD49','\UCD4A','\UCD4B','\UCD4C','\UCD4D','\UCD4E','\UCD4F','\UCD50','\UCD51','\UCD52','\UCD53','\UCD54','\UCD55','\UCD56','\UCD57','\UCD58','\UCD59','\UCD5A','\UCD5B','\UCD5C','\UCD5D','\UCD5E','\UCD5F','\UCD60','\UCD61','\UCD62','\UCD63','\UCD64','\UCD65','\UCD66','\UCD67','\UCD68','\UCD69','\UCD6A','\UCD6B','\UCD6C','\UCD6D','\UCD6E','\UCD6F','\UCD70','\UCD71','\UCD72','\UCD73','\UCD74','\UCD75','\UCD76','\UCD77','\UCD78','\UCD79','\UCD7A','\UCD7B','\UCD7C','\UCD7D','\UCD7E','\UCD7F','\UCD80','\UCD81','\UCD82','\UCD83','\UCD84','\UCD85','\UCD86','\UCD87','\UCD88','\UCD89','\UCD8A','\UCD8B','\UCD8C','\UCD8D','\UCD8E','\UCD8F','\UCD90','\UCD91','\UCD92','\UCD93','\UCD94','\UCD95','\UCD96','\UCD97','\UCD98','\UCD99','\UCD9A','\UCD9B','\UCD9C','\UCD9D','\UCD9E','\UCD9F','\UCDA0','\UCDA1','\UCDA2','\UCDA3','\UCDA4','\UCDA5','\UCDA6','\UCDA7','\UCDA8','\UCDA9','\UCDAA','\UCDAB','\UCDAC','\UCDAD','\UCDAE','\UCDAF','\UCDB0','\UCDB1','\UCDB2','\UCDB3','\UCDB4','\UCDB5','\UCDB6','\UCDB7','\UCDB8','\UCDB9','\UCDBA','\UCDBB','\UCDBC','\UCDBD','\UCDBE','\UCDBF','\UCDC0','\UCDC1','\UCDC2','\UCDC3','\UCDC4','\UCDC5','\UCDC6','\UCDC7','\UCDC8','\UCDC9','\UCDCA','\UCDCB','\UCDCC','\UCDCD','\UCDCE','\UCDCF','\UCDD0','\UCDD1','\UCDD2','\UCDD3','\UCDD4','\UCDD5','\UCDD6','\UCDD7','\UCDD8','\UCDD9','\UCDDA','\UCDDB','\UCDDC','\UCDDD','\UCDDE','\UCDDF','\UCDE0','\UCDE1','\UCDE2','\UCDE3','\UCDE4','\UCDE5','\UCDE6','\UCDE7','\UCDE8','\UCDE9','\UCDEA','\UCDEB','\UCDEC','\UCDED','\UCDEE','\UCDEF','\UCDF0','\UCDF1','\UCDF2','\UCDF3','\UCDF4','\UCDF5','\UCDF6','\UCDF7','\UCDF8','\UCDF9','\UCDFA','\UCDFB','\UCDFC','\UCDFD','\UCDFE','\UCDFF','\UCE00','\UCE01','\UCE02','\UCE03','\UCE04','\UCE05','\UCE06','\UCE07','\UCE08','\UCE09','\UCE0A','\UCE0B','\UCE0C','\UCE0D','\UCE0E','\UCE0F','\UCE10','\UCE11','\UCE12','\UCE13','\UCE14','\UCE15','\UCE16','\UCE17','\UCE18','\UCE19','\UCE1A','\UCE1B','\UCE1C','\UCE1D','\UCE1E','\UCE1F','\UCE20','\UCE21','\UCE22','\UCE23','\UCE24','\UCE25','\UCE26','\UCE27','\UCE28','\UCE29','\UCE2A','\UCE2B','\UCE2C','\UCE2D','\UCE2E','\UCE2F','\UCE30','\UCE31','\UCE32','\UCE33','\UCE34','\UCE35','\UCE36','\UCE37','\UCE38','\UCE39','\UCE3A','\UCE3B','\UCE3C','\UCE3D','\UCE3E','\UCE3F','\UCE40','\UCE41','\UCE42','\UCE43','\UCE44','\UCE45','\UCE46','\UCE47','\UCE48','\UCE49','\UCE4A','\UCE4B','\UCE4C','\UCE4D','\UCE4E','\UCE4F','\UCE50','\UCE51','\UCE52','\UCE53','\UCE54','\UCE55','\UCE56','\UCE57','\UCE58','\UCE59','\UCE5A','\UCE5B','\UCE5C','\UCE5D','\UCE5E','\UCE5F','\UCE60','\UCE61','\UCE62','\UCE63','\UCE64','\UCE65','\UCE66','\UCE67','\UCE68','\UCE69','\UCE6A','\UCE6B','\UCE6C','\UCE6D','\UCE6E','\UCE6F','\UCE70','\UCE71','\UCE72','\UCE73','\UCE74','\UCE75','\UCE76','\UCE77','\UCE78','\UCE79','\UCE7A','\UCE7B','\UCE7C','\UCE7D','\UCE7E','\UCE7F','\UCE80','\UCE81','\UCE82','\UCE83','\UCE84','\UCE85','\UCE86','\UCE87','\UCE88','\UCE89','\UCE8A','\UCE8B','\UCE8C','\UCE8D','\UCE8E','\UCE8F','\UCE90','\UCE91','\UCE92','\UCE93','\UCE94','\UCE95','\UCE96','\UCE97','\UCE98','\UCE99','\UCE9A','\UCE9B','\UCE9C','\UCE9D','\UCE9E','\UCE9F','\UCEA0','\UCEA1','\UCEA2','\UCEA3','\UCEA4','\UCEA5','\UCEA6','\UCEA7','\UCEA8','\UCEA9','\UCEAA','\UCEAB','\UCEAC','\UCEAD','\UCEAE','\UCEAF','\UCEB0','\UCEB1','\UCEB2','\UCEB3','\UCEB4','\UCEB5','\UCEB6','\UCEB7','\UCEB8','\UCEB9','\UCEBA','\UCEBB','\UCEBC','\UCEBD','\UCEBE','\UCEBF','\UCEC0','\UCEC1','\UCEC2','\UCEC3','\UCEC4','\UCEC5','\UCEC6','\UCEC7','\UCEC8','\UCEC9','\UCECA','\UCECB','\UCECC','\UCECD','\UCECE','\UCECF','\UCED0','\UCED1','\UCED2','\UCED3','\UCED4','\UCED5','\UCED6','\UCED7','\UCED8','\UCED9','\UCEDA','\UCEDB','\UCEDC','\UCEDD','\UCEDE','\UCEDF','\UCEE0','\UCEE1','\UCEE2','\UCEE3','\UCEE4','\UCEE5','\UCEE6','\UCEE7','\UCEE8','\UCEE9','\UCEEA','\UCEEB','\UCEEC','\UCEED','\UCEEE','\UCEEF','\UCEF0','\UCEF1','\UCEF2','\UCEF3','\UCEF4','\UCEF5','\UCEF6','\UCEF7','\UCEF8','\UCEF9','\UCEFA','\UCEFB','\UCEFC','\UCEFD','\UCEFE','\UCEFF','\UCF00','\UCF01','\UCF02','\UCF03','\UCF04','\UCF05','\UCF06','\UCF07','\UCF08','\UCF09','\UCF0A','\UCF0B','\UCF0C','\UCF0D','\UCF0E','\UCF0F','\UCF10','\UCF11','\UCF12','\UCF13','\UCF14','\UCF15','\UCF16','\UCF17','\UCF18','\UCF19','\UCF1A','\UCF1B','\UCF1C','\UCF1D','\UCF1E','\UCF1F','\UCF20','\UCF21','\UCF22','\UCF23','\UCF24','\UCF25','\UCF26','\UCF27','\UCF28','\UCF29','\UCF2A','\UCF2B','\UCF2C','\UCF2D','\UCF2E','\UCF2F','\UCF30','\UCF31','\UCF32','\UCF33','\UCF34','\UCF35','\UCF36','\UCF37','\UCF38','\UCF39','\UCF3A','\UCF3B','\UCF3C','\UCF3D','\UCF3E','\UCF3F','\UCF40','\UCF41','\UCF42','\UCF43','\UCF44','\UCF45','\UCF46','\UCF47','\UCF48','\UCF49','\UCF4A','\UCF4B','\UCF4C','\UCF4D','\UCF4E','\UCF4F','\UCF50','\UCF51','\UCF52','\UCF53','\UCF54','\UCF55','\UCF56','\UCF57','\UCF58','\UCF59','\UCF5A','\UCF5B','\UCF5C','\UCF5D','\UCF5E','\UCF5F','\UCF60','\UCF61','\UCF62','\UCF63','\UCF64','\UCF65','\UCF66','\UCF67','\UCF68','\UCF69','\UCF6A','\UCF6B','\UCF6C','\UCF6D','\UCF6E','\UCF6F','\UCF70','\UCF71','\UCF72','\UCF73','\UCF74','\UCF75','\UCF76','\UCF77','\UCF78','\UCF79','\UCF7A','\UCF7B','\UCF7C','\UCF7D','\UCF7E','\UCF7F','\UCF80','\UCF81','\UCF82','\UCF83','\UCF84','\UCF85','\UCF86','\UCF87','\UCF88','\UCF89','\UCF8A','\UCF8B','\UCF8C','\UCF8D','\UCF8E','\UCF8F','\UCF90','\UCF91','\UCF92','\UCF93','\UCF94','\UCF95','\UCF96','\UCF97','\UCF98','\UCF99','\UCF9A','\UCF9B','\UCF9C','\UCF9D','\UCF9E','\UCF9F','\UCFA0','\UCFA1','\UCFA2','\UCFA3','\UCFA4','\UCFA5','\UCFA6','\UCFA7','\UCFA8','\UCFA9','\UCFAA','\UCFAB','\UCFAC','\UCFAD','\UCFAE','\UCFAF','\UCFB0','\UCFB1','\UCFB2','\UCFB3','\UCFB4','\UCFB5','\UCFB6','\UCFB7','\UCFB8','\UCFB9','\UCFBA','\UCFBB','\UCFBC','\UCFBD','\UCFBE','\UCFBF','\UCFC0','\UCFC1','\UCFC2','\UCFC3','\UCFC4','\UCFC5','\UCFC6','\UCFC7','\UCFC8','\UCFC9','\UCFCA','\UCFCB','\UCFCC','\UCFCD','\UCFCE','\UCFCF','\UCFD0','\UCFD1','\UCFD2','\UCFD3','\UCFD4','\UCFD5','\UCFD6','\UCFD7','\UCFD8','\UCFD9','\UCFDA','\UCFDB','\UCFDC','\UCFDD','\UCFDE','\UCFDF','\UCFE0','\UCFE1','\UCFE2','\UCFE3','\UCFE4','\UCFE5','\UCFE6','\UCFE7','\UCFE8','\UCFE9','\UCFEA','\UCFEB','\UCFEC','\UCFED','\UCFEE','\UCFEF','\UCFF0','\UCFF1','\UCFF2','\UCFF3','\UCFF4','\UCFF5','\UCFF6','\UCFF7','\UCFF8','\UCFF9','\UCFFA','\UCFFB','\UCFFC','\UCFFD','\UCFFE','\UCFFF','\UD000','\UD001','\UD002','\UD003','\UD004','\UD005','\UD006','\UD007','\UD008','\UD009','\UD00A','\UD00B','\UD00C','\UD00D','\UD00E','\UD00F','\UD010','\UD011','\UD012','\UD013','\UD014','\UD015','\UD016','\UD017','\UD018','\UD019','\UD01A','\UD01B','\UD01C','\UD01D','\UD01E','\UD01F','\UD020','\UD021','\UD022','\UD023','\UD024','\UD025','\UD026','\UD027','\UD028','\UD029','\UD02A','\UD02B','\UD02C','\UD02D','\UD02E','\UD02F','\UD030','\UD031','\UD032','\UD033','\UD034','\UD035','\UD036','\UD037','\UD038','\UD039','\UD03A','\UD03B','\UD03C','\UD03D','\UD03E','\UD03F','\UD040','\UD041','\UD042','\UD043','\UD044','\UD045','\UD046','\UD047','\UD048','\UD049','\UD04A','\UD04B','\UD04C','\UD04D','\UD04E','\UD04F','\UD050','\UD051','\UD052','\UD053','\UD054','\UD055','\UD056','\UD057','\UD058','\UD059','\UD05A','\UD05B','\UD05C','\UD05D','\UD05E','\UD05F','\UD060','\UD061','\UD062','\UD063','\UD064','\UD065','\UD066','\UD067','\UD068','\UD069','\UD06A','\UD06B','\UD06C','\UD06D','\UD06E','\UD06F','\UD070','\UD071','\UD072','\UD073','\UD074','\UD075','\UD076','\UD077','\UD078','\UD079','\UD07A','\UD07B','\UD07C','\UD07D','\UD07E','\UD07F','\UD080','\UD081','\UD082','\UD083','\UD084','\UD085','\UD086','\UD087','\UD088','\UD089','\UD08A','\UD08B','\UD08C','\UD08D','\UD08E','\UD08F','\UD090','\UD091','\UD092','\UD093','\UD094','\UD095','\UD096','\UD097','\UD098','\UD099','\UD09A','\UD09B','\UD09C','\UD09D','\UD09E','\UD09F','\UD0A0','\UD0A1','\UD0A2','\UD0A3','\UD0A4','\UD0A5','\UD0A6','\UD0A7','\UD0A8','\UD0A9','\UD0AA','\UD0AB','\UD0AC','\UD0AD','\UD0AE','\UD0AF','\UD0B0','\UD0B1','\UD0B2','\UD0B3','\UD0B4','\UD0B5','\UD0B6','\UD0B7','\UD0B8','\UD0B9','\UD0BA','\UD0BB','\UD0BC','\UD0BD','\UD0BE','\UD0BF','\UD0C0','\UD0C1','\UD0C2','\UD0C3','\UD0C4','\UD0C5','\UD0C6','\UD0C7','\UD0C8','\UD0C9','\UD0CA','\UD0CB','\UD0CC','\UD0CD','\UD0CE','\UD0CF','\UD0D0','\UD0D1','\UD0D2','\UD0D3','\UD0D4','\UD0D5','\UD0D6','\UD0D7','\UD0D8','\UD0D9','\UD0DA','\UD0DB','\UD0DC','\UD0DD','\UD0DE','\UD0DF','\UD0E0','\UD0E1','\UD0E2','\UD0E3','\UD0E4','\UD0E5','\UD0E6','\UD0E7','\UD0E8','\UD0E9','\UD0EA','\UD0EB','\UD0EC','\UD0ED','\UD0EE','\UD0EF','\UD0F0','\UD0F1','\UD0F2','\UD0F3','\UD0F4','\UD0F5','\UD0F6','\UD0F7','\UD0F8','\UD0F9','\UD0FA','\UD0FB','\UD0FC','\UD0FD','\UD0FE','\UD0FF','\UD100','\UD101','\UD102','\UD103','\UD104','\UD105','\UD106','\UD107','\UD108','\UD109','\UD10A','\UD10B','\UD10C','\UD10D','\UD10E','\UD10F','\UD110','\UD111','\UD112','\UD113','\UD114','\UD115','\UD116','\UD117','\UD118','\UD119','\UD11A','\UD11B','\UD11C','\UD11D','\UD11E','\UD11F','\UD120','\UD121','\UD122','\UD123','\UD124','\UD125','\UD126','\UD127','\UD128','\UD129','\UD12A','\UD12B','\UD12C','\UD12D','\UD12E','\UD12F','\UD130','\UD131','\UD132','\UD133','\UD134','\UD135','\UD136','\UD137','\UD138','\UD139','\UD13A','\UD13B','\UD13C','\UD13D','\UD13E','\UD13F','\UD140','\UD141','\UD142','\UD143','\UD144','\UD145','\UD146','\UD147','\UD148','\UD149','\UD14A','\UD14B','\UD14C','\UD14D','\UD14E','\UD14F','\UD150','\UD151','\UD152','\UD153','\UD154','\UD155','\UD156','\UD157','\UD158','\UD159','\UD15A','\UD15B','\UD15C','\UD15D','\UD15E','\UD15F','\UD160','\UD161','\UD162','\UD163','\UD164','\UD165','\UD166','\UD167','\UD168','\UD169','\UD16A','\UD16B','\UD16C','\UD16D','\UD16E','\UD16F','\UD170','\UD171','\UD172','\UD173','\UD174','\UD175','\UD176','\UD177','\UD178','\UD179','\UD17A','\UD17B','\UD17C','\UD17D','\UD17E','\UD17F','\UD180','\UD181','\UD182','\UD183','\UD184','\UD185','\UD186','\UD187','\UD188','\UD189','\UD18A','\UD18B','\UD18C','\UD18D','\UD18E','\UD18F','\UD190','\UD191','\UD192','\UD193','\UD194','\UD195','\UD196','\UD197','\UD198','\UD199','\UD19A','\UD19B','\UD19C','\UD19D','\UD19E','\UD19F','\UD1A0','\UD1A1','\UD1A2','\UD1A3','\UD1A4','\UD1A5','\UD1A6','\UD1A7','\UD1A8','\UD1A9','\UD1AA','\UD1AB','\UD1AC','\UD1AD','\UD1AE','\UD1AF','\UD1B0','\UD1B1','\UD1B2','\UD1B3','\UD1B4','\UD1B5','\UD1B6','\UD1B7','\UD1B8','\UD1B9','\UD1BA','\UD1BB','\UD1BC','\UD1BD','\UD1BE','\UD1BF','\UD1C0','\UD1C1','\UD1C2','\UD1C3','\UD1C4','\UD1C5','\UD1C6','\UD1C7','\UD1C8','\UD1C9','\UD1CA','\UD1CB','\UD1CC','\UD1CD','\UD1CE','\UD1CF','\UD1D0','\UD1D1','\UD1D2','\UD1D3','\UD1D4','\UD1D5','\UD1D6','\UD1D7','\UD1D8','\UD1D9','\UD1DA','\UD1DB','\UD1DC','\UD1DD','\UD1DE','\UD1DF','\UD1E0','\UD1E1','\UD1E2','\UD1E3','\UD1E4','\UD1E5','\UD1E6','\UD1E7','\UD1E8','\UD1E9','\UD1EA','\UD1EB','\UD1EC','\UD1ED','\UD1EE','\UD1EF','\UD1F0','\UD1F1','\UD1F2','\UD1F3','\UD1F4','\UD1F5','\UD1F6','\UD1F7','\UD1F8','\UD1F9','\UD1FA','\UD1FB','\UD1FC','\UD1FD','\UD1FE','\UD1FF','\UD200','\UD201','\UD202','\UD203','\UD204','\UD205','\UD206','\UD207','\UD208','\UD209','\UD20A','\UD20B','\UD20C','\UD20D','\UD20E','\UD20F','\UD210','\UD211','\UD212','\UD213','\UD214','\UD215','\UD216','\UD217','\UD218','\UD219','\UD21A','\UD21B','\UD21C','\UD21D','\UD21E','\UD21F','\UD220','\UD221','\UD222','\UD223','\UD224','\UD225','\UD226','\UD227','\UD228','\UD229','\UD22A','\UD22B','\UD22C','\UD22D','\UD22E','\UD22F','\UD230','\UD231','\UD232','\UD233','\UD234','\UD235','\UD236','\UD237','\UD238','\UD239','\UD23A','\UD23B','\UD23C','\UD23D','\UD23E','\UD23F','\UD240','\UD241','\UD242','\UD243','\UD244','\UD245','\UD246','\UD247','\UD248','\UD249','\UD24A','\UD24B','\UD24C','\UD24D','\UD24E','\UD24F','\UD250','\UD251','\UD252','\UD253','\UD254','\UD255','\UD256','\UD257','\UD258','\UD259','\UD25A','\UD25B','\UD25C','\UD25D','\UD25E','\UD25F','\UD260','\UD261','\UD262','\UD263','\UD264','\UD265','\UD266','\UD267','\UD268','\UD269','\UD26A','\UD26B','\UD26C','\UD26D','\UD26E','\UD26F','\UD270','\UD271','\UD272','\UD273','\UD274','\UD275','\UD276','\UD277','\UD278','\UD279','\UD27A','\UD27B','\UD27C','\UD27D','\UD27E','\UD27F','\UD280','\UD281','\UD282','\UD283','\UD284','\UD285','\UD286','\UD287','\UD288','\UD289','\UD28A','\UD28B','\UD28C','\UD28D','\UD28E','\UD28F','\UD290','\UD291','\UD292','\UD293','\UD294','\UD295','\UD296','\UD297','\UD298','\UD299','\UD29A','\UD29B','\UD29C','\UD29D','\UD29E','\UD29F','\UD2A0','\UD2A1','\UD2A2','\UD2A3','\UD2A4','\UD2A5','\UD2A6','\UD2A7','\UD2A8','\UD2A9','\UD2AA','\UD2AB','\UD2AC','\UD2AD','\UD2AE','\UD2AF','\UD2B0','\UD2B1','\UD2B2','\UD2B3','\UD2B4','\UD2B5','\UD2B6','\UD2B7','\UD2B8','\UD2B9','\UD2BA','\UD2BB','\UD2BC','\UD2BD','\UD2BE','\UD2BF','\UD2C0','\UD2C1','\UD2C2','\UD2C3','\UD2C4','\UD2C5','\UD2C6','\UD2C7','\UD2C8','\UD2C9','\UD2CA','\UD2CB','\UD2CC','\UD2CD','\UD2CE','\UD2CF','\UD2D0','\UD2D1','\UD2D2','\UD2D3','\UD2D4','\UD2D5','\UD2D6','\UD2D7','\UD2D8','\UD2D9','\UD2DA','\UD2DB','\UD2DC','\UD2DD','\UD2DE','\UD2DF','\UD2E0','\UD2E1','\UD2E2','\UD2E3','\UD2E4','\UD2E5','\UD2E6','\UD2E7','\UD2E8','\UD2E9','\UD2EA','\UD2EB','\UD2EC','\UD2ED','\UD2EE','\UD2EF','\UD2F0','\UD2F1','\UD2F2','\UD2F3','\UD2F4','\UD2F5','\UD2F6','\UD2F7','\UD2F8','\UD2F9','\UD2FA','\UD2FB','\UD2FC','\UD2FD','\UD2FE','\UD2FF','\UD300','\UD301','\UD302','\UD303','\UD304','\UD305','\UD306','\UD307','\UD308','\UD309','\UD30A','\UD30B','\UD30C','\UD30D','\UD30E','\UD30F','\UD310','\UD311','\UD312','\UD313','\UD314','\UD315','\UD316','\UD317','\UD318','\UD319','\UD31A','\UD31B','\UD31C','\UD31D','\UD31E','\UD31F','\UD320','\UD321','\UD322','\UD323','\UD324','\UD325','\UD326','\UD327','\UD328','\UD329','\UD32A','\UD32B','\UD32C','\UD32D','\UD32E','\UD32F','\UD330','\UD331','\UD332','\UD333','\UD334','\UD335','\UD336','\UD337','\UD338','\UD339','\UD33A','\UD33B','\UD33C','\UD33D','\UD33E','\UD33F','\UD340','\UD341','\UD342','\UD343','\UD344','\UD345','\UD346','\UD347','\UD348','\UD349','\UD34A','\UD34B','\UD34C','\UD34D','\UD34E','\UD34F','\UD350','\UD351','\UD352','\UD353','\UD354','\UD355','\UD356','\UD357','\UD358','\UD359','\UD35A','\UD35B','\UD35C','\UD35D','\UD35E','\UD35F','\UD360','\UD361','\UD362','\UD363','\UD364','\UD365','\UD366','\UD367','\UD368','\UD369','\UD36A','\UD36B','\UD36C','\UD36D','\UD36E','\UD36F','\UD370','\UD371','\UD372','\UD373','\UD374','\UD375','\UD376','\UD377','\UD378','\UD379','\UD37A','\UD37B','\UD37C','\UD37D','\UD37E','\UD37F','\UD380','\UD381','\UD382','\UD383','\UD384','\UD385','\UD386','\UD387','\UD388','\UD389','\UD38A','\UD38B','\UD38C','\UD38D','\UD38E','\UD38F','\UD390','\UD391','\UD392','\UD393','\UD394','\UD395','\UD396','\UD397','\UD398','\UD399','\UD39A','\UD39B','\UD39C','\UD39D','\UD39E','\UD39F','\UD3A0','\UD3A1','\UD3A2','\UD3A3','\UD3A4','\UD3A5','\UD3A6','\UD3A7','\UD3A8','\UD3A9','\UD3AA','\UD3AB','\UD3AC','\UD3AD','\UD3AE','\UD3AF','\UD3B0','\UD3B1','\UD3B2','\UD3B3','\UD3B4','\UD3B5','\UD3B6','\UD3B7','\UD3B8','\UD3B9','\UD3BA','\UD3BB','\UD3BC','\UD3BD','\UD3BE','\UD3BF','\UD3C0','\UD3C1','\UD3C2','\UD3C3','\UD3C4','\UD3C5','\UD3C6','\UD3C7','\UD3C8','\UD3C9','\UD3CA','\UD3CB','\UD3CC','\UD3CD','\UD3CE','\UD3CF','\UD3D0','\UD3D1','\UD3D2','\UD3D3','\UD3D4','\UD3D5','\UD3D6','\UD3D7','\UD3D8','\UD3D9','\UD3DA','\UD3DB','\UD3DC','\UD3DD','\UD3DE','\UD3DF','\UD3E0','\UD3E1','\UD3E2','\UD3E3','\UD3E4','\UD3E5','\UD3E6','\UD3E7','\UD3E8','\UD3E9','\UD3EA','\UD3EB','\UD3EC','\UD3ED','\UD3EE','\UD3EF','\UD3F0','\UD3F1','\UD3F2','\UD3F3','\UD3F4','\UD3F5','\UD3F6','\UD3F7','\UD3F8','\UD3F9','\UD3FA','\UD3FB','\UD3FC','\UD3FD','\UD3FE','\UD3FF','\UD400','\UD401','\UD402','\UD403','\UD404','\UD405','\UD406','\UD407','\UD408','\UD409','\UD40A','\UD40B','\UD40C','\UD40D','\UD40E','\UD40F','\UD410','\UD411','\UD412','\UD413','\UD414','\UD415','\UD416','\UD417','\UD418','\UD419','\UD41A','\UD41B','\UD41C','\UD41D','\UD41E','\UD41F','\UD420','\UD421','\UD422','\UD423','\UD424','\UD425','\UD426','\UD427','\UD428','\UD429','\UD42A','\UD42B','\UD42C','\UD42D','\UD42E','\UD42F','\UD430','\UD431','\UD432','\UD433','\UD434','\UD435','\UD436','\UD437','\UD438','\UD439','\UD43A','\UD43B','\UD43C','\UD43D','\UD43E','\UD43F','\UD440','\UD441','\UD442','\UD443','\UD444','\UD445','\UD446','\UD447','\UD448','\UD449','\UD44A','\UD44B','\UD44C','\UD44D','\UD44E','\UD44F','\UD450','\UD451','\UD452','\UD453','\UD454','\UD455','\UD456','\UD457','\UD458','\UD459','\UD45A','\UD45B','\UD45C','\UD45D','\UD45E','\UD45F','\UD460','\UD461','\UD462','\UD463','\UD464','\UD465','\UD466','\UD467','\UD468','\UD469','\UD46A','\UD46B','\UD46C','\UD46D','\UD46E','\UD46F','\UD470','\UD471','\UD472','\UD473','\UD474','\UD475','\UD476','\UD477','\UD478','\UD479','\UD47A','\UD47B','\UD47C','\UD47D','\UD47E','\UD47F','\UD480','\UD481','\UD482','\UD483','\UD484','\UD485','\UD486','\UD487','\UD488','\UD489','\UD48A','\UD48B','\UD48C','\UD48D','\UD48E','\UD48F','\UD490','\UD491','\UD492','\UD493','\UD494','\UD495','\UD496','\UD497','\UD498','\UD499','\UD49A','\UD49B','\UD49C','\UD49D','\UD49E','\UD49F','\UD4A0','\UD4A1','\UD4A2','\UD4A3','\UD4A4','\UD4A5','\UD4A6','\UD4A7','\UD4A8','\UD4A9','\UD4AA','\UD4AB','\UD4AC','\UD4AD','\UD4AE','\UD4AF','\UD4B0','\UD4B1','\UD4B2','\UD4B3','\UD4B4','\UD4B5','\UD4B6','\UD4B7','\UD4B8','\UD4B9','\UD4BA','\UD4BB','\UD4BC','\UD4BD','\UD4BE','\UD4BF','\UD4C0','\UD4C1','\UD4C2','\UD4C3','\UD4C4','\UD4C5','\UD4C6','\UD4C7','\UD4C8','\UD4C9','\UD4CA','\UD4CB','\UD4CC','\UD4CD','\UD4CE','\UD4CF','\UD4D0','\UD4D1','\UD4D2','\UD4D3','\UD4D4','\UD4D5','\UD4D6','\UD4D7','\UD4D8','\UD4D9','\UD4DA','\UD4DB','\UD4DC','\UD4DD','\UD4DE','\UD4DF','\UD4E0','\UD4E1','\UD4E2','\UD4E3','\UD4E4','\UD4E5','\UD4E6','\UD4E7','\UD4E8','\UD4E9','\UD4EA','\UD4EB','\UD4EC','\UD4ED','\UD4EE','\UD4EF','\UD4F0','\UD4F1','\UD4F2','\UD4F3','\UD4F4','\UD4F5','\UD4F6','\UD4F7','\UD4F8','\UD4F9','\UD4FA','\UD4FB','\UD4FC','\UD4FD','\UD4FE','\UD4FF','\UD500','\UD501','\UD502','\UD503','\UD504','\UD505','\UD506','\UD507','\UD508','\UD509','\UD50A','\UD50B','\UD50C','\UD50D','\UD50E','\UD50F','\UD510','\UD511','\UD512','\UD513','\UD514','\UD515','\UD516','\UD517','\UD518','\UD519','\UD51A','\UD51B','\UD51C','\UD51D','\UD51E','\UD51F','\UD520','\UD521','\UD522','\UD523','\UD524','\UD525','\UD526','\UD527','\UD528','\UD529','\UD52A','\UD52B','\UD52C','\UD52D','\UD52E','\UD52F','\UD530','\UD531','\UD532','\UD533','\UD534','\UD535','\UD536','\UD537','\UD538','\UD539','\UD53A','\UD53B','\UD53C','\UD53D','\UD53E','\UD53F','\UD540','\UD541','\UD542','\UD543','\UD544','\UD545','\UD546','\UD547','\UD548','\UD549','\UD54A','\UD54B','\UD54C','\UD54D','\UD54E','\UD54F','\UD550','\UD551','\UD552','\UD553','\UD554','\UD555','\UD556','\UD557','\UD558','\UD559','\UD55A','\UD55B','\UD55C','\UD55D','\UD55E','\UD55F','\UD560','\UD561','\UD562','\UD563','\UD564','\UD565','\UD566','\UD567','\UD568','\UD569','\UD56A','\UD56B','\UD56C','\UD56D','\UD56E','\UD56F','\UD570','\UD571','\UD572','\UD573','\UD574','\UD575','\UD576','\UD577','\UD578','\UD579','\UD57A','\UD57B','\UD57C','\UD57D','\UD57E','\UD57F','\UD580','\UD581','\UD582','\UD583','\UD584','\UD585','\UD586','\UD587','\UD588','\UD589','\UD58A','\UD58B','\UD58C','\UD58D','\UD58E','\UD58F','\UD590','\UD591','\UD592','\UD593','\UD594','\UD595','\UD596','\UD597','\UD598','\UD599','\UD59A','\UD59B','\UD59C','\UD59D','\UD59E','\UD59F','\UD5A0','\UD5A1','\UD5A2','\UD5A3','\UD5A4','\UD5A5','\UD5A6','\UD5A7','\UD5A8','\UD5A9','\UD5AA','\UD5AB','\UD5AC','\UD5AD','\UD5AE','\UD5AF','\UD5B0','\UD5B1','\UD5B2','\UD5B3','\UD5B4','\UD5B5','\UD5B6','\UD5B7','\UD5B8','\UD5B9','\UD5BA','\UD5BB','\UD5BC','\UD5BD','\UD5BE','\UD5BF','\UD5C0','\UD5C1','\UD5C2','\UD5C3','\UD5C4','\UD5C5','\UD5C6','\UD5C7','\UD5C8','\UD5C9','\UD5CA','\UD5CB','\UD5CC','\UD5CD','\UD5CE','\UD5CF','\UD5D0','\UD5D1','\UD5D2','\UD5D3','\UD5D4','\UD5D5','\UD5D6','\UD5D7','\UD5D8','\UD5D9','\UD5DA','\UD5DB','\UD5DC','\UD5DD','\UD5DE','\UD5DF','\UD5E0','\UD5E1','\UD5E2','\UD5E3','\UD5E4','\UD5E5','\UD5E6','\UD5E7','\UD5E8','\UD5E9','\UD5EA','\UD5EB','\UD5EC','\UD5ED','\UD5EE','\UD5EF','\UD5F0','\UD5F1','\UD5F2','\UD5F3','\UD5F4','\UD5F5','\UD5F6','\UD5F7','\UD5F8','\UD5F9','\UD5FA','\UD5FB','\UD5FC','\UD5FD','\UD5FE','\UD5FF','\UD600','\UD601','\UD602','\UD603','\UD604','\UD605','\UD606','\UD607','\UD608','\UD609','\UD60A','\UD60B','\UD60C','\UD60D','\UD60E','\UD60F','\UD610','\UD611','\UD612','\UD613','\UD614','\UD615','\UD616','\UD617','\UD618','\UD619','\UD61A','\UD61B','\UD61C','\UD61D','\UD61E','\UD61F','\UD620','\UD621','\UD622','\UD623','\UD624','\UD625','\UD626','\UD627','\UD628','\UD629','\UD62A','\UD62B','\UD62C','\UD62D','\UD62E','\UD62F','\UD630','\UD631','\UD632','\UD633','\UD634','\UD635','\UD636','\UD637','\UD638','\UD639','\UD63A','\UD63B','\UD63C','\UD63D','\UD63E','\UD63F','\UD640','\UD641','\UD642','\UD643','\UD644','\UD645','\UD646','\UD647','\UD648','\UD649','\UD64A','\UD64B','\UD64C','\UD64D','\UD64E','\UD64F','\UD650','\UD651','\UD652','\UD653','\UD654','\UD655','\UD656','\UD657','\UD658','\UD659','\UD65A','\UD65B','\UD65C','\UD65D','\UD65E','\UD65F','\UD660','\UD661','\UD662','\UD663','\UD664','\UD665','\UD666','\UD667','\UD668','\UD669','\UD66A','\UD66B','\UD66C','\UD66D','\UD66E','\UD66F','\UD670','\UD671','\UD672','\UD673','\UD674','\UD675','\UD676','\UD677','\UD678','\UD679','\UD67A','\UD67B','\UD67C','\UD67D','\UD67E','\UD67F','\UD680','\UD681','\UD682','\UD683','\UD684','\UD685','\UD686','\UD687','\UD688','\UD689','\UD68A','\UD68B','\UD68C','\UD68D','\UD68E','\UD68F','\UD690','\UD691','\UD692','\UD693','\UD694','\UD695','\UD696','\UD697','\UD698','\UD699','\UD69A','\UD69B','\UD69C','\UD69D','\UD69E','\UD69F','\UD6A0','\UD6A1','\UD6A2','\UD6A3','\UD6A4','\UD6A5','\UD6A6','\UD6A7','\UD6A8','\UD6A9','\UD6AA','\UD6AB','\UD6AC','\UD6AD','\UD6AE','\UD6AF','\UD6B0','\UD6B1','\UD6B2','\UD6B3','\UD6B4','\UD6B5','\UD6B6','\UD6B7','\UD6B8','\UD6B9','\UD6BA','\UD6BB','\UD6BC','\UD6BD','\UD6BE','\UD6BF','\UD6C0','\UD6C1','\UD6C2','\UD6C3','\UD6C4','\UD6C5','\UD6C6','\UD6C7','\UD6C8','\UD6C9','\UD6CA','\UD6CB','\UD6CC','\UD6CD','\UD6CE','\UD6CF','\UD6D0','\UD6D1','\UD6D2','\UD6D3','\UD6D4','\UD6D5','\UD6D6','\UD6D7','\UD6D8','\UD6D9','\UD6DA','\UD6DB','\UD6DC','\UD6DD','\UD6DE','\UD6DF','\UD6E0','\UD6E1','\UD6E2','\UD6E3','\UD6E4','\UD6E5','\UD6E6','\UD6E7','\UD6E8','\UD6E9','\UD6EA','\UD6EB','\UD6EC','\UD6ED','\UD6EE','\UD6EF','\UD6F0','\UD6F1','\UD6F2','\UD6F3','\UD6F4','\UD6F5','\UD6F6','\UD6F7','\UD6F8','\UD6F9','\UD6FA','\UD6FB','\UD6FC','\UD6FD','\UD6FE','\UD6FF','\UD700','\UD701','\UD702','\UD703','\UD704','\UD705','\UD706','\UD707','\UD708','\UD709','\UD70A','\UD70B','\UD70C','\UD70D','\UD70E','\UD70F','\UD710','\UD711','\UD712','\UD713','\UD714','\UD715','\UD716','\UD717','\UD718','\UD719','\UD71A','\UD71B','\UD71C','\UD71D','\UD71E','\UD71F','\UD720','\UD721','\UD722','\UD723','\UD724','\UD725','\UD726','\UD727','\UD728','\UD729','\UD72A','\UD72B','\UD72C','\UD72D','\UD72E','\UD72F','\UD730','\UD731','\UD732','\UD733','\UD734','\UD735','\UD736','\UD737','\UD738','\UD739','\UD73A','\UD73B','\UD73C','\UD73D','\UD73E','\UD73F','\UD740','\UD741','\UD742','\UD743','\UD744','\UD745','\UD746','\UD747','\UD748','\UD749','\UD74A','\UD74B','\UD74C','\UD74D','\UD74E','\UD74F','\UD750','\UD751','\UD752','\UD753','\UD754','\UD755','\UD756','\UD757','\UD758','\UD759','\UD75A','\UD75B','\UD75C','\UD75D','\UD75E','\UD75F','\UD760','\UD761','\UD762','\UD763','\UD764','\UD765','\UD766','\UD767','\UD768','\UD769','\UD76A','\UD76B','\UD76C','\UD76D','\UD76E','\UD76F','\UD770','\UD771','\UD772','\UD773','\UD774','\UD775','\UD776','\UD777','\UD778','\UD779','\UD77A','\UD77B','\UD77C','\UD77D','\UD77E','\UD77F','\UD780','\UD781','\UD782','\UD783','\UD784','\UD785','\UD786','\UD787','\UD788','\UD789','\UD78A','\UD78B','\UD78C','\UD78D','\UD78E','\UD78F','\UD790','\UD791','\UD792','\UD793','\UD794','\UD795','\UD796','\UD797','\UD798','\UD799','\UD79A','\UD79B','\UD79C','\UD79D','\UD79E','\UD79F','\UD7A0','\UD7A1','\UD7A2','\UD7A3','\UD7A4','\UD7A5','\UD7A6','\UD7A7','\UD7A8','\UD7A9','\UD7AA','\UD7AB','\UD7AC','\UD7AD','\UD7AE','\UD7AF','\UD7B0','\UD7B1','\UD7B2','\UD7B3','\UD7B4','\UD7B5','\UD7B6','\UD7B7','\UD7B8','\UD7B9','\UD7BA','\UD7BB','\UD7BC','\UD7BD','\UD7BE','\UD7BF','\UD7C0','\UD7C1','\UD7C2','\UD7C3','\UD7C4','\UD7C5','\UD7C6','\UD7C7','\UD7C8','\UD7C9','\UD7CA','\UD7CB','\UD7CC','\UD7CD','\UD7CE','\UD7CF','\UD7D0','\UD7D1','\UD7D2','\UD7D3','\UD7D4','\UD7D5','\UD7D6','\UD7D7','\UD7D8','\UD7D9','\UD7DA','\UD7DB','\UD7DC','\UD7DD','\UD7DE','\UD7DF','\UD7E0','\UD7E1','\UD7E2','\UD7E3','\UD7E4','\UD7E5','\UD7E6','\UD7E7','\UD7E8','\UD7E9','\UD7EA','\UD7EB','\UD7EC','\UD7ED','\UD7EE','\UD7EF','\UD7F0','\UD7F1','\UD7F2','\UD7F3','\UD7F4','\UD7F5','\UD7F6','\UD7F7','\UD7F8','\UD7F9','\UD7FA','\UD7FB','\UD7FC','\UD7FD','\UD7FE','\UD7FF','\UE000','\UE001','\UE002','\UE003','\UE004','\UE005','\UE006','\UE007','\UE008','\UE009','\UE00A','\UE00B','\UE00C','\UE00D','\UE00E','\UE00F','\UE010','\UE011','\UE012','\UE013','\UE014','\UE015','\UE016','\UE017','\UE018','\UE019','\UE01A','\UE01B','\UE01C','\UE01D','\UE01E','\UE01F','\UE020','\UE021','\UE022','\UE023','\UE024','\UE025','\UE026','\UE027','\UE028','\UE029','\UE02A','\UE02B','\UE02C','\UE02D','\UE02E','\UE02F','\UE030','\UE031','\UE032','\UE033','\UE034','\UE035','\UE036','\UE037','\UE038','\UE039','\UE03A','\UE03B','\UE03C','\UE03D','\UE03E','\UE03F','\UE040','\UE041','\UE042','\UE043','\UE044','\UE045','\UE046','\UE047','\UE048','\UE049','\UE04A','\UE04B','\UE04C','\UE04D','\UE04E','\UE04F','\UE050','\UE051','\UE052','\UE053','\UE054','\UE055','\UE056','\UE057','\UE058','\UE059','\UE05A','\UE05B','\UE05C','\UE05D','\UE05E','\UE05F','\UE060','\UE061','\UE062','\UE063','\UE064','\UE065','\UE066','\UE067','\UE068','\UE069','\UE06A','\UE06B','\UE06C','\UE06D','\UE06E','\UE06F','\UE070','\UE071','\UE072','\UE073','\UE074','\UE075','\UE076','\UE077','\UE078','\UE079','\UE07A','\UE07B','\UE07C','\UE07D','\UE07E','\UE07F','\UE080','\UE081','\UE082','\UE083','\UE084','\UE085','\UE086','\UE087','\UE088','\UE089','\UE08A','\UE08B','\UE08C','\UE08D','\UE08E','\UE08F','\UE090','\UE091','\UE092','\UE093','\UE094','\UE095','\UE096','\UE097','\UE098','\UE099','\UE09A','\UE09B','\UE09C','\UE09D','\UE09E','\UE09F','\UE0A0','\UE0A1','\UE0A2','\UE0A3','\UE0A4','\UE0A5','\UE0A6','\UE0A7','\UE0A8','\UE0A9','\UE0AA','\UE0AB','\UE0AC','\UE0AD','\UE0AE','\UE0AF','\UE0B0','\UE0B1','\UE0B2','\UE0B3','\UE0B4','\UE0B5','\UE0B6','\UE0B7','\UE0B8','\UE0B9','\UE0BA','\UE0BB','\UE0BC','\UE0BD','\UE0BE','\UE0BF','\UE0C0','\UE0C1','\UE0C2','\UE0C3','\UE0C4','\UE0C5','\UE0C6','\UE0C7','\UE0C8','\UE0C9','\UE0CA','\UE0CB','\UE0CC','\UE0CD','\UE0CE','\UE0CF','\UE0D0','\UE0D1','\UE0D2','\UE0D3','\UE0D4','\UE0D5','\UE0D6','\UE0D7','\UE0D8','\UE0D9','\UE0DA','\UE0DB','\UE0DC','\UE0DD','\UE0DE','\UE0DF','\UE0E0','\UE0E1','\UE0E2','\UE0E3','\UE0E4','\UE0E5','\UE0E6','\UE0E7','\UE0E8','\UE0E9','\UE0EA','\UE0EB','\UE0EC','\UE0ED','\UE0EE','\UE0EF','\UE0F0','\UE0F1','\UE0F2','\UE0F3','\UE0F4','\UE0F5','\UE0F6','\UE0F7','\UE0F8','\UE0F9','\UE0FA','\UE0FB','\UE0FC','\UE0FD','\UE0FE','\UE0FF','\UE100','\UE101','\UE102','\UE103','\UE104','\UE105','\UE106','\UE107','\UE108','\UE109','\UE10A','\UE10B','\UE10C','\UE10D','\UE10E','\UE10F','\UE110','\UE111','\UE112','\UE113','\UE114','\UE115','\UE116','\UE117','\UE118','\UE119','\UE11A','\UE11B','\UE11C','\UE11D','\UE11E','\UE11F','\UE120','\UE121','\UE122','\UE123','\UE124','\UE125','\UE126','\UE127','\UE128','\UE129','\UE12A','\UE12B','\UE12C','\UE12D','\UE12E','\UE12F','\UE130','\UE131','\UE132','\UE133','\UE134','\UE135','\UE136','\UE137','\UE138','\UE139','\UE13A','\UE13B','\UE13C','\UE13D','\UE13E','\UE13F','\UE140','\UE141','\UE142','\UE143','\UE144','\UE145','\UE146','\UE147','\UE148','\UE149','\UE14A','\UE14B','\UE14C','\UE14D','\UE14E','\UE14F','\UE150','\UE151','\UE152','\UE153','\UE154','\UE155','\UE156','\UE157','\UE158','\UE159','\UE15A','\UE15B','\UE15C','\UE15D','\UE15E','\UE15F','\UE160','\UE161','\UE162','\UE163','\UE164','\UE165','\UE166','\UE167','\UE168','\UE169','\UE16A','\UE16B','\UE16C','\UE16D','\UE16E','\UE16F','\UE170','\UE171','\UE172','\UE173','\UE174','\UE175','\UE176','\UE177','\UE178','\UE179','\UE17A','\UE17B','\UE17C','\UE17D','\UE17E','\UE17F','\UE180','\UE181','\UE182','\UE183','\UE184','\UE185','\UE186','\UE187','\UE188','\UE189','\UE18A','\UE18B','\UE18C','\UE18D','\UE18E','\UE18F','\UE190','\UE191','\UE192','\UE193','\UE194','\UE195','\UE196','\UE197','\UE198','\UE199','\UE19A','\UE19B','\UE19C','\UE19D','\UE19E','\UE19F','\UE1A0','\UE1A1','\UE1A2','\UE1A3','\UE1A4','\UE1A5','\UE1A6','\UE1A7','\UE1A8','\UE1A9','\UE1AA','\UE1AB','\UE1AC','\UE1AD','\UE1AE','\UE1AF','\UE1B0','\UE1B1','\UE1B2','\UE1B3','\UE1B4','\UE1B5','\UE1B6','\UE1B7','\UE1B8','\UE1B9','\UE1BA','\UE1BB','\UE1BC','\UE1BD','\UE1BE','\UE1BF','\UE1C0','\UE1C1','\UE1C2','\UE1C3','\UE1C4','\UE1C5','\UE1C6','\UE1C7','\UE1C8','\UE1C9','\UE1CA','\UE1CB','\UE1CC','\UE1CD','\UE1CE','\UE1CF','\UE1D0','\UE1D1','\UE1D2','\UE1D3','\UE1D4','\UE1D5','\UE1D6','\UE1D7','\UE1D8','\UE1D9','\UE1DA','\UE1DB','\UE1DC','\UE1DD','\UE1DE','\UE1DF','\UE1E0','\UE1E1','\UE1E2','\UE1E3','\UE1E4','\UE1E5','\UE1E6','\UE1E7','\UE1E8','\UE1E9','\UE1EA','\UE1EB','\UE1EC','\UE1ED','\UE1EE','\UE1EF','\UE1F0','\UE1F1','\UE1F2','\UE1F3','\UE1F4','\UE1F5','\UE1F6','\UE1F7','\UE1F8','\UE1F9','\UE1FA','\UE1FB','\UE1FC','\UE1FD','\UE1FE','\UE1FF','\UE200','\UE201','\UE202','\UE203','\UE204','\UE205','\UE206','\UE207','\UE208','\UE209','\UE20A','\UE20B','\UE20C','\UE20D','\UE20E','\UE20F','\UE210','\UE211','\UE212','\UE213','\UE214','\UE215','\UE216','\UE217','\UE218','\UE219','\UE21A','\UE21B','\UE21C','\UE21D','\UE21E','\UE21F','\UE220','\UE221','\UE222','\UE223','\UE224','\UE225','\UE226','\UE227','\UE228','\UE229','\UE22A','\UE22B','\UE22C','\UE22D','\UE22E','\UE22F','\UE230','\UE231','\UE232','\UE233','\UE234','\UE235','\UE236','\UE237','\UE238','\UE239','\UE23A','\UE23B','\UE23C','\UE23D','\UE23E','\UE23F','\UE240','\UE241','\UE242','\UE243','\UE244','\UE245','\UE246','\UE247','\UE248','\UE249','\UE24A','\UE24B','\UE24C','\UE24D','\UE24E','\UE24F','\UE250','\UE251','\UE252','\UE253','\UE254','\UE255','\UE256','\UE257','\UE258','\UE259','\UE25A','\UE25B','\UE25C','\UE25D','\UE25E','\UE25F','\UE260','\UE261','\UE262','\UE263','\UE264','\UE265','\UE266','\UE267','\UE268','\UE269','\UE26A','\UE26B','\UE26C','\UE26D','\UE26E','\UE26F','\UE270','\UE271','\UE272','\UE273','\UE274','\UE275','\UE276','\UE277','\UE278','\UE279','\UE27A','\UE27B','\UE27C','\UE27D','\UE27E','\UE27F','\UE280','\UE281','\UE282','\UE283','\UE284','\UE285','\UE286','\UE287','\UE288','\UE289','\UE28A','\UE28B','\UE28C','\UE28D','\UE28E','\UE28F','\UE290','\UE291','\UE292','\UE293','\UE294','\UE295','\UE296','\UE297','\UE298','\UE299','\UE29A','\UE29B','\UE29C','\UE29D','\UE29E','\UE29F','\UE2A0','\UE2A1','\UE2A2','\UE2A3','\UE2A4','\UE2A5','\UE2A6','\UE2A7','\UE2A8','\UE2A9','\UE2AA','\UE2AB','\UE2AC','\UE2AD','\UE2AE','\UE2AF','\UE2B0','\UE2B1','\UE2B2','\UE2B3','\UE2B4','\UE2B5','\UE2B6','\UE2B7','\UE2B8','\UE2B9','\UE2BA','\UE2BB','\UE2BC','\UE2BD','\UE2BE','\UE2BF','\UE2C0','\UE2C1','\UE2C2','\UE2C3','\UE2C4','\UE2C5','\UE2C6','\UE2C7','\UE2C8','\UE2C9','\UE2CA','\UE2CB','\UE2CC','\UE2CD','\UE2CE','\UE2CF','\UE2D0','\UE2D1','\UE2D2','\UE2D3','\UE2D4','\UE2D5','\UE2D6','\UE2D7','\UE2D8','\UE2D9','\UE2DA','\UE2DB','\UE2DC','\UE2DD','\UE2DE','\UE2DF','\UE2E0','\UE2E1','\UE2E2','\UE2E3','\UE2E4','\UE2E5','\UE2E6','\UE2E7','\UE2E8','\UE2E9','\UE2EA','\UE2EB','\UE2EC','\UE2ED','\UE2EE','\UE2EF','\UE2F0','\UE2F1','\UE2F2','\UE2F3','\UE2F4','\UE2F5','\UE2F6','\UE2F7','\UE2F8','\UE2F9','\UE2FA','\UE2FB','\UE2FC','\UE2FD','\UE2FE','\UE2FF','\UE300','\UE301','\UE302','\UE303','\UE304','\UE305','\UE306','\UE307','\UE308','\UE309','\UE30A','\UE30B','\UE30C','\UE30D','\UE30E','\UE30F','\UE310','\UE311','\UE312','\UE313','\UE314','\UE315','\UE316','\UE317','\UE318','\UE319','\UE31A','\UE31B','\UE31C','\UE31D','\UE31E','\UE31F','\UE320','\UE321','\UE322','\UE323','\UE324','\UE325','\UE326','\UE327','\UE328','\UE329','\UE32A','\UE32B','\UE32C','\UE32D','\UE32E','\UE32F','\UE330','\UE331','\UE332','\UE333','\UE334','\UE335','\UE336','\UE337','\UE338','\UE339','\UE33A','\UE33B','\UE33C','\UE33D','\UE33E','\UE33F','\UE340','\UE341','\UE342','\UE343','\UE344','\UE345','\UE346','\UE347','\UE348','\UE349','\UE34A','\UE34B','\UE34C','\UE34D','\UE34E','\UE34F','\UE350','\UE351','\UE352','\UE353','\UE354','\UE355','\UE356','\UE357','\UE358','\UE359','\UE35A','\UE35B','\UE35C','\UE35D','\UE35E','\UE35F','\UE360','\UE361','\UE362','\UE363','\UE364','\UE365','\UE366','\UE367','\UE368','\UE369','\UE36A','\UE36B','\UE36C','\UE36D','\UE36E','\UE36F','\UE370','\UE371','\UE372','\UE373','\UE374','\UE375','\UE376','\UE377','\UE378','\UE379','\UE37A','\UE37B','\UE37C','\UE37D','\UE37E','\UE37F','\UE380','\UE381','\UE382','\UE383','\UE384','\UE385','\UE386','\UE387','\UE388','\UE389','\UE38A','\UE38B','\UE38C','\UE38D','\UE38E','\UE38F','\UE390','\UE391','\UE392','\UE393','\UE394','\UE395','\UE396','\UE397','\UE398','\UE399','\UE39A','\UE39B','\UE39C','\UE39D','\UE39E','\UE39F','\UE3A0','\UE3A1','\UE3A2','\UE3A3','\UE3A4','\UE3A5','\UE3A6','\UE3A7','\UE3A8','\UE3A9','\UE3AA','\UE3AB','\UE3AC','\UE3AD','\UE3AE','\UE3AF','\UE3B0','\UE3B1','\UE3B2','\UE3B3','\UE3B4','\UE3B5','\UE3B6','\UE3B7','\UE3B8','\UE3B9','\UE3BA','\UE3BB','\UE3BC','\UE3BD','\UE3BE','\UE3BF','\UE3C0','\UE3C1','\UE3C2','\UE3C3','\UE3C4','\UE3C5','\UE3C6','\UE3C7','\UE3C8','\UE3C9','\UE3CA','\UE3CB','\UE3CC','\UE3CD','\UE3CE','\UE3CF','\UE3D0','\UE3D1','\UE3D2','\UE3D3','\UE3D4','\UE3D5','\UE3D6','\UE3D7','\UE3D8','\UE3D9','\UE3DA','\UE3DB','\UE3DC','\UE3DD','\UE3DE','\UE3DF','\UE3E0','\UE3E1','\UE3E2','\UE3E3','\UE3E4','\UE3E5','\UE3E6','\UE3E7','\UE3E8','\UE3E9','\UE3EA','\UE3EB','\UE3EC','\UE3ED','\UE3EE','\UE3EF','\UE3F0','\UE3F1','\UE3F2','\UE3F3','\UE3F4','\UE3F5','\UE3F6','\UE3F7','\UE3F8','\UE3F9','\UE3FA','\UE3FB','\UE3FC','\UE3FD','\UE3FE','\UE3FF','\UE400','\UE401','\UE402','\UE403','\UE404','\UE405','\UE406','\UE407','\UE408','\UE409','\UE40A','\UE40B','\UE40C','\UE40D','\UE40E','\UE40F','\UE410','\UE411','\UE412','\UE413','\UE414','\UE415','\UE416','\UE417','\UE418','\UE419','\UE41A','\UE41B','\UE41C','\UE41D','\UE41E','\UE41F','\UE420','\UE421','\UE422','\UE423','\UE424','\UE425','\UE426','\UE427','\UE428','\UE429','\UE42A','\UE42B','\UE42C','\UE42D','\UE42E','\UE42F','\UE430','\UE431','\UE432','\UE433','\UE434','\UE435','\UE436','\UE437','\UE438','\UE439','\UE43A','\UE43B','\UE43C','\UE43D','\UE43E','\UE43F','\UE440','\UE441','\UE442','\UE443','\UE444','\UE445','\UE446','\UE447','\UE448','\UE449','\UE44A','\UE44B','\UE44C','\UE44D','\UE44E','\UE44F','\UE450','\UE451','\UE452','\UE453','\UE454','\UE455','\UE456','\UE457','\UE458','\UE459','\UE45A','\UE45B','\UE45C','\UE45D','\UE45E','\UE45F','\UE460','\UE461','\UE462','\UE463','\UE464','\UE465','\UE466','\UE467','\UE468','\UE469','\UE46A','\UE46B','\UE46C','\UE46D','\UE46E','\UE46F','\UE470','\UE471','\UE472','\UE473','\UE474','\UE475','\UE476','\UE477','\UE478','\UE479','\UE47A','\UE47B','\UE47C','\UE47D','\UE47E','\UE47F','\UE480','\UE481','\UE482','\UE483','\UE484','\UE485','\UE486','\UE487','\UE488','\UE489','\UE48A','\UE48B','\UE48C','\UE48D','\UE48E','\UE48F','\UE490','\UE491','\UE492','\UE493','\UE494','\UE495','\UE496','\UE497','\UE498','\UE499','\UE49A','\UE49B','\UE49C','\UE49D','\UE49E','\UE49F','\UE4A0','\UE4A1','\UE4A2','\UE4A3','\UE4A4','\UE4A5','\UE4A6','\UE4A7','\UE4A8','\UE4A9','\UE4AA','\UE4AB','\UE4AC','\UE4AD','\UE4AE','\UE4AF','\UE4B0','\UE4B1','\UE4B2','\UE4B3','\UE4B4','\UE4B5','\UE4B6','\UE4B7','\UE4B8','\UE4B9','\UE4BA','\UE4BB','\UE4BC','\UE4BD','\UE4BE','\UE4BF','\UE4C0','\UE4C1','\UE4C2','\UE4C3','\UE4C4','\UE4C5','\UE4C6','\UE4C7','\UE4C8','\UE4C9','\UE4CA','\UE4CB','\UE4CC','\UE4CD','\UE4CE','\UE4CF','\UE4D0','\UE4D1','\UE4D2','\UE4D3','\UE4D4','\UE4D5','\UE4D6','\UE4D7','\UE4D8','\UE4D9','\UE4DA','\UE4DB','\UE4DC','\UE4DD','\UE4DE','\UE4DF','\UE4E0','\UE4E1','\UE4E2','\UE4E3','\UE4E4','\UE4E5','\UE4E6','\UE4E7','\UE4E8','\UE4E9','\UE4EA','\UE4EB','\UE4EC','\UE4ED','\UE4EE','\UE4EF','\UE4F0','\UE4F1','\UE4F2','\UE4F3','\UE4F4','\UE4F5','\UE4F6','\UE4F7','\UE4F8','\UE4F9','\UE4FA','\UE4FB','\UE4FC','\UE4FD','\UE4FE','\UE4FF','\UE500','\UE501','\UE502','\UE503','\UE504','\UE505','\UE506','\UE507','\UE508','\UE509','\UE50A','\UE50B','\UE50C','\UE50D','\UE50E','\UE50F','\UE510','\UE511','\UE512','\UE513','\UE514','\UE515','\UE516','\UE517','\UE518','\UE519','\UE51A','\UE51B','\UE51C','\UE51D','\UE51E','\UE51F','\UE520','\UE521','\UE522','\UE523','\UE524','\UE525','\UE526','\UE527','\UE528','\UE529','\UE52A','\UE52B','\UE52C','\UE52D','\UE52E','\UE52F','\UE530','\UE531','\UE532','\UE533','\UE534','\UE535','\UE536','\UE537','\UE538','\UE539','\UE53A','\UE53B','\UE53C','\UE53D','\UE53E','\UE53F','\UE540','\UE541','\UE542','\UE543','\UE544','\UE545','\UE546','\UE547','\UE548','\UE549','\UE54A','\UE54B','\UE54C','\UE54D','\UE54E','\UE54F','\UE550','\UE551','\UE552','\UE553','\UE554','\UE555','\UE556','\UE557','\UE558','\UE559','\UE55A','\UE55B','\UE55C','\UE55D','\UE55E','\UE55F','\UE560','\UE561','\UE562','\UE563','\UE564','\UE565','\UE566','\UE567','\UE568','\UE569','\UE56A','\UE56B','\UE56C','\UE56D','\UE56E','\UE56F','\UE570','\UE571','\UE572','\UE573','\UE574','\UE575','\UE576','\UE577','\UE578','\UE579','\UE57A','\UE57B','\UE57C','\UE57D','\UE57E','\UE57F','\UE580','\UE581','\UE582','\UE583','\UE584','\UE585','\UE586','\UE587','\UE588','\UE589','\UE58A','\UE58B','\UE58C','\UE58D','\UE58E','\UE58F','\UE590','\UE591','\UE592','\UE593','\UE594','\UE595','\UE596','\UE597','\UE598','\UE599','\UE59A','\UE59B','\UE59C','\UE59D','\UE59E','\UE59F','\UE5A0','\UE5A1','\UE5A2','\UE5A3','\UE5A4','\UE5A5','\UE5A6','\UE5A7','\UE5A8','\UE5A9','\UE5AA','\UE5AB','\UE5AC','\UE5AD','\UE5AE','\UE5AF','\UE5B0','\UE5B1','\UE5B2','\UE5B3','\UE5B4','\UE5B5','\UE5B6','\UE5B7','\UE5B8','\UE5B9','\UE5BA','\UE5BB','\UE5BC','\UE5BD','\UE5BE','\UE5BF','\UE5C0','\UE5C1','\UE5C2','\UE5C3','\UE5C4','\UE5C5','\UE5C6','\UE5C7','\UE5C8','\UE5C9','\UE5CA','\UE5CB','\UE5CC','\UE5CD','\UE5CE','\UE5CF','\UE5D0','\UE5D1','\UE5D2','\UE5D3','\UE5D4','\UE5D5','\UE5D6','\UE5D7','\UE5D8','\UE5D9','\UE5DA','\UE5DB','\UE5DC','\UE5DD','\UE5DE','\UE5DF','\UE5E0','\UE5E1','\UE5E2','\UE5E3','\UE5E4','\UE5E5','\UE5E6','\UE5E7','\UE5E8','\UE5E9','\UE5EA','\UE5EB','\UE5EC','\UE5ED','\UE5EE','\UE5EF','\UE5F0','\UE5F1','\UE5F2','\UE5F3','\UE5F4','\UE5F5','\UE5F6','\UE5F7','\UE5F8','\UE5F9','\UE5FA','\UE5FB','\UE5FC','\UE5FD','\UE5FE','\UE5FF','\UE600','\UE601','\UE602','\UE603','\UE604','\UE605','\UE606','\UE607','\UE608','\UE609','\UE60A','\UE60B','\UE60C','\UE60D','\UE60E','\UE60F','\UE610','\UE611','\UE612','\UE613','\UE614','\UE615','\UE616','\UE617','\UE618','\UE619','\UE61A','\UE61B','\UE61C','\UE61D','\UE61E','\UE61F','\UE620','\UE621','\UE622','\UE623','\UE624','\UE625','\UE626','\UE627','\UE628','\UE629','\UE62A','\UE62B','\UE62C','\UE62D','\UE62E','\UE62F','\UE630','\UE631','\UE632','\UE633','\UE634','\UE635','\UE636','\UE637','\UE638','\UE639','\UE63A','\UE63B','\UE63C','\UE63D','\UE63E','\UE63F','\UE640','\UE641','\UE642','\UE643','\UE644','\UE645','\UE646','\UE647','\UE648','\UE649','\UE64A','\UE64B','\UE64C','\UE64D','\UE64E','\UE64F','\UE650','\UE651','\UE652','\UE653','\UE654','\UE655','\UE656','\UE657','\UE658','\UE659','\UE65A','\UE65B','\UE65C','\UE65D','\UE65E','\UE65F','\UE660','\UE661','\UE662','\UE663','\UE664','\UE665','\UE666','\UE667','\UE668','\UE669','\UE66A','\UE66B','\UE66C','\UE66D','\UE66E','\UE66F','\UE670','\UE671','\UE672','\UE673','\UE674','\UE675','\UE676','\UE677','\UE678','\UE679','\UE67A','\UE67B','\UE67C','\UE67D','\UE67E','\UE67F','\UE680','\UE681','\UE682','\UE683','\UE684','\UE685','\UE686','\UE687','\UE688','\UE689','\UE68A','\UE68B','\UE68C','\UE68D','\UE68E','\UE68F','\UE690','\UE691','\UE692','\UE693','\UE694','\UE695','\UE696','\UE697','\UE698','\UE699','\UE69A','\UE69B','\UE69C','\UE69D','\UE69E','\UE69F','\UE6A0','\UE6A1','\UE6A2','\UE6A3','\UE6A4','\UE6A5','\UE6A6','\UE6A7','\UE6A8','\UE6A9','\UE6AA','\UE6AB','\UE6AC','\UE6AD','\UE6AE','\UE6AF','\UE6B0','\UE6B1','\UE6B2','\UE6B3','\UE6B4','\UE6B5','\UE6B6','\UE6B7','\UE6B8','\UE6B9','\UE6BA','\UE6BB','\UE6BC','\UE6BD','\UE6BE','\UE6BF','\UE6C0','\UE6C1','\UE6C2','\UE6C3','\UE6C4','\UE6C5','\UE6C6','\UE6C7','\UE6C8','\UE6C9','\UE6CA','\UE6CB','\UE6CC','\UE6CD','\UE6CE','\UE6CF','\UE6D0','\UE6D1','\UE6D2','\UE6D3','\UE6D4','\UE6D5','\UE6D6','\UE6D7','\UE6D8','\UE6D9','\UE6DA','\UE6DB','\UE6DC','\UE6DD','\UE6DE','\UE6DF','\UE6E0','\UE6E1','\UE6E2','\UE6E3','\UE6E4','\UE6E5','\UE6E6','\UE6E7','\UE6E8','\UE6E9','\UE6EA','\UE6EB','\UE6EC','\UE6ED','\UE6EE','\UE6EF','\UE6F0','\UE6F1','\UE6F2','\UE6F3','\UE6F4','\UE6F5','\UE6F6','\UE6F7','\UE6F8','\UE6F9','\UE6FA','\UE6FB','\UE6FC','\UE6FD','\UE6FE','\UE6FF','\UE700','\UE701','\UE702','\UE703','\UE704','\UE705','\UE706','\UE707','\UE708','\UE709','\UE70A','\UE70B','\UE70C','\UE70D','\UE70E','\UE70F','\UE710','\UE711','\UE712','\UE713','\UE714','\UE715','\UE716','\UE717','\UE718','\UE719','\UE71A','\UE71B','\UE71C','\UE71D','\UE71E','\UE71F','\UE720','\UE721','\UE722','\UE723','\UE724','\UE725','\UE726','\UE727','\UE728','\UE729','\UE72A','\UE72B','\UE72C','\UE72D','\UE72E','\UE72F','\UE730','\UE731','\UE732','\UE733','\UE734','\UE735','\UE736','\UE737','\UE738','\UE739','\UE73A','\UE73B','\UE73C','\UE73D','\UE73E','\UE73F','\UE740','\UE741','\UE742','\UE743','\UE744','\UE745','\UE746','\UE747','\UE748','\UE749','\UE74A','\UE74B','\UE74C','\UE74D','\UE74E','\UE74F','\UE750','\UE751','\UE752','\UE753','\UE754','\UE755','\UE756','\UE757','\UE758','\UE759','\UE75A','\UE75B','\UE75C','\UE75D','\UE75E','\UE75F','\UE760','\UE761','\UE762','\UE763','\UE764','\UE765','\UE766','\UE767','\UE768','\UE769','\UE76A','\UE76B','\UE76C','\UE76D','\UE76E','\UE76F','\UE770','\UE771','\UE772','\UE773','\UE774','\UE775','\UE776','\UE777','\UE778','\UE779','\UE77A','\UE77B','\UE77C','\UE77D','\UE77E','\UE77F','\UE780','\UE781','\UE782','\UE783','\UE784','\UE785','\UE786','\UE787','\UE788','\UE789','\UE78A','\UE78B','\UE78C','\UE78D','\UE78E','\UE78F','\UE790','\UE791','\UE792','\UE793','\UE794','\UE795','\UE796','\UE797','\UE798','\UE799','\UE79A','\UE79B','\UE79C','\UE79D','\UE79E','\UE79F','\UE7A0','\UE7A1','\UE7A2','\UE7A3','\UE7A4','\UE7A5','\UE7A6','\UE7A7','\UE7A8','\UE7A9','\UE7AA','\UE7AB','\UE7AC','\UE7AD','\UE7AE','\UE7AF','\UE7B0','\UE7B1','\UE7B2','\UE7B3','\UE7B4','\UE7B5','\UE7B6','\UE7B7','\UE7B8','\UE7B9','\UE7BA','\UE7BB','\UE7BC','\UE7BD','\UE7BE','\UE7BF','\UE7C0','\UE7C1','\UE7C2','\UE7C3','\UE7C4','\UE7C5','\UE7C6','\UE7C7','\UE7C8','\UE7C9','\UE7CA','\UE7CB','\UE7CC','\UE7CD','\UE7CE','\UE7CF','\UE7D0','\UE7D1','\UE7D2','\UE7D3','\UE7D4','\UE7D5','\UE7D6','\UE7D7','\UE7D8','\UE7D9','\UE7DA','\UE7DB','\UE7DC','\UE7DD','\UE7DE','\UE7DF','\UE7E0','\UE7E1','\UE7E2','\UE7E3','\UE7E4','\UE7E5','\UE7E6','\UE7E7','\UE7E8','\UE7E9','\UE7EA','\UE7EB','\UE7EC','\UE7ED','\UE7EE','\UE7EF','\UE7F0','\UE7F1','\UE7F2','\UE7F3','\UE7F4','\UE7F5','\UE7F6','\UE7F7','\UE7F8','\UE7F9','\UE7FA','\UE7FB','\UE7FC','\UE7FD','\UE7FE','\UE7FF','\UE800','\UE801','\UE802','\UE803','\UE804','\UE805','\UE806','\UE807','\UE808','\UE809','\UE80A','\UE80B','\UE80C','\UE80D','\UE80E','\UE80F','\UE810','\UE811','\UE812','\UE813','\UE814','\UE815','\UE816','\UE817','\UE818','\UE819','\UE81A','\UE81B','\UE81C','\UE81D','\UE81E','\UE81F','\UE820','\UE821','\UE822','\UE823','\UE824','\UE825','\UE826','\UE827','\UE828','\UE829','\UE82A','\UE82B','\UE82C','\UE82D','\UE82E','\UE82F','\UE830','\UE831','\UE832','\UE833','\UE834','\UE835','\UE836','\UE837','\UE838','\UE839','\UE83A','\UE83B','\UE83C','\UE83D','\UE83E','\UE83F','\UE840','\UE841','\UE842','\UE843','\UE844','\UE845','\UE846','\UE847','\UE848','\UE849','\UE84A','\UE84B','\UE84C','\UE84D','\UE84E','\UE84F','\UE850','\UE851','\UE852','\UE853','\UE854','\UE855','\UE856','\UE857','\UE858','\UE859','\UE85A','\UE85B','\UE85C','\UE85D','\UE85E','\UE85F','\UE860','\UE861','\UE862','\UE863','\UE864','\UE865','\UE866','\UE867','\UE868','\UE869','\UE86A','\UE86B','\UE86C','\UE86D','\UE86E','\UE86F','\UE870','\UE871','\UE872','\UE873','\UE874','\UE875','\UE876','\UE877','\UE878','\UE879','\UE87A','\UE87B','\UE87C','\UE87D','\UE87E','\UE87F','\UE880','\UE881','\UE882','\UE883','\UE884','\UE885','\UE886','\UE887','\UE888','\UE889','\UE88A','\UE88B','\UE88C','\UE88D','\UE88E','\UE88F','\UE890','\UE891','\UE892','\UE893','\UE894','\UE895','\UE896','\UE897','\UE898','\UE899','\UE89A','\UE89B','\UE89C','\UE89D','\UE89E','\UE89F','\UE8A0','\UE8A1','\UE8A2','\UE8A3','\UE8A4','\UE8A5','\UE8A6','\UE8A7','\UE8A8','\UE8A9','\UE8AA','\UE8AB','\UE8AC','\UE8AD','\UE8AE','\UE8AF','\UE8B0','\UE8B1','\UE8B2','\UE8B3','\UE8B4','\UE8B5','\UE8B6','\UE8B7','\UE8B8','\UE8B9','\UE8BA','\UE8BB','\UE8BC','\UE8BD','\UE8BE','\UE8BF','\UE8C0','\UE8C1','\UE8C2','\UE8C3','\UE8C4','\UE8C5','\UE8C6','\UE8C7','\UE8C8','\UE8C9','\UE8CA','\UE8CB','\UE8CC','\UE8CD','\UE8CE','\UE8CF','\UE8D0','\UE8D1','\UE8D2','\UE8D3','\UE8D4','\UE8D5','\UE8D6','\UE8D7','\UE8D8','\UE8D9','\UE8DA','\UE8DB','\UE8DC','\UE8DD','\UE8DE','\UE8DF','\UE8E0','\UE8E1','\UE8E2','\UE8E3','\UE8E4','\UE8E5','\UE8E6','\UE8E7','\UE8E8','\UE8E9','\UE8EA','\UE8EB','\UE8EC','\UE8ED','\UE8EE','\UE8EF','\UE8F0','\UE8F1','\UE8F2','\UE8F3','\UE8F4','\UE8F5','\UE8F6','\UE8F7','\UE8F8','\UE8F9','\UE8FA','\UE8FB','\UE8FC','\UE8FD','\UE8FE','\UE8FF','\UE900','\UE901','\UE902','\UE903','\UE904','\UE905','\UE906','\UE907','\UE908','\UE909','\UE90A','\UE90B','\UE90C','\UE90D','\UE90E','\UE90F','\UE910','\UE911','\UE912','\UE913','\UE914','\UE915','\UE916','\UE917','\UE918','\UE919','\UE91A','\UE91B','\UE91C','\UE91D','\UE91E','\UE91F','\UE920','\UE921','\UE922','\UE923','\UE924','\UE925','\UE926','\UE927','\UE928','\UE929','\UE92A','\UE92B','\UE92C','\UE92D','\UE92E','\UE92F','\UE930','\UE931','\UE932','\UE933','\UE934','\UE935','\UE936','\UE937','\UE938','\UE939','\UE93A','\UE93B','\UE93C','\UE93D','\UE93E','\UE93F','\UE940','\UE941','\UE942','\UE943','\UE944','\UE945','\UE946','\UE947','\UE948','\UE949','\UE94A','\UE94B','\UE94C','\UE94D','\UE94E','\UE94F','\UE950','\UE951','\UE952','\UE953','\UE954','\UE955','\UE956','\UE957','\UE958','\UE959','\UE95A','\UE95B','\UE95C','\UE95D','\UE95E','\UE95F','\UE960','\UE961','\UE962','\UE963','\UE964','\UE965','\UE966','\UE967','\UE968','\UE969','\UE96A','\UE96B','\UE96C','\UE96D','\UE96E','\UE96F','\UE970','\UE971','\UE972','\UE973','\UE974','\UE975','\UE976','\UE977','\UE978','\UE979','\UE97A','\UE97B','\UE97C','\UE97D','\UE97E','\UE97F','\UE980','\UE981','\UE982','\UE983','\UE984','\UE985','\UE986','\UE987','\UE988','\UE989','\UE98A','\UE98B','\UE98C','\UE98D','\UE98E','\UE98F','\UE990','\UE991','\UE992','\UE993','\UE994','\UE995','\UE996','\UE997','\UE998','\UE999','\UE99A','\UE99B','\UE99C','\UE99D','\UE99E','\UE99F','\UE9A0','\UE9A1','\UE9A2','\UE9A3','\UE9A4','\UE9A5','\UE9A6','\UE9A7','\UE9A8','\UE9A9','\UE9AA','\UE9AB','\UE9AC','\UE9AD','\UE9AE','\UE9AF','\UE9B0','\UE9B1','\UE9B2','\UE9B3','\UE9B4','\UE9B5','\UE9B6','\UE9B7','\UE9B8','\UE9B9','\UE9BA','\UE9BB','\UE9BC','\UE9BD','\UE9BE','\UE9BF','\UE9C0','\UE9C1','\UE9C2','\UE9C3','\UE9C4','\UE9C5','\UE9C6','\UE9C7','\UE9C8','\UE9C9','\UE9CA','\UE9CB','\UE9CC','\UE9CD','\UE9CE','\UE9CF','\UE9D0','\UE9D1','\UE9D2','\UE9D3','\UE9D4','\UE9D5','\UE9D6','\UE9D7','\UE9D8','\UE9D9','\UE9DA','\UE9DB','\UE9DC','\UE9DD','\UE9DE','\UE9DF','\UE9E0','\UE9E1','\UE9E2','\UE9E3','\UE9E4','\UE9E5','\UE9E6','\UE9E7','\UE9E8','\UE9E9','\UE9EA','\UE9EB','\UE9EC','\UE9ED','\UE9EE','\UE9EF','\UE9F0','\UE9F1','\UE9F2','\UE9F3','\UE9F4','\UE9F5','\UE9F6','\UE9F7','\UE9F8','\UE9F9','\UE9FA','\UE9FB','\UE9FC','\UE9FD','\UE9FE','\UE9FF','\UEA00','\UEA01','\UEA02','\UEA03','\UEA04','\UEA05','\UEA06','\UEA07','\UEA08','\UEA09','\UEA0A','\UEA0B','\UEA0C','\UEA0D','\UEA0E','\UEA0F','\UEA10','\UEA11','\UEA12','\UEA13','\UEA14','\UEA15','\UEA16','\UEA17','\UEA18','\UEA19','\UEA1A','\UEA1B','\UEA1C','\UEA1D','\UEA1E','\UEA1F','\UEA20','\UEA21','\UEA22','\UEA23','\UEA24','\UEA25','\UEA26','\UEA27','\UEA28','\UEA29','\UEA2A','\UEA2B','\UEA2C','\UEA2D','\UEA2E','\UEA2F','\UEA30','\UEA31','\UEA32','\UEA33','\UEA34','\UEA35','\UEA36','\UEA37','\UEA38','\UEA39','\UEA3A','\UEA3B','\UEA3C','\UEA3D','\UEA3E','\UEA3F','\UEA40','\UEA41','\UEA42','\UEA43','\UEA44','\UEA45','\UEA46','\UEA47','\UEA48','\UEA49','\UEA4A','\UEA4B','\UEA4C','\UEA4D','\UEA4E','\UEA4F','\UEA50','\UEA51','\UEA52','\UEA53','\UEA54','\UEA55','\UEA56','\UEA57','\UEA58','\UEA59','\UEA5A','\UEA5B','\UEA5C','\UEA5D','\UEA5E','\UEA5F','\UEA60','\UEA61','\UEA62','\UEA63','\UEA64','\UEA65','\UEA66','\UEA67','\UEA68','\UEA69','\UEA6A','\UEA6B','\UEA6C','\UEA6D','\UEA6E','\UEA6F','\UEA70','\UEA71','\UEA72','\UEA73','\UEA74','\UEA75','\UEA76','\UEA77','\UEA78','\UEA79','\UEA7A','\UEA7B','\UEA7C','\UEA7D','\UEA7E','\UEA7F','\UEA80','\UEA81','\UEA82','\UEA83','\UEA84','\UEA85','\UEA86','\UEA87','\UEA88','\UEA89','\UEA8A','\UEA8B','\UEA8C','\UEA8D','\UEA8E','\UEA8F','\UEA90','\UEA91','\UEA92','\UEA93','\UEA94','\UEA95','\UEA96','\UEA97','\UEA98','\UEA99','\UEA9A','\UEA9B','\UEA9C','\UEA9D','\UEA9E','\UEA9F','\UEAA0','\UEAA1','\UEAA2','\UEAA3','\UEAA4','\UEAA5','\UEAA6','\UEAA7','\UEAA8','\UEAA9','\UEAAA','\UEAAB','\UEAAC','\UEAAD','\UEAAE','\UEAAF','\UEAB0','\UEAB1','\UEAB2','\UEAB3','\UEAB4','\UEAB5','\UEAB6','\UEAB7','\UEAB8','\UEAB9','\UEABA','\UEABB','\UEABC','\UEABD','\UEABE','\UEABF','\UEAC0','\UEAC1','\UEAC2','\UEAC3','\UEAC4','\UEAC5','\UEAC6','\UEAC7','\UEAC8','\UEAC9','\UEACA','\UEACB','\UEACC','\UEACD','\UEACE','\UEACF','\UEAD0','\UEAD1','\UEAD2','\UEAD3','\UEAD4','\UEAD5','\UEAD6','\UEAD7','\UEAD8','\UEAD9','\UEADA','\UEADB','\UEADC','\UEADD','\UEADE','\UEADF','\UEAE0','\UEAE1','\UEAE2','\UEAE3','\UEAE4','\UEAE5','\UEAE6','\UEAE7','\UEAE8','\UEAE9','\UEAEA','\UEAEB','\UEAEC','\UEAED','\UEAEE','\UEAEF','\UEAF0','\UEAF1','\UEAF2','\UEAF3','\UEAF4','\UEAF5','\UEAF6','\UEAF7','\UEAF8','\UEAF9','\UEAFA','\UEAFB','\UEAFC','\UEAFD','\UEAFE','\UEAFF','\UEB00','\UEB01','\UEB02','\UEB03','\UEB04','\UEB05','\UEB06','\UEB07','\UEB08','\UEB09','\UEB0A','\UEB0B','\UEB0C','\UEB0D','\UEB0E','\UEB0F','\UEB10','\UEB11','\UEB12','\UEB13','\UEB14','\UEB15','\UEB16','\UEB17','\UEB18','\UEB19','\UEB1A','\UEB1B','\UEB1C','\UEB1D','\UEB1E','\UEB1F','\UEB20','\UEB21','\UEB22','\UEB23','\UEB24','\UEB25','\UEB26','\UEB27','\UEB28','\UEB29','\UEB2A','\UEB2B','\UEB2C','\UEB2D','\UEB2E','\UEB2F','\UEB30','\UEB31','\UEB32','\UEB33','\UEB34','\UEB35','\UEB36','\UEB37','\UEB38','\UEB39','\UEB3A','\UEB3B','\UEB3C','\UEB3D','\UEB3E','\UEB3F','\UEB40','\UEB41','\UEB42','\UEB43','\UEB44','\UEB45','\UEB46','\UEB47','\UEB48','\UEB49','\UEB4A','\UEB4B','\UEB4C','\UEB4D','\UEB4E','\UEB4F','\UEB50','\UEB51','\UEB52','\UEB53','\UEB54','\UEB55','\UEB56','\UEB57','\UEB58','\UEB59','\UEB5A','\UEB5B','\UEB5C','\UEB5D','\UEB5E','\UEB5F','\UEB60','\UEB61','\UEB62','\UEB63','\UEB64','\UEB65','\UEB66','\UEB67','\UEB68','\UEB69','\UEB6A','\UEB6B','\UEB6C','\UEB6D','\UEB6E','\UEB6F','\UEB70','\UEB71','\UEB72','\UEB73','\UEB74','\UEB75','\UEB76','\UEB77','\UEB78','\UEB79','\UEB7A','\UEB7B','\UEB7C','\UEB7D','\UEB7E','\UEB7F','\UEB80','\UEB81','\UEB82','\UEB83','\UEB84','\UEB85','\UEB86','\UEB87','\UEB88','\UEB89','\UEB8A','\UEB8B','\UEB8C','\UEB8D','\UEB8E','\UEB8F','\UEB90','\UEB91','\UEB92','\UEB93','\UEB94','\UEB95','\UEB96','\UEB97','\UEB98','\UEB99','\UEB9A','\UEB9B','\UEB9C','\UEB9D','\UEB9E','\UEB9F','\UEBA0','\UEBA1','\UEBA2','\UEBA3','\UEBA4','\UEBA5','\UEBA6','\UEBA7','\UEBA8','\UEBA9','\UEBAA','\UEBAB','\UEBAC','\UEBAD','\UEBAE','\UEBAF','\UEBB0','\UEBB1','\UEBB2','\UEBB3','\UEBB4','\UEBB5','\UEBB6','\UEBB7','\UEBB8','\UEBB9','\UEBBA','\UEBBB','\UEBBC','\UEBBD','\UEBBE','\UEBBF','\UEBC0','\UEBC1','\UEBC2','\UEBC3','\UEBC4','\UEBC5','\UEBC6','\UEBC7','\UEBC8','\UEBC9','\UEBCA','\UEBCB','\UEBCC','\UEBCD','\UEBCE','\UEBCF','\UEBD0','\UEBD1','\UEBD2','\UEBD3','\UEBD4','\UEBD5','\UEBD6','\UEBD7','\UEBD8','\UEBD9','\UEBDA','\UEBDB','\UEBDC','\UEBDD','\UEBDE','\UEBDF','\UEBE0','\UEBE1','\UEBE2','\UEBE3','\UEBE4','\UEBE5','\UEBE6','\UEBE7','\UEBE8','\UEBE9','\UEBEA','\UEBEB','\UEBEC','\UEBED','\UEBEE','\UEBEF','\UEBF0','\UEBF1','\UEBF2','\UEBF3','\UEBF4','\UEBF5','\UEBF6','\UEBF7','\UEBF8','\UEBF9','\UEBFA','\UEBFB','\UEBFC','\UEBFD','\UEBFE','\UEBFF','\UEC00','\UEC01','\UEC02','\UEC03','\UEC04','\UEC05','\UEC06','\UEC07','\UEC08','\UEC09','\UEC0A','\UEC0B','\UEC0C','\UEC0D','\UEC0E','\UEC0F','\UEC10','\UEC11','\UEC12','\UEC13','\UEC14','\UEC15','\UEC16','\UEC17','\UEC18','\UEC19','\UEC1A','\UEC1B','\UEC1C','\UEC1D','\UEC1E','\UEC1F','\UEC20','\UEC21','\UEC22','\UEC23','\UEC24','\UEC25','\UEC26','\UEC27','\UEC28','\UEC29','\UEC2A','\UEC2B','\UEC2C','\UEC2D','\UEC2E','\UEC2F','\UEC30','\UEC31','\UEC32','\UEC33','\UEC34','\UEC35','\UEC36','\UEC37','\UEC38','\UEC39','\UEC3A','\UEC3B','\UEC3C','\UEC3D','\UEC3E','\UEC3F','\UEC40','\UEC41','\UEC42','\UEC43','\UEC44','\UEC45','\UEC46','\UEC47','\UEC48','\UEC49','\UEC4A','\UEC4B','\UEC4C','\UEC4D','\UEC4E','\UEC4F','\UEC50','\UEC51','\UEC52','\UEC53','\UEC54','\UEC55','\UEC56','\UEC57','\UEC58','\UEC59','\UEC5A','\UEC5B','\UEC5C','\UEC5D','\UEC5E','\UEC5F','\UEC60','\UEC61','\UEC62','\UEC63','\UEC64','\UEC65','\UEC66','\UEC67','\UEC68','\UEC69','\UEC6A','\UEC6B','\UEC6C','\UEC6D','\UEC6E','\UEC6F','\UEC70','\UEC71','\UEC72','\UEC73','\UEC74','\UEC75','\UEC76','\UEC77','\UEC78','\UEC79','\UEC7A','\UEC7B','\UEC7C','\UEC7D','\UEC7E','\UEC7F','\UEC80','\UEC81','\UEC82','\UEC83','\UEC84','\UEC85','\UEC86','\UEC87','\UEC88','\UEC89','\UEC8A','\UEC8B','\UEC8C','\UEC8D','\UEC8E','\UEC8F','\UEC90','\UEC91','\UEC92','\UEC93','\UEC94','\UEC95','\UEC96','\UEC97','\UEC98','\UEC99','\UEC9A','\UEC9B','\UEC9C','\UEC9D','\UEC9E','\UEC9F','\UECA0','\UECA1','\UECA2','\UECA3','\UECA4','\UECA5','\UECA6','\UECA7','\UECA8','\UECA9','\UECAA','\UECAB','\UECAC','\UECAD','\UECAE','\UECAF','\UECB0','\UECB1','\UECB2','\UECB3','\UECB4','\UECB5','\UECB6','\UECB7','\UECB8','\UECB9','\UECBA','\UECBB','\UECBC','\UECBD','\UECBE','\UECBF','\UECC0','\UECC1','\UECC2','\UECC3','\UECC4','\UECC5','\UECC6','\UECC7','\UECC8','\UECC9','\UECCA','\UECCB','\UECCC','\UECCD','\UECCE','\UECCF','\UECD0','\UECD1','\UECD2','\UECD3','\UECD4','\UECD5','\UECD6','\UECD7','\UECD8','\UECD9','\UECDA','\UECDB','\UECDC','\UECDD','\UECDE','\UECDF','\UECE0','\UECE1','\UECE2','\UECE3','\UECE4','\UECE5','\UECE6','\UECE7','\UECE8','\UECE9','\UECEA','\UECEB','\UECEC','\UECED','\UECEE','\UECEF','\UECF0','\UECF1','\UECF2','\UECF3','\UECF4','\UECF5','\UECF6','\UECF7','\UECF8','\UECF9','\UECFA','\UECFB','\UECFC','\UECFD','\UECFE','\UECFF','\UED00','\UED01','\UED02','\UED03','\UED04','\UED05','\UED06','\UED07','\UED08','\UED09','\UED0A','\UED0B','\UED0C','\UED0D','\UED0E','\UED0F','\UED10','\UED11','\UED12','\UED13','\UED14','\UED15','\UED16','\UED17','\UED18','\UED19','\UED1A','\UED1B','\UED1C','\UED1D','\UED1E','\UED1F','\UED20','\UED21','\UED22','\UED23','\UED24','\UED25','\UED26','\UED27','\UED28','\UED29','\UED2A','\UED2B','\UED2C','\UED2D','\UED2E','\UED2F','\UED30','\UED31','\UED32','\UED33','\UED34','\UED35','\UED36','\UED37','\UED38','\UED39','\UED3A','\UED3B','\UED3C','\UED3D','\UED3E','\UED3F','\UED40','\UED41','\UED42','\UED43','\UED44','\UED45','\UED46','\UED47','\UED48','\UED49','\UED4A','\UED4B','\UED4C','\UED4D','\UED4E','\UED4F','\UED50','\UED51','\UED52','\UED53','\UED54','\UED55','\UED56','\UED57','\UED58','\UED59','\UED5A','\UED5B','\UED5C','\UED5D','\UED5E','\UED5F','\UED60','\UED61','\UED62','\UED63','\UED64','\UED65','\UED66','\UED67','\UED68','\UED69','\UED6A','\UED6B','\UED6C','\UED6D','\UED6E','\UED6F','\UED70','\UED71','\UED72','\UED73','\UED74','\UED75','\UED76','\UED77','\UED78','\UED79','\UED7A','\UED7B','\UED7C','\UED7D','\UED7E','\UED7F','\UED80','\UED81','\UED82','\UED83','\UED84','\UED85','\UED86','\UED87','\UED88','\UED89','\UED8A','\UED8B','\UED8C','\UED8D','\UED8E','\UED8F','\UED90','\UED91','\UED92','\UED93','\UED94','\UED95','\UED96','\UED97','\UED98','\UED99','\UED9A','\UED9B','\UED9C','\UED9D','\UED9E','\UED9F','\UEDA0','\UEDA1','\UEDA2','\UEDA3','\UEDA4','\UEDA5','\UEDA6','\UEDA7','\UEDA8','\UEDA9','\UEDAA','\UEDAB','\UEDAC','\UEDAD','\UEDAE','\UEDAF','\UEDB0','\UEDB1','\UEDB2','\UEDB3','\UEDB4','\UEDB5','\UEDB6','\UEDB7','\UEDB8','\UEDB9','\UEDBA','\UEDBB','\UEDBC','\UEDBD','\UEDBE','\UEDBF','\UEDC0','\UEDC1','\UEDC2','\UEDC3','\UEDC4','\UEDC5','\UEDC6','\UEDC7','\UEDC8','\UEDC9','\UEDCA','\UEDCB','\UEDCC','\UEDCD','\UEDCE','\UEDCF','\UEDD0','\UEDD1','\UEDD2','\UEDD3','\UEDD4','\UEDD5','\UEDD6','\UEDD7','\UEDD8','\UEDD9','\UEDDA','\UEDDB','\UEDDC','\UEDDD','\UEDDE','\UEDDF','\UEDE0','\UEDE1','\UEDE2','\UEDE3','\UEDE4','\UEDE5','\UEDE6','\UEDE7','\UEDE8','\UEDE9','\UEDEA','\UEDEB','\UEDEC','\UEDED','\UEDEE','\UEDEF','\UEDF0','\UEDF1','\UEDF2','\UEDF3','\UEDF4','\UEDF5','\UEDF6','\UEDF7','\UEDF8','\UEDF9','\UEDFA','\UEDFB','\UEDFC','\UEDFD','\UEDFE','\UEDFF','\UEE00','\UEE01','\UEE02','\UEE03','\UEE04','\UEE05','\UEE06','\UEE07','\UEE08','\UEE09','\UEE0A','\UEE0B','\UEE0C','\UEE0D','\UEE0E','\UEE0F','\UEE10','\UEE11','\UEE12','\UEE13','\UEE14','\UEE15','\UEE16','\UEE17','\UEE18','\UEE19','\UEE1A','\UEE1B','\UEE1C','\UEE1D','\UEE1E','\UEE1F','\UEE20','\UEE21','\UEE22','\UEE23','\UEE24','\UEE25','\UEE26','\UEE27','\UEE28','\UEE29','\UEE2A','\UEE2B','\UEE2C','\UEE2D','\UEE2E','\UEE2F','\UEE30','\UEE31','\UEE32','\UEE33','\UEE34','\UEE35','\UEE36','\UEE37','\UEE38','\UEE39','\UEE3A','\UEE3B','\UEE3C','\UEE3D','\UEE3E','\UEE3F','\UEE40','\UEE41','\UEE42','\UEE43','\UEE44','\UEE45','\UEE46','\UEE47','\UEE48','\UEE49','\UEE4A','\UEE4B','\UEE4C','\UEE4D','\UEE4E','\UEE4F','\UEE50','\UEE51','\UEE52','\UEE53','\UEE54','\UEE55','\UEE56','\UEE57','\UEE58','\UEE59','\UEE5A','\UEE5B','\UEE5C','\UEE5D','\UEE5E','\UEE5F','\UEE60','\UEE61','\UEE62','\UEE63','\UEE64','\UEE65','\UEE66','\UEE67','\UEE68','\UEE69','\UEE6A','\UEE6B','\UEE6C','\UEE6D','\UEE6E','\UEE6F','\UEE70','\UEE71','\UEE72','\UEE73','\UEE74','\UEE75','\UEE76','\UEE77','\UEE78','\UEE79','\UEE7A','\UEE7B','\UEE7C','\UEE7D','\UEE7E','\UEE7F','\UEE80','\UEE81','\UEE82','\UEE83','\UEE84','\UEE85','\UEE86','\UEE87','\UEE88','\UEE89','\UEE8A','\UEE8B','\UEE8C','\UEE8D','\UEE8E','\UEE8F','\UEE90','\UEE91','\UEE92','\UEE93','\UEE94','\UEE95','\UEE96','\UEE97','\UEE98','\UEE99','\UEE9A','\UEE9B','\UEE9C','\UEE9D','\UEE9E','\UEE9F','\UEEA0','\UEEA1','\UEEA2','\UEEA3','\UEEA4','\UEEA5','\UEEA6','\UEEA7','\UEEA8','\UEEA9','\UEEAA','\UEEAB','\UEEAC','\UEEAD','\UEEAE','\UEEAF','\UEEB0','\UEEB1','\UEEB2','\UEEB3','\UEEB4','\UEEB5','\UEEB6','\UEEB7','\UEEB8','\UEEB9','\UEEBA','\UEEBB','\UEEBC','\UEEBD','\UEEBE','\UEEBF','\UEEC0','\UEEC1','\UEEC2','\UEEC3','\UEEC4','\UEEC5','\UEEC6','\UEEC7','\UEEC8','\UEEC9','\UEECA','\UEECB','\UEECC','\UEECD','\UEECE','\UEECF','\UEED0','\UEED1','\UEED2','\UEED3','\UEED4','\UEED5','\UEED6','\UEED7','\UEED8','\UEED9','\UEEDA','\UEEDB','\UEEDC','\UEEDD','\UEEDE','\UEEDF','\UEEE0','\UEEE1','\UEEE2','\UEEE3','\UEEE4','\UEEE5','\UEEE6','\UEEE7','\UEEE8','\UEEE9','\UEEEA','\UEEEB','\UEEEC','\UEEED','\UEEEE','\UEEEF','\UEEF0','\UEEF1','\UEEF2','\UEEF3','\UEEF4','\UEEF5','\UEEF6','\UEEF7','\UEEF8','\UEEF9','\UEEFA','\UEEFB','\UEEFC','\UEEFD','\UEEFE','\UEEFF','\UEF00','\UEF01','\UEF02','\UEF03','\UEF04','\UEF05','\UEF06','\UEF07','\UEF08','\UEF09','\UEF0A','\UEF0B','\UEF0C','\UEF0D','\UEF0E','\UEF0F','\UEF10','\UEF11','\UEF12','\UEF13','\UEF14','\UEF15','\UEF16','\UEF17','\UEF18','\UEF19','\UEF1A','\UEF1B','\UEF1C','\UEF1D','\UEF1E','\UEF1F','\UEF20','\UEF21','\UEF22','\UEF23','\UEF24','\UEF25','\UEF26','\UEF27','\UEF28','\UEF29','\UEF2A','\UEF2B','\UEF2C','\UEF2D','\UEF2E','\UEF2F','\UEF30','\UEF31','\UEF32','\UEF33','\UEF34','\UEF35','\UEF36','\UEF37','\UEF38','\UEF39','\UEF3A','\UEF3B','\UEF3C','\UEF3D','\UEF3E','\UEF3F','\UEF40','\UEF41','\UEF42','\UEF43','\UEF44','\UEF45','\UEF46','\UEF47','\UEF48','\UEF49','\UEF4A','\UEF4B','\UEF4C','\UEF4D','\UEF4E','\UEF4F','\UEF50','\UEF51','\UEF52','\UEF53','\UEF54','\UEF55','\UEF56','\UEF57','\UEF58','\UEF59','\UEF5A','\UEF5B','\UEF5C','\UEF5D','\UEF5E','\UEF5F','\UEF60','\UEF61','\UEF62','\UEF63','\UEF64','\UEF65','\UEF66','\UEF67','\UEF68','\UEF69','\UEF6A','\UEF6B','\UEF6C','\UEF6D','\UEF6E','\UEF6F','\UEF70','\UEF71','\UEF72','\UEF73','\UEF74','\UEF75','\UEF76','\UEF77','\UEF78','\UEF79','\UEF7A','\UEF7B','\UEF7C','\UEF7D','\UEF7E','\UEF7F','\UEF80','\UEF81','\UEF82','\UEF83','\UEF84','\UEF85','\UEF86','\UEF87','\UEF88','\UEF89','\UEF8A','\UEF8B','\UEF8C','\UEF8D','\UEF8E','\UEF8F','\UEF90','\UEF91','\UEF92','\UEF93','\UEF94','\UEF95','\UEF96','\UEF97','\UEF98','\UEF99','\UEF9A','\UEF9B','\UEF9C','\UEF9D','\UEF9E','\UEF9F','\UEFA0','\UEFA1','\UEFA2','\UEFA3','\UEFA4','\UEFA5','\UEFA6','\UEFA7','\UEFA8','\UEFA9','\UEFAA','\UEFAB','\UEFAC','\UEFAD','\UEFAE','\UEFAF','\UEFB0','\UEFB1','\UEFB2','\UEFB3','\UEFB4','\UEFB5','\UEFB6','\UEFB7','\UEFB8','\UEFB9','\UEFBA','\UEFBB','\UEFBC','\UEFBD','\UEFBE','\UEFBF','\UEFC0','\UEFC1','\UEFC2','\UEFC3','\UEFC4','\UEFC5','\UEFC6','\UEFC7','\UEFC8','\UEFC9','\UEFCA','\UEFCB','\UEFCC','\UEFCD','\UEFCE','\UEFCF','\UEFD0','\UEFD1','\UEFD2','\UEFD3','\UEFD4','\UEFD5','\UEFD6','\UEFD7','\UEFD8','\UEFD9','\UEFDA','\UEFDB','\UEFDC','\UEFDD','\UEFDE','\UEFDF','\UEFE0','\UEFE1','\UEFE2','\UEFE3','\UEFE4','\UEFE5','\UEFE6','\UEFE7','\UEFE8','\UEFE9','\UEFEA','\UEFEB','\UEFEC','\UEFED','\UEFEE','\UEFEF','\UEFF0','\UEFF1','\UEFF2','\UEFF3','\UEFF4','\UEFF5','\UEFF6','\UEFF7','\UEFF8','\UEFF9','\UEFFA','\UEFFB','\UEFFC','\UEFFD','\UEFFE','\UEFFF','\UF000','\UF001','\UF002','\UF003','\UF004','\UF005','\UF006','\UF007','\UF008','\UF009','\UF00A','\UF00B','\UF00C','\UF00D','\UF00E','\UF00F','\UF010','\UF011','\UF012','\UF013','\UF014','\UF015','\UF016','\UF017','\UF018','\UF019','\UF01A','\UF01B','\UF01C','\UF01D','\UF01E','\UF01F','\UF020','\UF021','\UF022','\UF023','\UF024','\UF025','\UF026','\UF027','\UF028','\UF029','\UF02A','\UF02B','\UF02C','\UF02D','\UF02E','\UF02F','\UF030','\UF031','\UF032','\UF033','\UF034','\UF035','\UF036','\UF037','\UF038','\UF039','\UF03A','\UF03B','\UF03C','\UF03D','\UF03E','\UF03F','\UF040','\UF041','\UF042','\UF043','\UF044','\UF045','\UF046','\UF047','\UF048','\UF049','\UF04A','\UF04B','\UF04C','\UF04D','\UF04E','\UF04F','\UF050','\UF051','\UF052','\UF053','\UF054','\UF055','\UF056','\UF057','\UF058','\UF059','\UF05A','\UF05B','\UF05C','\UF05D','\UF05E','\UF05F','\UF060','\UF061','\UF062','\UF063','\UF064','\UF065','\UF066','\UF067','\UF068','\UF069','\UF06A','\UF06B','\UF06C','\UF06D','\UF06E','\UF06F','\UF070','\UF071','\UF072','\UF073','\UF074','\UF075','\UF076','\UF077','\UF078','\UF079','\UF07A','\UF07B','\UF07C','\UF07D','\UF07E','\UF07F','\UF080','\UF081','\UF082','\UF083','\UF084','\UF085','\UF086','\UF087','\UF088','\UF089','\UF08A','\UF08B','\UF08C','\UF08D','\UF08E','\UF08F','\UF090','\UF091','\UF092','\UF093','\UF094','\UF095','\UF096','\UF097','\UF098','\UF099','\UF09A','\UF09B','\UF09C','\UF09D','\UF09E','\UF09F','\UF0A0','\UF0A1','\UF0A2','\UF0A3','\UF0A4','\UF0A5','\UF0A6','\UF0A7','\UF0A8','\UF0A9','\UF0AA','\UF0AB','\UF0AC','\UF0AD','\UF0AE','\UF0AF','\UF0B0','\UF0B1','\UF0B2','\UF0B3','\UF0B4','\UF0B5','\UF0B6','\UF0B7','\UF0B8','\UF0B9','\UF0BA','\UF0BB','\UF0BC','\UF0BD','\UF0BE','\UF0BF','\UF0C0','\UF0C1','\UF0C2','\UF0C3','\UF0C4','\UF0C5','\UF0C6','\UF0C7','\UF0C8','\UF0C9','\UF0CA','\UF0CB','\UF0CC','\UF0CD','\UF0CE','\UF0CF','\UF0D0','\UF0D1','\UF0D2','\UF0D3','\UF0D4','\UF0D5','\UF0D6','\UF0D7','\UF0D8','\UF0D9','\UF0DA','\UF0DB','\UF0DC','\UF0DD','\UF0DE','\UF0DF','\UF0E0','\UF0E1','\UF0E2','\UF0E3','\UF0E4','\UF0E5','\UF0E6','\UF0E7','\UF0E8','\UF0E9','\UF0EA','\UF0EB','\UF0EC','\UF0ED','\UF0EE','\UF0EF','\UF0F0','\UF0F1','\UF0F2','\UF0F3','\UF0F4','\UF0F5','\UF0F6','\UF0F7','\UF0F8','\UF0F9','\UF0FA','\UF0FB','\UF0FC','\UF0FD','\UF0FE','\UF0FF','\UF100','\UF101','\UF102','\UF103','\UF104','\UF105','\UF106','\UF107','\UF108','\UF109','\UF10A','\UF10B','\UF10C','\UF10D','\UF10E','\UF10F','\UF110','\UF111','\UF112','\UF113','\UF114','\UF115','\UF116','\UF117','\UF118','\UF119','\UF11A','\UF11B','\UF11C','\UF11D','\UF11E','\UF11F','\UF120','\UF121','\UF122','\UF123','\UF124','\UF125','\UF126','\UF127','\UF128','\UF129','\UF12A','\UF12B','\UF12C','\UF12D','\UF12E','\UF12F','\UF130','\UF131','\UF132','\UF133','\UF134','\UF135','\UF136','\UF137','\UF138','\UF139','\UF13A','\UF13B','\UF13C','\UF13D','\UF13E','\UF13F','\UF140','\UF141','\UF142','\UF143','\UF144','\UF145','\UF146','\UF147','\UF148','\UF149','\UF14A','\UF14B','\UF14C','\UF14D','\UF14E','\UF14F','\UF150','\UF151','\UF152','\UF153','\UF154','\UF155','\UF156','\UF157','\UF158','\UF159','\UF15A','\UF15B','\UF15C','\UF15D','\UF15E','\UF15F','\UF160','\UF161','\UF162','\UF163','\UF164','\UF165','\UF166','\UF167','\UF168','\UF169','\UF16A','\UF16B','\UF16C','\UF16D','\UF16E','\UF16F','\UF170','\UF171','\UF172','\UF173','\UF174','\UF175','\UF176','\UF177','\UF178','\UF179','\UF17A','\UF17B','\UF17C','\UF17D','\UF17E','\UF17F','\UF180','\UF181','\UF182','\UF183','\UF184','\UF185','\UF186','\UF187','\UF188','\UF189','\UF18A','\UF18B','\UF18C','\UF18D','\UF18E','\UF18F','\UF190','\UF191','\UF192','\UF193','\UF194','\UF195','\UF196','\UF197','\UF198','\UF199','\UF19A','\UF19B','\UF19C','\UF19D','\UF19E','\UF19F','\UF1A0','\UF1A1','\UF1A2','\UF1A3','\UF1A4','\UF1A5','\UF1A6','\UF1A7','\UF1A8','\UF1A9','\UF1AA','\UF1AB','\UF1AC','\UF1AD','\UF1AE','\UF1AF','\UF1B0','\UF1B1','\UF1B2','\UF1B3','\UF1B4','\UF1B5','\UF1B6','\UF1B7','\UF1B8','\UF1B9','\UF1BA','\UF1BB','\UF1BC','\UF1BD','\UF1BE','\UF1BF','\UF1C0','\UF1C1','\UF1C2','\UF1C3','\UF1C4','\UF1C5','\UF1C6','\UF1C7','\UF1C8','\UF1C9','\UF1CA','\UF1CB','\UF1CC','\UF1CD','\UF1CE','\UF1CF','\UF1D0','\UF1D1','\UF1D2','\UF1D3','\UF1D4','\UF1D5','\UF1D6','\UF1D7','\UF1D8','\UF1D9','\UF1DA','\UF1DB','\UF1DC','\UF1DD','\UF1DE','\UF1DF','\UF1E0','\UF1E1','\UF1E2','\UF1E3','\UF1E4','\UF1E5','\UF1E6','\UF1E7','\UF1E8','\UF1E9','\UF1EA','\UF1EB','\UF1EC','\UF1ED','\UF1EE','\UF1EF','\UF1F0','\UF1F1','\UF1F2','\UF1F3','\UF1F4','\UF1F5','\UF1F6','\UF1F7','\UF1F8','\UF1F9','\UF1FA','\UF1FB','\UF1FC','\UF1FD','\UF1FE','\UF1FF','\UF200','\UF201','\UF202','\UF203','\UF204','\UF205','\UF206','\UF207','\UF208','\UF209','\UF20A','\UF20B','\UF20C','\UF20D','\UF20E','\UF20F','\UF210','\UF211','\UF212','\UF213','\UF214','\UF215','\UF216','\UF217','\UF218','\UF219','\UF21A','\UF21B','\UF21C','\UF21D','\UF21E','\UF21F','\UF220','\UF221','\UF222','\UF223','\UF224','\UF225','\UF226','\UF227','\UF228','\UF229','\UF22A','\UF22B','\UF22C','\UF22D','\UF22E','\UF22F','\UF230','\UF231','\UF232','\UF233','\UF234','\UF235','\UF236','\UF237','\UF238','\UF239','\UF23A','\UF23B','\UF23C','\UF23D','\UF23E','\UF23F','\UF240','\UF241','\UF242','\UF243','\UF244','\UF245','\UF246','\UF247','\UF248','\UF249','\UF24A','\UF24B','\UF24C','\UF24D','\UF24E','\UF24F','\UF250','\UF251','\UF252','\UF253','\UF254','\UF255','\UF256','\UF257','\UF258','\UF259','\UF25A','\UF25B','\UF25C','\UF25D','\UF25E','\UF25F','\UF260','\UF261','\UF262','\UF263','\UF264','\UF265','\UF266','\UF267','\UF268','\UF269','\UF26A','\UF26B','\UF26C','\UF26D','\UF26E','\UF26F','\UF270','\UF271','\UF272','\UF273','\UF274','\UF275','\UF276','\UF277','\UF278','\UF279','\UF27A','\UF27B','\UF27C','\UF27D','\UF27E','\UF27F','\UF280','\UF281','\UF282','\UF283','\UF284','\UF285','\UF286','\UF287','\UF288','\UF289','\UF28A','\UF28B','\UF28C','\UF28D','\UF28E','\UF28F','\UF290','\UF291','\UF292','\UF293','\UF294','\UF295','\UF296','\UF297','\UF298','\UF299','\UF29A','\UF29B','\UF29C','\UF29D','\UF29E','\UF29F','\UF2A0','\UF2A1','\UF2A2','\UF2A3','\UF2A4','\UF2A5','\UF2A6','\UF2A7','\UF2A8','\UF2A9','\UF2AA','\UF2AB','\UF2AC','\UF2AD','\UF2AE','\UF2AF','\UF2B0','\UF2B1','\UF2B2','\UF2B3','\UF2B4','\UF2B5','\UF2B6','\UF2B7','\UF2B8','\UF2B9','\UF2BA','\UF2BB','\UF2BC','\UF2BD','\UF2BE','\UF2BF','\UF2C0','\UF2C1','\UF2C2','\UF2C3','\UF2C4','\UF2C5','\UF2C6','\UF2C7','\UF2C8','\UF2C9','\UF2CA','\UF2CB','\UF2CC','\UF2CD','\UF2CE','\UF2CF','\UF2D0','\UF2D1','\UF2D2','\UF2D3','\UF2D4','\UF2D5','\UF2D6','\UF2D7','\UF2D8','\UF2D9','\UF2DA','\UF2DB','\UF2DC','\UF2DD','\UF2DE','\UF2DF','\UF2E0','\UF2E1','\UF2E2','\UF2E3','\UF2E4','\UF2E5','\UF2E6','\UF2E7','\UF2E8','\UF2E9','\UF2EA','\UF2EB','\UF2EC','\UF2ED','\UF2EE','\UF2EF','\UF2F0','\UF2F1','\UF2F2','\UF2F3','\UF2F4','\UF2F5','\UF2F6','\UF2F7','\UF2F8','\UF2F9','\UF2FA','\UF2FB','\UF2FC','\UF2FD','\UF2FE','\UF2FF','\UF300','\UF301','\UF302','\UF303','\UF304','\UF305','\UF306','\UF307','\UF308','\UF309','\UF30A','\UF30B','\UF30C','\UF30D','\UF30E','\UF30F','\UF310','\UF311','\UF312','\UF313','\UF314','\UF315','\UF316','\UF317','\UF318','\UF319','\UF31A','\UF31B','\UF31C','\UF31D','\UF31E','\UF31F','\UF320','\UF321','\UF322','\UF323','\UF324','\UF325','\UF326','\UF327','\UF328','\UF329','\UF32A','\UF32B','\UF32C','\UF32D','\UF32E','\UF32F','\UF330','\UF331','\UF332','\UF333','\UF334','\UF335','\UF336','\UF337','\UF338','\UF339','\UF33A','\UF33B','\UF33C','\UF33D','\UF33E','\UF33F','\UF340','\UF341','\UF342','\UF343','\UF344','\UF345','\UF346','\UF347','\UF348','\UF349','\UF34A','\UF34B','\UF34C','\UF34D','\UF34E','\UF34F','\UF350','\UF351','\UF352','\UF353','\UF354','\UF355','\UF356','\UF357','\UF358','\UF359','\UF35A','\UF35B','\UF35C','\UF35D','\UF35E','\UF35F','\UF360','\UF361','\UF362','\UF363','\UF364','\UF365','\UF366','\UF367','\UF368','\UF369','\UF36A','\UF36B','\UF36C','\UF36D','\UF36E','\UF36F','\UF370','\UF371','\UF372','\UF373','\UF374','\UF375','\UF376','\UF377','\UF378','\UF379','\UF37A','\UF37B','\UF37C','\UF37D','\UF37E','\UF37F','\UF380','\UF381','\UF382','\UF383','\UF384','\UF385','\UF386','\UF387','\UF388','\UF389','\UF38A','\UF38B','\UF38C','\UF38D','\UF38E','\UF38F','\UF390','\UF391','\UF392','\UF393','\UF394','\UF395','\UF396','\UF397','\UF398','\UF399','\UF39A','\UF39B','\UF39C','\UF39D','\UF39E','\UF39F','\UF3A0','\UF3A1','\UF3A2','\UF3A3','\UF3A4','\UF3A5','\UF3A6','\UF3A7','\UF3A8','\UF3A9','\UF3AA','\UF3AB','\UF3AC','\UF3AD','\UF3AE','\UF3AF','\UF3B0','\UF3B1','\UF3B2','\UF3B3','\UF3B4','\UF3B5','\UF3B6','\UF3B7','\UF3B8','\UF3B9','\UF3BA','\UF3BB','\UF3BC','\UF3BD','\UF3BE','\UF3BF','\UF3C0','\UF3C1','\UF3C2','\UF3C3','\UF3C4','\UF3C5','\UF3C6','\UF3C7','\UF3C8','\UF3C9','\UF3CA','\UF3CB','\UF3CC','\UF3CD','\UF3CE','\UF3CF','\UF3D0','\UF3D1','\UF3D2','\UF3D3','\UF3D4','\UF3D5','\UF3D6','\UF3D7','\UF3D8','\UF3D9','\UF3DA','\UF3DB','\UF3DC','\UF3DD','\UF3DE','\UF3DF','\UF3E0','\UF3E1','\UF3E2','\UF3E3','\UF3E4','\UF3E5','\UF3E6','\UF3E7','\UF3E8','\UF3E9','\UF3EA','\UF3EB','\UF3EC','\UF3ED','\UF3EE','\UF3EF','\UF3F0','\UF3F1','\UF3F2','\UF3F3','\UF3F4','\UF3F5','\UF3F6','\UF3F7','\UF3F8','\UF3F9','\UF3FA','\UF3FB','\UF3FC','\UF3FD','\UF3FE','\UF3FF','\UF400','\UF401','\UF402','\UF403','\UF404','\UF405','\UF406','\UF407','\UF408','\UF409','\UF40A','\UF40B','\UF40C','\UF40D','\UF40E','\UF40F','\UF410','\UF411','\UF412','\UF413','\UF414','\UF415','\UF416','\UF417','\UF418','\UF419','\UF41A','\UF41B','\UF41C','\UF41D','\UF41E','\UF41F','\UF420','\UF421','\UF422','\UF423','\UF424','\UF425','\UF426','\UF427','\UF428','\UF429','\UF42A','\UF42B','\UF42C','\UF42D','\UF42E','\UF42F','\UF430','\UF431','\UF432','\UF433','\UF434','\UF435','\UF436','\UF437','\UF438','\UF439','\UF43A','\UF43B','\UF43C','\UF43D','\UF43E','\UF43F','\UF440','\UF441','\UF442','\UF443','\UF444','\UF445','\UF446','\UF447','\UF448','\UF449','\UF44A','\UF44B','\UF44C','\UF44D','\UF44E','\UF44F','\UF450','\UF451','\UF452','\UF453','\UF454','\UF455','\UF456','\UF457','\UF458','\UF459','\UF45A','\UF45B','\UF45C','\UF45D','\UF45E','\UF45F','\UF460','\UF461','\UF462','\UF463','\UF464','\UF465','\UF466','\UF467','\UF468','\UF469','\UF46A','\UF46B','\UF46C','\UF46D','\UF46E','\UF46F','\UF470','\UF471','\UF472','\UF473','\UF474','\UF475','\UF476','\UF477','\UF478','\UF479','\UF47A','\UF47B','\UF47C','\UF47D','\UF47E','\UF47F','\UF480','\UF481','\UF482','\UF483','\UF484','\UF485','\UF486','\UF487','\UF488','\UF489','\UF48A','\UF48B','\UF48C','\UF48D','\UF48E','\UF48F','\UF490','\UF491','\UF492','\UF493','\UF494','\UF495','\UF496','\UF497','\UF498','\UF499','\UF49A','\UF49B','\UF49C','\UF49D','\UF49E','\UF49F','\UF4A0','\UF4A1','\UF4A2','\UF4A3','\UF4A4','\UF4A5','\UF4A6','\UF4A7','\UF4A8','\UF4A9','\UF4AA','\UF4AB','\UF4AC','\UF4AD','\UF4AE','\UF4AF','\UF4B0','\UF4B1','\UF4B2','\UF4B3','\UF4B4','\UF4B5','\UF4B6','\UF4B7','\UF4B8','\UF4B9','\UF4BA','\UF4BB','\UF4BC','\UF4BD','\UF4BE','\UF4BF','\UF4C0','\UF4C1','\UF4C2','\UF4C3','\UF4C4','\UF4C5','\UF4C6','\UF4C7','\UF4C8','\UF4C9','\UF4CA','\UF4CB','\UF4CC','\UF4CD','\UF4CE','\UF4CF','\UF4D0','\UF4D1','\UF4D2','\UF4D3','\UF4D4','\UF4D5','\UF4D6','\UF4D7','\UF4D8','\UF4D9','\UF4DA','\UF4DB','\UF4DC','\UF4DD','\UF4DE','\UF4DF','\UF4E0','\UF4E1','\UF4E2','\UF4E3','\UF4E4','\UF4E5','\UF4E6','\UF4E7','\UF4E8','\UF4E9','\UF4EA','\UF4EB','\UF4EC','\UF4ED','\UF4EE','\UF4EF','\UF4F0','\UF4F1','\UF4F2','\UF4F3','\UF4F4','\UF4F5','\UF4F6','\UF4F7','\UF4F8','\UF4F9','\UF4FA','\UF4FB','\UF4FC','\UF4FD','\UF4FE','\UF4FF','\UF500','\UF501','\UF502','\UF503','\UF504','\UF505','\UF506','\UF507','\UF508','\UF509','\UF50A','\UF50B','\UF50C','\UF50D','\UF50E','\UF50F','\UF510','\UF511','\UF512','\UF513','\UF514','\UF515','\UF516','\UF517','\UF518','\UF519','\UF51A','\UF51B','\UF51C','\UF51D','\UF51E','\UF51F','\UF520','\UF521','\UF522','\UF523','\UF524','\UF525','\UF526','\UF527','\UF528','\UF529','\UF52A','\UF52B','\UF52C','\UF52D','\UF52E','\UF52F','\UF530','\UF531','\UF532','\UF533','\UF534','\UF535','\UF536','\UF537','\UF538','\UF539','\UF53A','\UF53B','\UF53C','\UF53D','\UF53E','\UF53F','\UF540','\UF541','\UF542','\UF543','\UF544','\UF545','\UF546','\UF547','\UF548','\UF549','\UF54A','\UF54B','\UF54C','\UF54D','\UF54E','\UF54F','\UF550','\UF551','\UF552','\UF553','\UF554','\UF555','\UF556','\UF557','\UF558','\UF559','\UF55A','\UF55B','\UF55C','\UF55D','\UF55E','\UF55F','\UF560','\UF561','\UF562','\UF563','\UF564','\UF565','\UF566','\UF567','\UF568','\UF569','\UF56A','\UF56B','\UF56C','\UF56D','\UF56E','\UF56F','\UF570','\UF571','\UF572','\UF573','\UF574','\UF575','\UF576','\UF577','\UF578','\UF579','\UF57A','\UF57B','\UF57C','\UF57D','\UF57E','\UF57F','\UF580','\UF581','\UF582','\UF583','\UF584','\UF585','\UF586','\UF587','\UF588','\UF589','\UF58A','\UF58B','\UF58C','\UF58D','\UF58E','\UF58F','\UF590','\UF591','\UF592','\UF593','\UF594','\UF595','\UF596','\UF597','\UF598','\UF599','\UF59A','\UF59B','\UF59C','\UF59D','\UF59E','\UF59F','\UF5A0','\UF5A1','\UF5A2','\UF5A3','\UF5A4','\UF5A5','\UF5A6','\UF5A7','\UF5A8','\UF5A9','\UF5AA','\UF5AB','\UF5AC','\UF5AD','\UF5AE','\UF5AF','\UF5B0','\UF5B1','\UF5B2','\UF5B3','\UF5B4','\UF5B5','\UF5B6','\UF5B7','\UF5B8','\UF5B9','\UF5BA','\UF5BB','\UF5BC','\UF5BD','\UF5BE','\UF5BF','\UF5C0','\UF5C1','\UF5C2','\UF5C3','\UF5C4','\UF5C5','\UF5C6','\UF5C7','\UF5C8','\UF5C9','\UF5CA','\UF5CB','\UF5CC','\UF5CD','\UF5CE','\UF5CF','\UF5D0','\UF5D1','\UF5D2','\UF5D3','\UF5D4','\UF5D5','\UF5D6','\UF5D7','\UF5D8','\UF5D9','\UF5DA','\UF5DB','\UF5DC','\UF5DD','\UF5DE','\UF5DF','\UF5E0','\UF5E1','\UF5E2','\UF5E3','\UF5E4','\UF5E5','\UF5E6','\UF5E7','\UF5E8','\UF5E9','\UF5EA','\UF5EB','\UF5EC','\UF5ED','\UF5EE','\UF5EF','\UF5F0','\UF5F1','\UF5F2','\UF5F3','\UF5F4','\UF5F5','\UF5F6','\UF5F7','\UF5F8','\UF5F9','\UF5FA','\UF5FB','\UF5FC','\UF5FD','\UF5FE','\UF5FF','\UF600','\UF601','\UF602','\UF603','\UF604','\UF605','\UF606','\UF607','\UF608','\UF609','\UF60A','\UF60B','\UF60C','\UF60D','\UF60E','\UF60F','\UF610','\UF611','\UF612','\UF613','\UF614','\UF615','\UF616','\UF617','\UF618','\UF619','\UF61A','\UF61B','\UF61C','\UF61D','\UF61E','\UF61F','\UF620','\UF621','\UF622','\UF623','\UF624','\UF625','\UF626','\UF627','\UF628','\UF629','\UF62A','\UF62B','\UF62C','\UF62D','\UF62E','\UF62F','\UF630','\UF631','\UF632','\UF633','\UF634','\UF635','\UF636','\UF637','\UF638','\UF639','\UF63A','\UF63B','\UF63C','\UF63D','\UF63E','\UF63F','\UF640','\UF641','\UF642','\UF643','\UF644','\UF645','\UF646','\UF647','\UF648','\UF649','\UF64A','\UF64B','\UF64C','\UF64D','\UF64E','\UF64F','\UF650','\UF651','\UF652','\UF653','\UF654','\UF655','\UF656','\UF657','\UF658','\UF659','\UF65A','\UF65B','\UF65C','\UF65D','\UF65E','\UF65F','\UF660','\UF661','\UF662','\UF663','\UF664','\UF665','\UF666','\UF667','\UF668','\UF669','\UF66A','\UF66B','\UF66C','\UF66D','\UF66E','\UF66F','\UF670','\UF671','\UF672','\UF673','\UF674','\UF675','\UF676','\UF677','\UF678','\UF679','\UF67A','\UF67B','\UF67C','\UF67D','\UF67E','\UF67F','\UF680','\UF681','\UF682','\UF683','\UF684','\UF685','\UF686','\UF687','\UF688','\UF689','\UF68A','\UF68B','\UF68C','\UF68D','\UF68E','\UF68F','\UF690','\UF691','\UF692','\UF693','\UF694','\UF695','\UF696','\UF697','\UF698','\UF699','\UF69A','\UF69B','\UF69C','\UF69D','\UF69E','\UF69F','\UF6A0','\UF6A1','\UF6A2','\UF6A3','\UF6A4','\UF6A5','\UF6A6','\UF6A7','\UF6A8','\UF6A9','\UF6AA','\UF6AB','\UF6AC','\UF6AD','\UF6AE','\UF6AF','\UF6B0','\UF6B1','\UF6B2','\UF6B3','\UF6B4','\UF6B5','\UF6B6','\UF6B7','\UF6B8','\UF6B9','\UF6BA','\UF6BB','\UF6BC','\UF6BD','\UF6BE','\UF6BF','\UF6C0','\UF6C1','\UF6C2','\UF6C3','\UF6C4','\UF6C5','\UF6C6','\UF6C7','\UF6C8','\UF6C9','\UF6CA','\UF6CB','\UF6CC','\UF6CD','\UF6CE','\UF6CF','\UF6D0','\UF6D1','\UF6D2','\UF6D3','\UF6D4','\UF6D5','\UF6D6','\UF6D7','\UF6D8','\UF6D9','\UF6DA','\UF6DB','\UF6DC','\UF6DD','\UF6DE','\UF6DF','\UF6E0','\UF6E1','\UF6E2','\UF6E3','\UF6E4','\UF6E5','\UF6E6','\UF6E7','\UF6E8','\UF6E9','\UF6EA','\UF6EB','\UF6EC','\UF6ED','\UF6EE','\UF6EF','\UF6F0','\UF6F1','\UF6F2','\UF6F3','\UF6F4','\UF6F5','\UF6F6','\UF6F7','\UF6F8','\UF6F9','\UF6FA','\UF6FB','\UF6FC','\UF6FD','\UF6FE','\UF6FF','\UF700','\UF701','\UF702','\UF703','\UF704','\UF705','\UF706','\UF707','\UF708','\UF709','\UF70A','\UF70B','\UF70C','\UF70D','\UF70E','\UF70F','\UF710','\UF711','\UF712','\UF713','\UF714','\UF715','\UF716','\UF717','\UF718','\UF719','\UF71A','\UF71B','\UF71C','\UF71D','\UF71E','\UF71F','\UF720','\UF721','\UF722','\UF723','\UF724','\UF725','\UF726','\UF727','\UF728','\UF729','\UF72A','\UF72B','\UF72C','\UF72D','\UF72E','\UF72F','\UF730','\UF731','\UF732','\UF733','\UF734','\UF735','\UF736','\UF737','\UF738','\UF739','\UF73A','\UF73B','\UF73C','\UF73D','\UF73E','\UF73F','\UF740','\UF741','\UF742','\UF743','\UF744','\UF745','\UF746','\UF747','\UF748','\UF749','\UF74A','\UF74B','\UF74C','\UF74D','\UF74E','\UF74F','\UF750','\UF751','\UF752','\UF753','\UF754','\UF755','\UF756','\UF757','\UF758','\UF759','\UF75A','\UF75B','\UF75C','\UF75D','\UF75E','\UF75F','\UF760','\UF761','\UF762','\UF763','\UF764','\UF765','\UF766','\UF767','\UF768','\UF769','\UF76A','\UF76B','\UF76C','\UF76D','\UF76E','\UF76F','\UF770','\UF771','\UF772','\UF773','\UF774','\UF775','\UF776','\UF777','\UF778','\UF779','\UF77A','\UF77B','\UF77C','\UF77D','\UF77E','\UF77F','\UF780','\UF781','\UF782','\UF783','\UF784','\UF785','\UF786','\UF787','\UF788','\UF789','\UF78A','\UF78B','\UF78C','\UF78D','\UF78E','\UF78F','\UF790','\UF791','\UF792','\UF793','\UF794','\UF795','\UF796','\UF797','\UF798','\UF799','\UF79A','\UF79B','\UF79C','\UF79D','\UF79E','\UF79F','\UF7A0','\UF7A1','\UF7A2','\UF7A3','\UF7A4','\UF7A5','\UF7A6','\UF7A7','\UF7A8','\UF7A9','\UF7AA','\UF7AB','\UF7AC','\UF7AD','\UF7AE','\UF7AF','\UF7B0','\UF7B1','\UF7B2','\UF7B3','\UF7B4','\UF7B5','\UF7B6','\UF7B7','\UF7B8','\UF7B9','\UF7BA','\UF7BB','\UF7BC','\UF7BD','\UF7BE','\UF7BF','\UF7C0','\UF7C1','\UF7C2','\UF7C3','\UF7C4','\UF7C5','\UF7C6','\UF7C7','\UF7C8','\UF7C9','\UF7CA','\UF7CB','\UF7CC','\UF7CD','\UF7CE','\UF7CF','\UF7D0','\UF7D1','\UF7D2','\UF7D3','\UF7D4','\UF7D5','\UF7D6','\UF7D7','\UF7D8','\UF7D9','\UF7DA','\UF7DB','\UF7DC','\UF7DD','\UF7DE','\UF7DF','\UF7E0','\UF7E1','\UF7E2','\UF7E3','\UF7E4','\UF7E5','\UF7E6','\UF7E7','\UF7E8','\UF7E9','\UF7EA','\UF7EB','\UF7EC','\UF7ED','\UF7EE','\UF7EF','\UF7F0','\UF7F1','\UF7F2','\UF7F3','\UF7F4','\UF7F5','\UF7F6','\UF7F7','\UF7F8','\UF7F9','\UF7FA','\UF7FB','\UF7FC','\UF7FD','\UF7FE','\UF7FF','\UF800','\UF801','\UF802','\UF803','\UF804','\UF805','\UF806','\UF807','\UF808','\UF809','\UF80A','\UF80B','\UF80C','\UF80D','\UF80E','\UF80F','\UF810','\UF811','\UF812','\UF813','\UF814','\UF815','\UF816','\UF817','\UF818','\UF819','\UF81A','\UF81B','\UF81C','\UF81D','\UF81E','\UF81F','\UF820','\UF821','\UF822','\UF823','\UF824','\UF825','\UF826','\UF827','\UF828','\UF829','\UF82A','\UF82B','\UF82C','\UF82D','\UF82E','\UF82F','\UF830','\UF831','\UF832','\UF833','\UF834','\UF835','\UF836','\UF837','\UF838','\UF839','\UF83A','\UF83B','\UF83C','\UF83D','\UF83E','\UF83F','\UF840','\UF841','\UF842','\UF843','\UF844','\UF845','\UF846','\UF847','\UF848','\UF849','\UF84A','\UF84B','\UF84C','\UF84D','\UF84E','\UF84F','\UF850','\UF851','\UF852','\UF853','\UF854','\UF855','\UF856','\UF857','\UF858','\UF859','\UF85A','\UF85B','\UF85C','\UF85D','\UF85E','\UF85F','\UF860','\UF861','\UF862','\UF863','\UF864','\UF865','\UF866','\UF867','\UF868','\UF869','\UF86A','\UF86B','\UF86C','\UF86D','\UF86E','\UF86F','\UF870','\UF871','\UF872','\UF873','\UF874','\UF875','\UF876','\UF877','\UF878','\UF879','\UF87A','\UF87B','\UF87C','\UF87D','\UF87E','\UF87F','\UF880','\UF881','\UF882','\UF883','\UF884','\UF885','\UF886','\UF887','\UF888','\UF889','\UF88A','\UF88B','\UF88C','\UF88D','\UF88E','\UF88F','\UF890','\UF891','\UF892','\UF893','\UF894','\UF895','\UF896','\UF897','\UF898','\UF899','\UF89A','\UF89B','\UF89C','\UF89D','\UF89E','\UF89F','\UF8A0','\UF8A1','\UF8A2','\UF8A3','\UF8A4','\UF8A5','\UF8A6','\UF8A7','\UF8A8','\UF8A9','\UF8AA','\UF8AB','\UF8AC','\UF8AD','\UF8AE','\UF8AF','\UF8B0','\UF8B1','\UF8B2','\UF8B3','\UF8B4','\UF8B5','\UF8B6','\UF8B7','\UF8B8','\UF8B9','\UF8BA','\UF8BB','\UF8BC','\UF8BD','\UF8BE','\UF8BF','\UF8C0','\UF8C1','\UF8C2','\UF8C3','\UF8C4','\UF8C5','\UF8C6','\UF8C7','\UF8C8','\UF8C9','\UF8CA','\UF8CB','\UF8CC','\UF8CD','\UF8CE','\UF8CF','\UF8D0','\UF8D1','\UF8D2','\UF8D3','\UF8D4','\UF8D5','\UF8D6','\UF8D7','\UF8D8','\UF8D9','\UF8DA','\UF8DB','\UF8DC','\UF8DD','\UF8DE','\UF8DF','\UF8E0','\UF8E1','\UF8E2','\UF8E3','\UF8E4','\UF8E5','\UF8E6','\UF8E7','\UF8E8','\UF8E9','\UF8EA','\UF8EB','\UF8EC','\UF8ED','\UF8EE','\UF8EF','\UF8F0','\UF8F1','\UF8F2','\UF8F3','\UF8F4','\UF8F5','\UF8F6','\UF8F7','\UF8F8','\UF8F9','\UF8FA','\UF8FB','\UF8FC','\UF8FD','\UF8FE','\UF8FF','\UF900','\UF901','\UF902','\UF903','\UF904','\UF905','\UF906','\UF907','\UF908','\UF909','\UF90A','\UF90B','\UF90C','\UF90D','\UF90E','\UF90F','\UF910','\UF911','\UF912','\UF913','\UF914','\UF915','\UF916','\UF917','\UF918','\UF919','\UF91A','\UF91B','\UF91C','\UF91D','\UF91E','\UF91F','\UF920','\UF921','\UF922','\UF923','\UF924','\UF925','\UF926','\UF927','\UF928','\UF929','\UF92A','\UF92B','\UF92C','\UF92D','\UF92E','\UF92F','\UF930','\UF931','\UF932','\UF933','\UF934','\UF935','\UF936','\UF937','\UF938','\UF939','\UF93A','\UF93B','\UF93C','\UF93D','\UF93E','\UF93F','\UF940','\UF941','\UF942','\UF943','\UF944','\UF945','\UF946','\UF947','\UF948','\UF949','\UF94A','\UF94B','\UF94C','\UF94D','\UF94E','\UF94F','\UF950','\UF951','\UF952','\UF953','\UF954','\UF955','\UF956','\UF957','\UF958','\UF959','\UF95A','\UF95B','\UF95C','\UF95D','\UF95E','\UF95F','\UF960','\UF961','\UF962','\UF963','\UF964','\UF965','\UF966','\UF967','\UF968','\UF969','\UF96A','\UF96B','\UF96C','\UF96D','\UF96E','\UF96F','\UF970','\UF971','\UF972','\UF973','\UF974','\UF975','\UF976','\UF977','\UF978','\UF979','\UF97A','\UF97B','\UF97C','\UF97D','\UF97E','\UF97F','\UF980','\UF981','\UF982','\UF983','\UF984','\UF985','\UF986','\UF987','\UF988','\UF989','\UF98A','\UF98B','\UF98C','\UF98D','\UF98E','\UF98F','\UF990','\UF991','\UF992','\UF993','\UF994','\UF995','\UF996','\UF997','\UF998','\UF999','\UF99A','\UF99B','\UF99C','\UF99D','\UF99E','\UF99F','\UF9A0','\UF9A1','\UF9A2','\UF9A3','\UF9A4','\UF9A5','\UF9A6','\UF9A7','\UF9A8','\UF9A9','\UF9AA','\UF9AB','\UF9AC','\UF9AD','\UF9AE','\UF9AF','\UF9B0','\UF9B1','\UF9B2','\UF9B3','\UF9B4','\UF9B5','\UF9B6','\UF9B7','\UF9B8','\UF9B9','\UF9BA','\UF9BB','\UF9BC','\UF9BD','\UF9BE','\UF9BF','\UF9C0','\UF9C1','\UF9C2','\UF9C3','\UF9C4','\UF9C5','\UF9C6','\UF9C7','\UF9C8','\UF9C9','\UF9CA','\UF9CB','\UF9CC','\UF9CD','\UF9CE','\UF9CF','\UF9D0','\UF9D1','\UF9D2','\UF9D3','\UF9D4','\UF9D5','\UF9D6','\UF9D7','\UF9D8','\UF9D9','\UF9DA','\UF9DB','\UF9DC','\UF9DD','\UF9DE','\UF9DF','\UF9E0','\UF9E1','\UF9E2','\UF9E3','\UF9E4','\UF9E5','\UF9E6','\UF9E7','\UF9E8','\UF9E9','\UF9EA','\UF9EB','\UF9EC','\UF9ED','\UF9EE','\UF9EF','\UF9F0','\UF9F1','\UF9F2','\UF9F3','\UF9F4','\UF9F5','\UF9F6','\UF9F7','\UF9F8','\UF9F9','\UF9FA','\UF9FB','\UF9FC','\UF9FD','\UF9FE','\UF9FF','\UFA00','\UFA01','\UFA02','\UFA03','\UFA04','\UFA05','\UFA06','\UFA07','\UFA08','\UFA09','\UFA0A','\UFA0B','\UFA0C','\UFA0D','\UFA0E','\UFA0F','\UFA10','\UFA11','\UFA12','\UFA13','\UFA14','\UFA15','\UFA16','\UFA17','\UFA18','\UFA19','\UFA1A','\UFA1B','\UFA1C','\UFA1D','\UFA1E','\UFA1F','\UFA20','\UFA21','\UFA22','\UFA23','\UFA24','\UFA25','\UFA26','\UFA27','\UFA28','\UFA29','\UFA2A','\UFA2B','\UFA2C','\UFA2D','\UFA2E','\UFA2F','\UFA30','\UFA31','\UFA32','\UFA33','\UFA34','\UFA35','\UFA36','\UFA37','\UFA38','\UFA39','\UFA3A','\UFA3B','\UFA3C','\UFA3D','\UFA3E','\UFA3F','\UFA40','\UFA41','\UFA42','\UFA43','\UFA44','\UFA45','\UFA46','\UFA47','\UFA48','\UFA49','\UFA4A','\UFA4B','\UFA4C','\UFA4D','\UFA4E','\UFA4F','\UFA50','\UFA51','\UFA52','\UFA53','\UFA54','\UFA55','\UFA56','\UFA57','\UFA58','\UFA59','\UFA5A','\UFA5B','\UFA5C','\UFA5D','\UFA5E','\UFA5F','\UFA60','\UFA61','\UFA62','\UFA63','\UFA64','\UFA65','\UFA66','\UFA67','\UFA68','\UFA69','\UFA6A','\UFA6B','\UFA6C','\UFA6D','\UFA6E','\UFA6F','\UFA70','\UFA71','\UFA72','\UFA73','\UFA74','\UFA75','\UFA76','\UFA77','\UFA78','\UFA79','\UFA7A','\UFA7B','\UFA7C','\UFA7D','\UFA7E','\UFA7F','\UFA80','\UFA81','\UFA82','\UFA83','\UFA84','\UFA85','\UFA86','\UFA87','\UFA88','\UFA89','\UFA8A','\UFA8B','\UFA8C','\UFA8D','\UFA8E','\UFA8F','\UFA90','\UFA91','\UFA92','\UFA93','\UFA94','\UFA95','\UFA96','\UFA97','\UFA98','\UFA99','\UFA9A','\UFA9B','\UFA9C','\UFA9D','\UFA9E','\UFA9F','\UFAA0','\UFAA1','\UFAA2','\UFAA3','\UFAA4','\UFAA5','\UFAA6','\UFAA7','\UFAA8','\UFAA9','\UFAAA','\UFAAB','\UFAAC','\UFAAD','\UFAAE','\UFAAF','\UFAB0','\UFAB1','\UFAB2','\UFAB3','\UFAB4','\UFAB5','\UFAB6','\UFAB7','\UFAB8','\UFAB9','\UFABA','\UFABB','\UFABC','\UFABD','\UFABE','\UFABF','\UFAC0','\UFAC1','\UFAC2','\UFAC3','\UFAC4','\UFAC5','\UFAC6','\UFAC7','\UFAC8','\UFAC9','\UFACA','\UFACB','\UFACC','\UFACD','\UFACE','\UFACF','\UFAD0','\UFAD1','\UFAD2','\UFAD3','\UFAD4','\UFAD5','\UFAD6','\UFAD7','\UFAD8','\UFAD9','\UFADA','\UFADB','\UFADC','\UFADD','\UFADE','\UFADF','\UFAE0','\UFAE1','\UFAE2','\UFAE3','\UFAE4','\UFAE5','\UFAE6','\UFAE7','\UFAE8','\UFAE9','\UFAEA','\UFAEB','\UFAEC','\UFAED','\UFAEE','\UFAEF','\UFAF0','\UFAF1','\UFAF2','\UFAF3','\UFAF4','\UFAF5','\UFAF6','\UFAF7','\UFAF8','\UFAF9','\UFAFA','\UFAFB','\UFAFC','\UFAFD','\UFAFE','\UFAFF','\UFB00','\UFB01','\UFB02','\UFB03','\UFB04','\UFB05','\UFB06','\UFB07','\UFB08','\UFB09','\UFB0A','\UFB0B','\UFB0C','\UFB0D','\UFB0E','\UFB0F','\UFB10','\UFB11','\UFB12','\UFB13','\UFB14','\UFB15','\UFB16','\UFB17','\UFB18','\UFB19','\UFB1A','\UFB1B','\UFB1C','\UFB1D','\UFB1E','\UFB1F','\UFB20','\UFB21','\UFB22','\UFB23','\UFB24','\UFB25','\UFB26','\UFB27','\UFB28','\UFB29','\UFB2A','\UFB2B','\UFB2C','\UFB2D','\UFB2E','\UFB2F','\UFB30','\UFB31','\UFB32','\UFB33','\UFB34','\UFB35','\UFB36','\UFB37','\UFB38','\UFB39','\UFB3A','\UFB3B','\UFB3C','\UFB3D','\UFB3E','\UFB3F','\UFB40','\UFB41','\UFB42','\UFB43','\UFB44','\UFB45','\UFB46','\UFB47','\UFB48','\UFB49','\UFB4A','\UFB4B','\UFB4C','\UFB4D','\UFB4E','\UFB4F','\UFB50','\UFB51','\UFB52','\UFB53','\UFB54','\UFB55','\UFB56','\UFB57','\UFB58','\UFB59','\UFB5A','\UFB5B','\UFB5C','\UFB5D','\UFB5E','\UFB5F','\UFB60','\UFB61','\UFB62','\UFB63','\UFB64','\UFB65','\UFB66','\UFB67','\UFB68','\UFB69','\UFB6A','\UFB6B','\UFB6C','\UFB6D','\UFB6E','\UFB6F','\UFB70','\UFB71','\UFB72','\UFB73','\UFB74','\UFB75','\UFB76','\UFB77','\UFB78','\UFB79','\UFB7A','\UFB7B','\UFB7C','\UFB7D','\UFB7E','\UFB7F','\UFB80','\UFB81','\UFB82','\UFB83','\UFB84','\UFB85','\UFB86','\UFB87','\UFB88','\UFB89','\UFB8A','\UFB8B','\UFB8C','\UFB8D','\UFB8E','\UFB8F','\UFB90','\UFB91','\UFB92','\UFB93','\UFB94','\UFB95','\UFB96','\UFB97','\UFB98','\UFB99','\UFB9A','\UFB9B','\UFB9C','\UFB9D','\UFB9E','\UFB9F','\UFBA0','\UFBA1','\UFBA2','\UFBA3','\UFBA4','\UFBA5','\UFBA6','\UFBA7','\UFBA8','\UFBA9','\UFBAA','\UFBAB','\UFBAC','\UFBAD','\UFBAE','\UFBAF','\UFBB0','\UFBB1','\UFBB2','\UFBB3','\UFBB4','\UFBB5','\UFBB6','\UFBB7','\UFBB8','\UFBB9','\UFBBA','\UFBBB','\UFBBC','\UFBBD','\UFBBE','\UFBBF','\UFBC0','\UFBC1','\UFBC2','\UFBC3','\UFBC4','\UFBC5','\UFBC6','\UFBC7','\UFBC8','\UFBC9','\UFBCA','\UFBCB','\UFBCC','\UFBCD','\UFBCE','\UFBCF','\UFBD0','\UFBD1','\UFBD2','\UFBD3','\UFBD4','\UFBD5','\UFBD6','\UFBD7','\UFBD8','\UFBD9','\UFBDA','\UFBDB','\UFBDC','\UFBDD','\UFBDE','\UFBDF','\UFBE0','\UFBE1','\UFBE2','\UFBE3','\UFBE4','\UFBE5','\UFBE6','\UFBE7','\UFBE8','\UFBE9','\UFBEA','\UFBEB','\UFBEC','\UFBED','\UFBEE','\UFBEF','\UFBF0','\UFBF1','\UFBF2','\UFBF3','\UFBF4','\UFBF5','\UFBF6','\UFBF7','\UFBF8','\UFBF9','\UFBFA','\UFBFB','\UFBFC','\UFBFD','\UFBFE','\UFBFF','\UFC00','\UFC01','\UFC02','\UFC03','\UFC04','\UFC05','\UFC06','\UFC07','\UFC08','\UFC09','\UFC0A','\UFC0B','\UFC0C','\UFC0D','\UFC0E','\UFC0F','\UFC10','\UFC11','\UFC12','\UFC13','\UFC14','\UFC15','\UFC16','\UFC17','\UFC18','\UFC19','\UFC1A','\UFC1B','\UFC1C','\UFC1D','\UFC1E','\UFC1F','\UFC20','\UFC21','\UFC22','\UFC23','\UFC24','\UFC25','\UFC26','\UFC27','\UFC28','\UFC29','\UFC2A','\UFC2B','\UFC2C','\UFC2D','\UFC2E','\UFC2F','\UFC30','\UFC31','\UFC32','\UFC33','\UFC34','\UFC35','\UFC36','\UFC37','\UFC38','\UFC39','\UFC3A','\UFC3B','\UFC3C','\UFC3D','\UFC3E','\UFC3F','\UFC40','\UFC41','\UFC42','\UFC43','\UFC44','\UFC45','\UFC46','\UFC47','\UFC48','\UFC49','\UFC4A','\UFC4B','\UFC4C','\UFC4D','\UFC4E','\UFC4F','\UFC50','\UFC51','\UFC52','\UFC53','\UFC54','\UFC55','\UFC56','\UFC57','\UFC58','\UFC59','\UFC5A','\UFC5B','\UFC5C','\UFC5D','\UFC5E','\UFC5F','\UFC60','\UFC61','\UFC62','\UFC63','\UFC64','\UFC65','\UFC66','\UFC67','\UFC68','\UFC69','\UFC6A','\UFC6B','\UFC6C','\UFC6D','\UFC6E','\UFC6F','\UFC70','\UFC71','\UFC72','\UFC73','\UFC74','\UFC75','\UFC76','\UFC77','\UFC78','\UFC79','\UFC7A','\UFC7B','\UFC7C','\UFC7D','\UFC7E','\UFC7F','\UFC80','\UFC81','\UFC82','\UFC83','\UFC84','\UFC85','\UFC86','\UFC87','\UFC88','\UFC89','\UFC8A','\UFC8B','\UFC8C','\UFC8D','\UFC8E','\UFC8F','\UFC90','\UFC91','\UFC92','\UFC93','\UFC94','\UFC95','\UFC96','\UFC97','\UFC98','\UFC99','\UFC9A','\UFC9B','\UFC9C','\UFC9D','\UFC9E','\UFC9F','\UFCA0','\UFCA1','\UFCA2','\UFCA3','\UFCA4','\UFCA5','\UFCA6','\UFCA7','\UFCA8','\UFCA9','\UFCAA','\UFCAB','\UFCAC','\UFCAD','\UFCAE','\UFCAF','\UFCB0','\UFCB1','\UFCB2','\UFCB3','\UFCB4','\UFCB5','\UFCB6','\UFCB7','\UFCB8','\UFCB9','\UFCBA','\UFCBB','\UFCBC','\UFCBD','\UFCBE','\UFCBF','\UFCC0','\UFCC1','\UFCC2','\UFCC3','\UFCC4','\UFCC5','\UFCC6','\UFCC7','\UFCC8','\UFCC9','\UFCCA','\UFCCB','\UFCCC','\UFCCD','\UFCCE','\UFCCF','\UFCD0','\UFCD1','\UFCD2','\UFCD3','\UFCD4','\UFCD5','\UFCD6','\UFCD7','\UFCD8','\UFCD9','\UFCDA','\UFCDB','\UFCDC','\UFCDD','\UFCDE','\UFCDF','\UFCE0','\UFCE1','\UFCE2','\UFCE3','\UFCE4','\UFCE5','\UFCE6','\UFCE7','\UFCE8','\UFCE9','\UFCEA','\UFCEB','\UFCEC','\UFCED','\UFCEE','\UFCEF','\UFCF0','\UFCF1','\UFCF2','\UFCF3','\UFCF4','\UFCF5','\UFCF6','\UFCF7','\UFCF8','\UFCF9','\UFCFA','\UFCFB','\UFCFC','\UFCFD','\UFCFE','\UFCFF','\UFD00','\UFD01','\UFD02','\UFD03','\UFD04','\UFD05','\UFD06','\UFD07','\UFD08','\UFD09','\UFD0A','\UFD0B','\UFD0C','\UFD0D','\UFD0E','\UFD0F','\UFD10','\UFD11','\UFD12','\UFD13','\UFD14','\UFD15','\UFD16','\UFD17','\UFD18','\UFD19','\UFD1A','\UFD1B','\UFD1C','\UFD1D','\UFD1E','\UFD1F','\UFD20','\UFD21','\UFD22','\UFD23','\UFD24','\UFD25','\UFD26','\UFD27','\UFD28','\UFD29','\UFD2A','\UFD2B','\UFD2C','\UFD2D','\UFD2E','\UFD2F','\UFD30','\UFD31','\UFD32','\UFD33','\UFD34','\UFD35','\UFD36','\UFD37','\UFD38','\UFD39','\UFD3A','\UFD3B','\UFD3C','\UFD3D','\UFD3E','\UFD3F','\UFD40','\UFD41','\UFD42','\UFD43','\UFD44','\UFD45','\UFD46','\UFD47','\UFD48','\UFD49','\UFD4A','\UFD4B','\UFD4C','\UFD4D','\UFD4E','\UFD4F','\UFD50','\UFD51','\UFD52','\UFD53','\UFD54','\UFD55','\UFD56','\UFD57','\UFD58','\UFD59','\UFD5A','\UFD5B','\UFD5C','\UFD5D','\UFD5E','\UFD5F','\UFD60','\UFD61','\UFD62','\UFD63','\UFD64','\UFD65','\UFD66','\UFD67','\UFD68','\UFD69','\UFD6A','\UFD6B','\UFD6C','\UFD6D','\UFD6E','\UFD6F','\UFD70','\UFD71','\UFD72','\UFD73','\UFD74','\UFD75','\UFD76','\UFD77','\UFD78','\UFD79','\UFD7A','\UFD7B','\UFD7C','\UFD7D','\UFD7E','\UFD7F','\UFD80','\UFD81','\UFD82','\UFD83','\UFD84','\UFD85','\UFD86','\UFD87','\UFD88','\UFD89','\UFD8A','\UFD8B','\UFD8C','\UFD8D','\UFD8E','\UFD8F','\UFD90','\UFD91','\UFD92','\UFD93','\UFD94','\UFD95','\UFD96','\UFD97','\UFD98','\UFD99','\UFD9A','\UFD9B','\UFD9C','\UFD9D','\UFD9E','\UFD9F','\UFDA0','\UFDA1','\UFDA2','\UFDA3','\UFDA4','\UFDA5','\UFDA6','\UFDA7','\UFDA8','\UFDA9','\UFDAA','\UFDAB','\UFDAC','\UFDAD','\UFDAE','\UFDAF','\UFDB0','\UFDB1','\UFDB2','\UFDB3','\UFDB4','\UFDB5','\UFDB6','\UFDB7','\UFDB8','\UFDB9','\UFDBA','\UFDBB','\UFDBC','\UFDBD','\UFDBE','\UFDBF','\UFDC0','\UFDC1','\UFDC2','\UFDC3','\UFDC4','\UFDC5','\UFDC6','\UFDC7','\UFDC8','\UFDC9','\UFDCA','\UFDCB','\UFDCC','\UFDCD','\UFDCE','\UFDCF','\UFDD0','\UFDD1','\UFDD2','\UFDD3','\UFDD4','\UFDD5','\UFDD6','\UFDD7','\UFDD8','\UFDD9','\UFDDA','\UFDDB','\UFDDC','\UFDDD','\UFDDE','\UFDDF','\UFDE0','\UFDE1','\UFDE2','\UFDE3','\UFDE4','\UFDE5','\UFDE6','\UFDE7','\UFDE8','\UFDE9','\UFDEA','\UFDEB','\UFDEC','\UFDED','\UFDEE','\UFDEF','\UFDF0','\UFDF1','\UFDF2','\UFDF3','\UFDF4','\UFDF5','\UFDF6','\UFDF7','\UFDF8','\UFDF9','\UFDFA','\UFDFB','\UFDFC','\UFDFD','\UFDFE','\UFDFF','\UFE00','\UFE01','\UFE02','\UFE03','\UFE04','\UFE05','\UFE06','\UFE07','\UFE08','\UFE09','\UFE0A','\UFE0B','\UFE0C','\UFE0D','\UFE0E','\UFE0F','\UFE10','\UFE11','\UFE12','\UFE13','\UFE14','\UFE15','\UFE16','\UFE17','\UFE18','\UFE19','\UFE1A','\UFE1B','\UFE1C','\UFE1D','\UFE1E','\UFE1F','\UFE20','\UFE21','\UFE22','\UFE23','\UFE24','\UFE25','\UFE26','\UFE27','\UFE28','\UFE29','\UFE2A','\UFE2B','\UFE2C','\UFE2D','\UFE2E','\UFE2F','\UFE30','\UFE31','\UFE32','\UFE33','\UFE34','\UFE35','\UFE36','\UFE37','\UFE38','\UFE39','\UFE3A','\UFE3B','\UFE3C','\UFE3D','\UFE3E','\UFE3F','\UFE40','\UFE41','\UFE42','\UFE43','\UFE44','\UFE45','\UFE46','\UFE47','\UFE48','\UFE49','\UFE4A','\UFE4B','\UFE4C','\UFE4D','\UFE4E','\UFE4F','\UFE50','\UFE51','\UFE52','\UFE53','\UFE54','\UFE55','\UFE56','\UFE57','\UFE58','\UFE59','\UFE5A','\UFE5B','\UFE5C','\UFE5D','\UFE5E','\UFE5F','\UFE60','\UFE61','\UFE62','\UFE63','\UFE64','\UFE65','\UFE66','\UFE67','\UFE68','\UFE69','\UFE6A','\UFE6B','\UFE6C','\UFE6D','\UFE6E','\UFE6F','\UFE70','\UFE71','\UFE72','\UFE73','\UFE74','\UFE75','\UFE76','\UFE77','\UFE78','\UFE79','\UFE7A','\UFE7B','\UFE7C','\UFE7D','\UFE7E','\UFE7F','\UFE80','\UFE81','\UFE82','\UFE83','\UFE84','\UFE85','\UFE86','\UFE87','\UFE88','\UFE89','\UFE8A','\UFE8B','\UFE8C','\UFE8D','\UFE8E','\UFE8F','\UFE90','\UFE91','\UFE92','\UFE93','\UFE94','\UFE95','\UFE96','\UFE97','\UFE98','\UFE99','\UFE9A','\UFE9B','\UFE9C','\UFE9D','\UFE9E','\UFE9F','\UFEA0','\UFEA1','\UFEA2','\UFEA3','\UFEA4','\UFEA5','\UFEA6','\UFEA7','\UFEA8','\UFEA9','\UFEAA','\UFEAB','\UFEAC','\UFEAD','\UFEAE','\UFEAF','\UFEB0','\UFEB1','\UFEB2','\UFEB3','\UFEB4','\UFEB5','\UFEB6','\UFEB7','\UFEB8','\UFEB9','\UFEBA','\UFEBB','\UFEBC','\UFEBD','\UFEBE','\UFEBF','\UFEC0','\UFEC1','\UFEC2','\UFEC3','\UFEC4','\UFEC5','\UFEC6','\UFEC7','\UFEC8','\UFEC9','\UFECA','\UFECB','\UFECC','\UFECD','\UFECE','\UFECF','\UFED0','\UFED1','\UFED2','\UFED3','\UFED4','\UFED5','\UFED6','\UFED7','\UFED8','\UFED9','\UFEDA','\UFEDB','\UFEDC','\UFEDD','\UFEDE','\UFEDF','\UFEE0','\UFEE1','\UFEE2','\UFEE3','\UFEE4','\UFEE5','\UFEE6','\UFEE7','\UFEE8','\UFEE9','\UFEEA','\UFEEB','\UFEEC','\UFEED','\UFEEE','\UFEEF','\UFEF0','\UFEF1','\UFEF2','\UFEF3','\UFEF4','\UFEF5','\UFEF6','\UFEF7','\UFEF8','\UFEF9','\UFEFA','\UFEFB','\UFEFC','\UFEFD','\UFEFE','\UFF00','\UFF01','\UFF02','\UFF03','\UFF04','\UFF05','\UFF06','\UFF07','\UFF08','\UFF09','\UFF0A','\UFF0B','\UFF0C','\UFF0D','\UFF0E','\UFF0F','\UFF10','\UFF11','\UFF12','\UFF13','\UFF14','\UFF15','\UFF16','\UFF17','\UFF18','\UFF19','\UFF1A','\UFF1B','\UFF1C','\UFF1D','\UFF1E','\UFF1F','\UFF20','\UFF21','\UFF22','\UFF23','\UFF24','\UFF25','\UFF26','\UFF27','\UFF28','\UFF29','\UFF2A','\UFF2B','\UFF2C','\UFF2D','\UFF2E','\UFF2F','\UFF30','\UFF31','\UFF32','\UFF33','\UFF34','\UFF35','\UFF36','\UFF37','\UFF38','\UFF39','\UFF3A','\UFF3B','\UFF3C','\UFF3D','\UFF3E','\UFF3F','\UFF40','\UFF41','\UFF42','\UFF43','\UFF44','\UFF45','\UFF46','\UFF47','\UFF48','\UFF49','\UFF4A','\UFF4B','\UFF4C','\UFF4D','\UFF4E','\UFF4F','\UFF50','\UFF51','\UFF52','\UFF53','\UFF54','\UFF55','\UFF56','\UFF57','\UFF58','\UFF59','\UFF5A','\UFF5B','\UFF5C','\UFF5D','\UFF5E','\UFF5F','\UFF60','\UFF61','\UFF62','\UFF63','\UFF64','\UFF65','\UFF66','\UFF67','\UFF68','\UFF69','\UFF6A','\UFF6B','\UFF6C','\UFF6D','\UFF6E','\UFF6F','\UFF70','\UFF71','\UFF72','\UFF73','\UFF74','\UFF75','\UFF76','\UFF77','\UFF78','\UFF79','\UFF7A','\UFF7B','\UFF7C','\UFF7D','\UFF7E','\UFF7F','\UFF80','\UFF81','\UFF82','\UFF83','\UFF84','\UFF85','\UFF86','\UFF87','\UFF88','\UFF89','\UFF8A','\UFF8B','\UFF8C','\UFF8D','\UFF8E','\UFF8F','\UFF90','\UFF91','\UFF92','\UFF93','\UFF94','\UFF95','\UFF96','\UFF97','\UFF98','\UFF99','\UFF9A','\UFF9B','\UFF9C','\UFF9D','\UFF9E','\UFF9F','\UFFA0','\UFFA1','\UFFA2','\UFFA3','\UFFA4','\UFFA5','\UFFA6','\UFFA7','\UFFA8','\UFFA9','\UFFAA','\UFFAB','\UFFAC','\UFFAD','\UFFAE','\UFFAF','\UFFB0','\UFFB1','\UFFB2','\UFFB3','\UFFB4','\UFFB5','\UFFB6','\UFFB7','\UFFB8','\UFFB9','\UFFBA','\UFFBB','\UFFBC','\UFFBD','\UFFBE','\UFFBF','\UFFC0','\UFFC1','\UFFC2','\UFFC3','\UFFC4','\UFFC5','\UFFC6','\UFFC7','\UFFC8','\UFFC9','\UFFCA','\UFFCB','\UFFCC','\UFFCD','\UFFCE','\UFFCF','\UFFD0','\UFFD1','\UFFD2','\UFFD3','\UFFD4','\UFFD5','\UFFD6','\UFFD7','\UFFD8','\UFFD9','\UFFDA','\UFFDB','\UFFDC','\UFFDD','\UFFDE','\UFFDF','\UFFE0','\UFFE1','\UFFE2','\UFFE3','\UFFE4','\UFFE5','\UFFE6','\UFFE7','\UFFE8','\UFFE9','\UFFEA','\UFFEB','\UFFEC','\UFFED','\UFFEE','\UFFEF','\UFFF0','\UFFF1','\UFFF2','\UFFF3','\UFFF4','\UFFF5','\UFFF6','\UFFF7','\UFFF8','\UFFF9','\UFFFA','\UFFFB','\UFFFC','\UFFFD','\UFFFE','\UFFFF') diff --git a/Tests/FoundationEssentialsTests/Resources/test_oldStylePlist_getSlashedChars_unicode_expected.plist b/Tests/FoundationEssentialsTests/Resources/test_oldStylePlist_getSlashedChars_unicode_expected.plist deleted file mode 100644 index bee363d8d..000000000 Binary files a/Tests/FoundationEssentialsTests/Resources/test_oldStylePlist_getSlashedChars_unicode_expected.plist and /dev/null differ diff --git a/Tests/FoundationEssentialsTests/SortComparatorTests.swift b/Tests/FoundationEssentialsTests/SortComparatorTests.swift deleted file mode 100644 index 36f2206bb..000000000 --- a/Tests/FoundationEssentialsTests/SortComparatorTests.swift +++ /dev/null @@ -1,65 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#else -@testable import FoundationEssentials -#endif // FOUNDATION_FRAMEWORK - -class SortComparatorTests: XCTestCase { - func test_comparable_descriptors() { - let intDesc: ComparableComparator = ComparableComparator() - XCTAssertEqual(intDesc.compare(0, 1), .orderedAscending) - let result = intDesc.compare(1000, -10) - XCTAssertEqual(result, .orderedDescending) - } - - - func test_order() { - var intDesc: ComparableComparator = ComparableComparator(order: .reverse) - XCTAssertEqual(intDesc.compare(0, 1), .orderedDescending) - XCTAssertEqual(intDesc.compare(1000, -10), .orderedAscending) - XCTAssertEqual(intDesc.compare(100, 100), .orderedSame) - - intDesc.order = .forward - XCTAssertEqual(intDesc.compare(0, 1), .orderedAscending) - XCTAssertEqual(intDesc.compare(1000, -10), .orderedDescending) - XCTAssertEqual(intDesc.compare(100, 100), .orderedSame) - } - - func test_compare_options_descriptor() { - let compareOptions = String.Comparator(options: [.numeric]) - XCTAssertEqual( - compareOptions.compare("ttestest005", "test2"), - "test005".compare("test2", options: [.numeric])) - XCTAssertEqual( - compareOptions.compare("test2", "test005"), - "test2".compare("test005", options: [.numeric])) - } - - func testAnySortComparatorEquality() { - let a: ComparableComparator = ComparableComparator() - let b: ComparableComparator = ComparableComparator(order: .reverse) - let c: ComparableComparator = ComparableComparator() - XCTAssertEqual(AnySortComparator(a), AnySortComparator(a)) - XCTAssertEqual(AnySortComparator(b), AnySortComparator(b)) - XCTAssertEqual(AnySortComparator(c), AnySortComparator(c)) - XCTAssertNotEqual(AnySortComparator(a), AnySortComparator(b)) - XCTAssertNotEqual(AnySortComparator(b), AnySortComparator(c)) - XCTAssertNotEqual(AnySortComparator(a), AnySortComparator(c)) - } -} diff --git a/Tests/FoundationEssentialsTests/StringTests.swift b/Tests/FoundationEssentialsTests/StringTests.swift deleted file mode 100644 index 7b7cb041b..000000000 --- a/Tests/FoundationEssentialsTests/StringTests.swift +++ /dev/null @@ -1,3135 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#else -@testable import FoundationEssentials -#endif // FOUNDATION_FRAMEWORK - -#if canImport(TestSupport) -import TestSupport -#endif - -final class StringTests : XCTestCase { - // MARK: - Case mapping - - func testCapitalize() { - func test(_ string: String, _ expected: String, file: StaticString = #filePath, line: UInt = #line) { - XCTAssertEqual(string._capitalized(), expected, file: file, line: line) - } - - test("iı", "Iı") - test("ıi", "Ii") - - // Word boundaries - test("Th.he.EVERYWHERE", - "Th.He.Everywhere") - test("HELLO world\t\t\tThere.here.EVERYWHERE 78dollars", - "Hello World\t\t\tThere.Here.Everywhere 78Dollars") - test("GOOd Evening WOrld!", "Good Evening World!") - - // We don't do title case, so minor words are also capitalized - test("train your mind for peak performance: a science-based approach for achieving your goals!", "Train Your Mind For Peak Performance: A Science-Based Approach For Achieving Your Goals!") - test("cAt! Ê»eTc.", "Cat! Ê»Etc.") - test("a Ê»CaT. A Ê»dOg! Ê»eTc.", "A Ê»Cat. A Ê»Dog! Ê»Etc.") - test("49ERS", "49Ers") - test("«丰(aBc)»", "«丰(Abc)»") - test("Nat’s test can’t run", "Nat’s Test Can’t Run") - - test("ijssEl iglOo IJSSEL", "Ijssel Igloo Ijssel") - test("\u{00DF}", "Ss") // Sharp S - test("\u{FB00}", "Ff") // Ligature FF - test("\u{1F80}", "\u{1F88}") - - // Width variants - test("hellï½ï¼Œï½—ï½ï¼²ï¼¬ï¼¤\there.THERE?eVerYWHERE", - "Hellï½ï¼Œï¼·ï½ï½’ld\tHere.There?Everywhere") - - // Diacritics - test("ĤĒḺḶŠẀỌṜÅÃ", "Ĥēḻḷő Ẁá»á¹Å‚ð") - - // Hiragana, Katacana -- case not affected - test("ァィゥㇳ゚ェォ ヶ゜ アイウエオ", "ァィゥㇳ゚ェォ ヶ゜ アイウエオ") - test("ããƒã…ã‡ã‰ ã© ã‚•ã‚–ãã‘ã“", "ããƒã…ã‡ã‰ ã© ã‚•ã‚–ãã‘ã“") - } - - func testTrimmingWhitespace() { - func test(_ str: String, _ expected: String, file: StaticString = #filePath, line: UInt = #line) { - XCTAssertEqual(str._trimmingWhitespace(), expected, file: file, line: line) - } - test(" \tABCDEFGAbc \t \t ", "ABCDEFGAbc") - test("ABCDEFGAbc \t \t ", "ABCDEFGAbc") - test(" \tABCDEFGAbc", "ABCDEFGAbc") - test(" \t\t\t \t\t \t", "") - test(" X", "X") - test("X ", "X") - test("X", "X") - test("", "") - test("X\u{00A0}", "X") // NBSP - test(" \u{202F}\u{00A0} X \u{202F}\u{00A0}", "X") // NBSP and narrow NBSP - } - - func testTrimmingCharactersWithPredicate() { - func test(_ str: String, while predicate: (Character) -> Bool, _ expected: Substring, file: StaticString = #filePath, line: UInt = #line) { - XCTAssertEqual(str._trimmingCharacters(while: predicate), expected, file: file, line: line) - } - - typealias TrimmingPredicate = (Character) -> Bool - - let isNewline: TrimmingPredicate = { $0.isNewline } - - test("\u{2028}ABCDEFGAbc \u{2028}", while: isNewline, "ABCDEFGAbc ") - test("\nABCDEFGAbc \n\n", while: isNewline, "ABCDEFGAbc ") - test("\n\u{2028}ABCDEFGAbc \n\u{2028}\n", while: isNewline, "ABCDEFGAbc ") - test("\u{2029}ABCDEFGAbc \u{2029}", while: isNewline, "ABCDEFGAbc ") - test("\nABCDEFGAbc \n\u{2029}\n", while: isNewline, "ABCDEFGAbc ") - test(" \n \n\n\t \n\t\n", while: { $0.isNewline || $0.isWhitespace }, "") - - let isNumber: TrimmingPredicate = { $0.isNumber } - - test("1B", while: isNumber, "B") - test("11 B22", while: isNumber, " B") - test("11 B\u{0662}\u{0661}", while: isNumber, " B") // ARABIC-INDIC DIGIT TWO and ONE - test(" B 22", while: isNumber, " B ") - test(" B \u{0662}\u{0661}", while: isNumber, " B ") - - test("11 B\u{0662}\u{0661}", while: { $0.isNumber || $0.isASCII }, "") // ARABIC-INDIC DIGIT TWO and ONE - test("\u{ffff}a\u{ffff}", while: { !$0.isNumber && !$0.isASCII }, "a") - - let isLowercase: TrimmingPredicate = { $0.isLowercase } - let isLetter: TrimmingPredicate = { $0.isLetter } - let isUppercase: TrimmingPredicate = { $0.isUppercase } - - test("ABðŸ³ï¸â€ðŸŒˆxyz👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ab", while: isLetter, "ðŸ³ï¸â€ðŸŒˆxyz👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦") - test("ABðŸ³ï¸â€ðŸŒˆxyz👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ab", while: isUppercase, "ðŸ³ï¸â€ðŸŒˆxyz👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ab") - test("ABðŸ³ï¸â€ðŸŒˆxyz👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ab", while: isLowercase, "ABðŸ³ï¸â€ðŸŒˆxyz👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦") - - test("cafe\u{0301}abcABC123", while: { $0.isLetter || $0.isNumber }, "") - test("cafe\u{0301}abcABC123", while: isLetter, "123") - test("cafe\u{0301}abcABC123", while: isLowercase, "ABC123") - - test("\u{0301}abc123xyz\u{0301}", while: isLetter, "\u{0301}abc123") // \u{0301} isn't a letter on its own, but it is when normalized and combined with the previous character - test("\u{0301}abc123xyz\u{0301}", while: isLowercase, "\u{0301}abc123") - - test("+a+b+c+1+2+3++", while: { $0.isSymbol }, "a+b+c+1+2+3") - test("+a+b+c+1+2+3!!", while: { $0.isPunctuation }, "+a+b+c+1+2+3") - - let alwaysReject: TrimmingPredicate = { _ in return false } - - test("", while: alwaysReject, "") - test("ðŸ³ï¸â€ðŸŒˆxyz👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦", while: alwaysReject, "ðŸ³ï¸â€ðŸŒˆxyz👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦") - test("11 B\u{0662}\u{0661}", while: alwaysReject, "11 B\u{0662}\u{0661}") - - let alwaysTrim: TrimmingPredicate = { _ in return true } - - test("ðŸ³ï¸â€ðŸŒˆxyz👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦", while: alwaysTrim, "") - test("11 B\u{0662}\u{0661}", while: alwaysTrim, "") - } - - func _testRangeOfString(_ tested: String, string: String, anchored: Bool, backwards: Bool, _ expectation: Range?, file: StaticString = #filePath, line: UInt = #line) { - let result = tested._range(of: string, anchored: anchored, backwards: backwards) - var exp: Range? - if let expectation { - exp = tested.index(tested.startIndex, offsetBy: expectation.lowerBound) ..< tested.index(tested.startIndex, offsetBy: expectation.upperBound) - } else { - exp = nil - } - - var message: String - if let result { - let readableRange = tested.distance(from: tested.startIndex, to: result.lowerBound)..?, file: StaticString = #filePath, line: UInt = #line) { - return _testRangeOfString(tested, string: string, anchored: anchored, backwards: backwards, expectation, file: file, line: line) - } - - tested = "ABCDEFGAbcABCDE" - testASCII("", anchored: false, backwards: false, 0..<0) - testASCII("A", anchored: false, backwards: false, 0..<1) - testASCII("B", anchored: false, backwards: false, 1..<2) - testASCII("b", anchored: false, backwards: false, 8..<9) - testASCII("FG", anchored: false, backwards: false, 5..<7) - testASCII("FGH", anchored: false, backwards: false, nil) - testASCII("cde", anchored: false, backwards: false, nil) - testASCII("CDE", anchored: false, backwards: false, 2..<5) - - testASCII("", anchored: true, backwards: false, 0..<0) - testASCII("AB", anchored: true, backwards: false, 0..<2) - testASCII("ab", anchored: true, backwards: false, nil) - testASCII("BC", anchored: true, backwards: false, nil) - testASCII("bc", anchored: true, backwards: false, nil) - - testASCII("", anchored: false, backwards: true, 15..<15) - testASCII("A", anchored: false, backwards: true, 10..<11) - testASCII("B", anchored: false, backwards: true, 11..<12) - testASCII("b", anchored: false, backwards: true, 8..<9) - testASCII("FG", anchored: false, backwards: true, 5..<7) - testASCII("FGH", anchored: false, backwards: true, nil) - testASCII("cde", anchored: false, backwards: true, nil) - testASCII("CDE", anchored: false, backwards: true, 12..<15) - - testASCII("", anchored: true, backwards: true, 15..<15) - testASCII("AB", anchored: true, backwards: true, nil) - testASCII("ab", anchored: true, backwards: true, nil) - testASCII("BC", anchored: true, backwards: true, nil) - testASCII("bc", anchored: true, backwards: true, nil) - testASCII("bcd", anchored: true, backwards: true, nil) - testASCII("B", anchored: true, backwards: true, nil) - testASCII("b", anchored: true, backwards: true, nil) - testASCII("FG", anchored: true, backwards: true, nil) - testASCII("FGH", anchored: true, backwards: true, nil) - testASCII("cde", anchored: true, backwards: true, nil) - testASCII("CDE", anchored: true, backwards: true, 12..<15) - testASCII("ABCDE", anchored: true, backwards: true, 10..<15) - testASCII("E", anchored: true, backwards: true, 14..<15) - - tested = "" - testASCII("ABCDER", anchored: false, backwards: false, nil) - } - - func testRangeOfString_graphemeCluster() { - var tested: String - func test(_ string: String, anchored: Bool, backwards: Bool, _ expectation: Range?, file: StaticString = #filePath, line: UInt = #line) { - return _testRangeOfString(tested, string: string, anchored: anchored, backwards: backwards, expectation, file: file, line: line) - } - - do { - // ðŸ³ï¸â€ðŸŒˆ = U+1F3F3 U+FE0F U+200D U+1F308 - // 👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ = U+1F469 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466 - // 🕵ï¸â€â™€ï¸ = U+1F575 U+FE0F U+200D U+2640 U+FE0F - tested = "ðŸ³ï¸â€ðŸŒˆAB👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ab🕵ï¸â€â™€ï¸" - - test("ðŸ³ï¸â€ðŸŒˆ", anchored: false, backwards: false, 0..<1) - test("ðŸ³", anchored: false, backwards: false, nil) // U+1F3F3 - - test("ðŸ³ï¸â€ðŸŒˆA", anchored: false, backwards: false, 0..<2) - - test("B👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦a", anchored: false, backwards: false, 2..<5) - test("b🕵ï¸â€â™€ï¸", anchored: false, backwards: false, 5..<7) - - - test("ðŸ³ï¸â€ðŸŒˆA", anchored: true, backwards: false, 0..<2) - test("AB", anchored: true, backwards: false, nil) - test("B👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦a", anchored: true, backwards: false, nil) - test("b🕵ï¸â€â™€ï¸", anchored: true, backwards: false, nil) - - test("ðŸ³ï¸â€ðŸŒˆ", anchored: true, backwards: true, nil) - test("B👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦a", anchored: true, backwards: true, nil) - test("🕵ï¸â€â™€ï¸", anchored: true, backwards: true, 6..<7) - test("b🕵ï¸â€â™€ï¸", anchored: true, backwards: true, 5..<7) - test("B🕵ï¸â€â™€ï¸", anchored: true, backwards: true, nil) - - } - } - - func testRangeOfString_lineSeparator() { - func test(_ tested: String, _ string: String, anchored: Bool, backwards: Bool, _ expectation: Range?, file: StaticString = #filePath, line: UInt = #line) { - return _testRangeOfString(tested, string: string, anchored: anchored, backwards: backwards, expectation, file: file, line: line) - } - test("\r\n \r", "\r", anchored: false, backwards: false, 2..<3) - test("\r\n \r", "\r", anchored: true, backwards: false, nil) - test("\r\n \r", "\r", anchored: false, backwards: true, 2..<3) - test("\r\n \r", "\r", anchored: true, backwards: true, 2..<3) - - test("\r \r\n \r", "\r", anchored: false, backwards: false, 0..<1) - test("\r \r\n \r", "\r", anchored: true, backwards: false, 0..<1) - test("\r \r\n \r", "\r", anchored: false, backwards: true, 4..<5) - test("\r \r\n \r", "\r", anchored: true, backwards: true, 4..<5) - } - - func testTryFromUTF16() { - func test(_ utf16Buffer: [UInt16], expected: String?, file: StaticString = #filePath, line: UInt = #line) { - let result = utf16Buffer.withUnsafeBufferPointer { - String(_utf16: $0) - } - - XCTAssertEqual(result, expected, file: file, line: line) - } - - test([], expected: "") - test([ 0x00 ], expected: "\u{0000}") - test([ 0x24 ], expected: "$") - test([ 0x41, 0x42 ], expected: "AB") - test([ 0x20AC ], expected: "\u{20AC}") - test([ 0x3040, 0x3041, 0xFFEF ], expected: "\u{3040}\u{3041}\u{FFEF}") - test([ 0x0939, 0x0940 ], expected: "\u{0939}\u{0940}") - - // surrogates - test([ 0xD801, 0xDC37 ], expected: "\u{10437}") - test([ 0xD852, 0xDF62 ], expected: "\u{24B62}") - test([ 0x41, 0x42, 0xD852, 0xDF62 ], expected: "AB\u{24B62}") - - // invalid input - test([ 0xD800 ], expected: nil) - test([ 0x42, 0xD800 ], expected: nil) - test([ 0xD800, 0x42 ], expected: nil) - } - - func testTryFromUTF16_roundtrip() { - - func test(_ string: String, file: StaticString = #filePath, line: UInt = #line) { - let utf16Array = Array(string.utf16) - let res = utf16Array.withUnsafeBufferPointer { - String(_utf16: $0) - } - XCTAssertNotNil(res, file: file, line: line) - XCTAssertEqual(res, string, file: file, line: line) - } - - // BMP: consists code points up to U+FFFF - test("") - test("\t\t\n abcFooFOO \n FOOc\t \t 123 \n") - test("the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy the quick brown fox jumps over the lazy dogz") - test("\u{3040}\u{3041}\u{FFEF}") - test("\u{3040}\u{3041}\u{FFEF}abbbc\u{FFFF}\u{FFF0}\u{FFF1}") - - // surrogates: U+010000 to U+10FFFF - test("\u{10437}\u{24B62}\u{10001}\u{10FFFF}") - - test("\u{1F425}") - test("ðŸ³ï¸â€ðŸŒˆAB👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ab🕵ï¸â€â™€ï¸") - } - - func testRangeRegexB() throws { - let str = "self.name" - let range = try str[...]._range(of: "\\bname"[...], options: .regularExpression) - let start = str.index(str.startIndex, offsetBy: 5) - let end = str.index(str.startIndex, offsetBy: 9) - XCTAssertEqual(range, start ..< end) - } - - func testParagraphLineRangeOfSeparator() { - for separator in ["\n", "\r", "\r\n", "\u{2029}", "\u{2028}", "\u{85}"] { - let range = separator.startIndex ..< separator.endIndex - let paragraphResult = separator._paragraphBounds(around: range) - let lineResult = separator._lineBounds(around: range) - XCTAssertEqual(paragraphResult.start ..< paragraphResult.end, range) - XCTAssertEqual(lineResult.start ..< lineResult.end, range) - } - } - - func testAlmostMatchingSeparator() { - let string = "A\u{200D}B" // U+200D Zero Width Joiner (ZWJ) matches U+2028 Line Separator except for the final UTF-8 scalar - let lineResult = string._lineBounds(around: string.startIndex ..< string.startIndex) - XCTAssertEqual(lineResult.start, string.startIndex) - XCTAssertEqual(lineResult.end, string.endIndex) - XCTAssertEqual(lineResult.contentsEnd, string.endIndex) - } - - func testFileSystemRepresentation() { - func assertCString(_ ptr: UnsafePointer, equals other: String, file: StaticString = #filePath, line: UInt = #line) { - XCTAssertEqual(String(cString: ptr), other, file: file, line: line) - } - -#if os(Windows) - let original = #"\Path1\Path Two\Path Three\Some Really Long File Name Section.txt"# -#else - let original = "/Path1/Path Two/Path Three/Some Really Long File Name Section.txt" -#endif - original.withFileSystemRepresentation { - XCTAssertNotNil($0) - assertCString($0!, equals: original) - } - - let withWhitespace = original + "\u{2000}\u{2001}" - withWhitespace.withFileSystemRepresentation { - XCTAssertNotNil($0) - assertCString($0!, equals: withWhitespace) - } - - let withHangul = original + "\u{AC00}\u{AC01}" - withHangul.withFileSystemRepresentation { buf1 in - XCTAssertNotNil(buf1) - buf1!.withMemoryRebound(to: UInt8.self, capacity: strlen(buf1!)) { buf1Rebound in - let fsr = String(decodingCString: buf1Rebound, as: UTF8.self) - fsr.withFileSystemRepresentation { buf2 in - XCTAssertNotNil(buf2) - XCTAssertEqual(strcmp(buf1!, buf2!), 0) - } - } - } - - let withNullSuffix = original + "\u{0000}\u{0000}" - withNullSuffix.withFileSystemRepresentation { - XCTAssertNotNil($0) - assertCString($0!, equals: original) - } - -#if canImport(Darwin) || FOUNDATION_FRAMEWORK - // The buffer should dynamically grow and not be limited to a size of PATH_MAX - Array(repeating: "A", count: Int(PATH_MAX) - 1).joined().withFileSystemRepresentation { ptr in - XCTAssertNotNil(ptr) - } - - Array(repeating: "A", count: Int(PATH_MAX)).joined().withFileSystemRepresentation { ptr in - XCTAssertNotNil(ptr) - } - - // The buffer should fit the scalars that expand the most during decomposition - for string in ["\u{1D160}", "\u{0CCB}", "\u{0390}"] { - string.withFileSystemRepresentation { ptr in - XCTAssertNotNil(ptr, "Could not create file system representation for \(string.debugDescription)") - } - } -#endif - } - - func testLastPathComponent() { - XCTAssertEqual("".lastPathComponent, "") - XCTAssertEqual("a".lastPathComponent, "a") - XCTAssertEqual("/a".lastPathComponent, "a") - XCTAssertEqual("a/".lastPathComponent, "a") - XCTAssertEqual("/a/".lastPathComponent, "a") - - XCTAssertEqual("a/b".lastPathComponent, "b") - XCTAssertEqual("/a/b".lastPathComponent, "b") - XCTAssertEqual("a/b/".lastPathComponent, "b") - XCTAssertEqual("/a/b/".lastPathComponent, "b") - - XCTAssertEqual("a//".lastPathComponent, "a") - XCTAssertEqual("a////".lastPathComponent, "a") - XCTAssertEqual("/a//".lastPathComponent, "a") - XCTAssertEqual("/a////".lastPathComponent, "a") - XCTAssertEqual("//a//".lastPathComponent, "a") - XCTAssertEqual("/a/b//".lastPathComponent, "b") - XCTAssertEqual("//a//b////".lastPathComponent, "b") - - XCTAssertEqual("/".lastPathComponent, "/") - XCTAssertEqual("//".lastPathComponent, "/") - XCTAssertEqual("/////".lastPathComponent, "/") - XCTAssertEqual("/./..//./..//".lastPathComponent, "..") - XCTAssertEqual("/😎/😂/â¤ï¸/".lastPathComponent, "â¤ï¸") - } - - func testRemovingDotSegments() { - XCTAssertEqual(".".removingDotSegments, "") - XCTAssertEqual("..".removingDotSegments, "") - XCTAssertEqual("../".removingDotSegments, "") - XCTAssertEqual("../.".removingDotSegments, "") - XCTAssertEqual("../..".removingDotSegments, "") - XCTAssertEqual("../../".removingDotSegments, "") - XCTAssertEqual("../../.".removingDotSegments, "") - XCTAssertEqual("../../..".removingDotSegments, "") - XCTAssertEqual("../../../".removingDotSegments, "") - XCTAssertEqual("../.././".removingDotSegments, "") - XCTAssertEqual("../../a".removingDotSegments, "a") - XCTAssertEqual("../../a/".removingDotSegments, "a/") - XCTAssertEqual(".././".removingDotSegments, "") - XCTAssertEqual(".././.".removingDotSegments, "") - XCTAssertEqual(".././..".removingDotSegments, "") - XCTAssertEqual(".././../".removingDotSegments, "") - XCTAssertEqual("../././".removingDotSegments, "") - XCTAssertEqual(".././a".removingDotSegments, "a") - XCTAssertEqual(".././a/".removingDotSegments, "a/") - XCTAssertEqual("../a".removingDotSegments, "a") - XCTAssertEqual("../a/".removingDotSegments, "a/") - XCTAssertEqual("../a/.".removingDotSegments, "a/") - XCTAssertEqual("../a/..".removingDotSegments, "/") - XCTAssertEqual("../a/../".removingDotSegments, "/") - XCTAssertEqual("../a/./".removingDotSegments, "a/") - XCTAssertEqual("../a/b".removingDotSegments, "a/b") - XCTAssertEqual("../a/b/".removingDotSegments, "a/b/") - XCTAssertEqual("./".removingDotSegments, "") - XCTAssertEqual("./.".removingDotSegments, "") - XCTAssertEqual("./..".removingDotSegments, "") - XCTAssertEqual("./../".removingDotSegments, "") - XCTAssertEqual("./../.".removingDotSegments, "") - XCTAssertEqual("./../..".removingDotSegments, "") - XCTAssertEqual("./../../".removingDotSegments, "") - XCTAssertEqual("./.././".removingDotSegments, "") - XCTAssertEqual("./../a".removingDotSegments, "a") - XCTAssertEqual("./../a/".removingDotSegments, "a/") - XCTAssertEqual("././".removingDotSegments, "") - XCTAssertEqual("././.".removingDotSegments, "") - XCTAssertEqual("././..".removingDotSegments, "") - XCTAssertEqual("././../".removingDotSegments, "") - XCTAssertEqual("./././".removingDotSegments, "") - XCTAssertEqual("././a".removingDotSegments, "a") - XCTAssertEqual("././a/".removingDotSegments, "a/") - XCTAssertEqual("./a".removingDotSegments, "a") - XCTAssertEqual("./a/".removingDotSegments, "a/") - XCTAssertEqual("./a/.".removingDotSegments, "a/") - XCTAssertEqual("./a/..".removingDotSegments, "/") - XCTAssertEqual("./a/../".removingDotSegments, "/") - XCTAssertEqual("./a/./".removingDotSegments, "a/") - XCTAssertEqual("./a/b".removingDotSegments, "a/b") - XCTAssertEqual("./a/b/".removingDotSegments, "a/b/") - XCTAssertEqual("/".removingDotSegments, "/") - XCTAssertEqual("/.".removingDotSegments, "/") - XCTAssertEqual("/..".removingDotSegments, "/") - XCTAssertEqual("/../".removingDotSegments, "/") - XCTAssertEqual("/../.".removingDotSegments, "/") - XCTAssertEqual("/../..".removingDotSegments, "/") - XCTAssertEqual("/../../".removingDotSegments, "/") - XCTAssertEqual("/../../.".removingDotSegments, "/") - XCTAssertEqual("/../../..".removingDotSegments, "/") - XCTAssertEqual("/../../../".removingDotSegments, "/") - XCTAssertEqual("/../.././".removingDotSegments, "/") - XCTAssertEqual("/../../a".removingDotSegments, "/a") - XCTAssertEqual("/../../a/".removingDotSegments, "/a/") - XCTAssertEqual("/.././".removingDotSegments, "/") - XCTAssertEqual("/.././.".removingDotSegments, "/") - XCTAssertEqual("/.././..".removingDotSegments, "/") - XCTAssertEqual("/.././../".removingDotSegments, "/") - XCTAssertEqual("/../././".removingDotSegments, "/") - XCTAssertEqual("/.././a".removingDotSegments, "/a") - XCTAssertEqual("/.././a/".removingDotSegments, "/a/") - XCTAssertEqual("/../a".removingDotSegments, "/a") - XCTAssertEqual("/../a/".removingDotSegments, "/a/") - XCTAssertEqual("/../a/.".removingDotSegments, "/a/") - XCTAssertEqual("/../a/..".removingDotSegments, "/") - XCTAssertEqual("/../a/../".removingDotSegments, "/") - XCTAssertEqual("/../a/./".removingDotSegments, "/a/") - XCTAssertEqual("/../a/b".removingDotSegments, "/a/b") - XCTAssertEqual("/../a/b/".removingDotSegments, "/a/b/") - XCTAssertEqual("/./".removingDotSegments, "/") - XCTAssertEqual("/./.".removingDotSegments, "/") - XCTAssertEqual("/./..".removingDotSegments, "/") - XCTAssertEqual("/./../".removingDotSegments, "/") - XCTAssertEqual("/./../.".removingDotSegments, "/") - XCTAssertEqual("/./../..".removingDotSegments, "/") - XCTAssertEqual("/./../../".removingDotSegments, "/") - XCTAssertEqual("/./.././".removingDotSegments, "/") - XCTAssertEqual("/./../a".removingDotSegments, "/a") - XCTAssertEqual("/./../a/".removingDotSegments, "/a/") - XCTAssertEqual("/././".removingDotSegments, "/") - XCTAssertEqual("/././.".removingDotSegments, "/") - XCTAssertEqual("/././..".removingDotSegments, "/") - XCTAssertEqual("/././../".removingDotSegments, "/") - XCTAssertEqual("/./././".removingDotSegments, "/") - XCTAssertEqual("/././a".removingDotSegments, "/a") - XCTAssertEqual("/././a/".removingDotSegments, "/a/") - XCTAssertEqual("/./a".removingDotSegments, "/a") - XCTAssertEqual("/./a/".removingDotSegments, "/a/") - XCTAssertEqual("/./a/.".removingDotSegments, "/a/") - XCTAssertEqual("/./a/..".removingDotSegments, "/") - XCTAssertEqual("/./a/../".removingDotSegments, "/") - XCTAssertEqual("/./a/./".removingDotSegments, "/a/") - XCTAssertEqual("/./a/b".removingDotSegments, "/a/b") - XCTAssertEqual("/./a/b/".removingDotSegments, "/a/b/") - XCTAssertEqual("/a".removingDotSegments, "/a") - XCTAssertEqual("/a/".removingDotSegments, "/a/") - XCTAssertEqual("/a/.".removingDotSegments, "/a/") - XCTAssertEqual("/a/..".removingDotSegments, "/") - XCTAssertEqual("/a/../".removingDotSegments, "/") - XCTAssertEqual("/a/../.".removingDotSegments, "/") - XCTAssertEqual("/a/../..".removingDotSegments, "/") - XCTAssertEqual("/a/../../".removingDotSegments, "/") - XCTAssertEqual("/a/.././".removingDotSegments, "/") - XCTAssertEqual("/a/../b".removingDotSegments, "/b") - XCTAssertEqual("/a/../b/".removingDotSegments, "/b/") - XCTAssertEqual("/a/./".removingDotSegments, "/a/") - XCTAssertEqual("/a/./.".removingDotSegments, "/a/") - XCTAssertEqual("/a/./..".removingDotSegments, "/") - XCTAssertEqual("/a/./../".removingDotSegments, "/") - XCTAssertEqual("/a/././".removingDotSegments, "/a/") - XCTAssertEqual("/a/./b".removingDotSegments, "/a/b") - XCTAssertEqual("/a/./b/".removingDotSegments, "/a/b/") - XCTAssertEqual("/a/b".removingDotSegments, "/a/b") - XCTAssertEqual("/a/b/".removingDotSegments, "/a/b/") - XCTAssertEqual("/a/b/.".removingDotSegments, "/a/b/") - XCTAssertEqual("/a/b/..".removingDotSegments, "/a/") - XCTAssertEqual("/a/b/../".removingDotSegments, "/a/") - XCTAssertEqual("/a/b/../.".removingDotSegments, "/a/") - XCTAssertEqual("/a/b/../..".removingDotSegments, "/") - XCTAssertEqual("/a/b/../../".removingDotSegments, "/") - XCTAssertEqual("/a/b/.././".removingDotSegments, "/a/") - XCTAssertEqual("/a/b/../c".removingDotSegments, "/a/c") - XCTAssertEqual("/a/b/../c/".removingDotSegments, "/a/c/") - XCTAssertEqual("/a/b/./".removingDotSegments, "/a/b/") - XCTAssertEqual("/a/b/./.".removingDotSegments, "/a/b/") - XCTAssertEqual("/a/b/./..".removingDotSegments, "/a/") - XCTAssertEqual("/a/b/./../".removingDotSegments, "/a/") - XCTAssertEqual("/a/b/././".removingDotSegments, "/a/b/") - XCTAssertEqual("/a/b/./c".removingDotSegments, "/a/b/c") - XCTAssertEqual("/a/b/./c/".removingDotSegments, "/a/b/c/") - XCTAssertEqual("/a/b/c".removingDotSegments, "/a/b/c") - XCTAssertEqual("/a/b/c/".removingDotSegments, "/a/b/c/") - XCTAssertEqual("/a/b/c/.".removingDotSegments, "/a/b/c/") - XCTAssertEqual("/a/b/c/..".removingDotSegments, "/a/b/") - XCTAssertEqual("/a/b/c/../".removingDotSegments, "/a/b/") - XCTAssertEqual("/a/b/c/./".removingDotSegments, "/a/b/c/") - XCTAssertEqual("a".removingDotSegments, "a") - XCTAssertEqual("a/".removingDotSegments, "a/") - XCTAssertEqual("a/.".removingDotSegments, "a/") - XCTAssertEqual("a/..".removingDotSegments, "/") - XCTAssertEqual("a/../".removingDotSegments, "/") - XCTAssertEqual("a/../.".removingDotSegments, "/") - XCTAssertEqual("a/../..".removingDotSegments, "/") - XCTAssertEqual("a/../../".removingDotSegments, "/") - XCTAssertEqual("a/.././".removingDotSegments, "/") - XCTAssertEqual("a/../b".removingDotSegments, "/b") - XCTAssertEqual("a/../b/".removingDotSegments, "/b/") - XCTAssertEqual("a/./".removingDotSegments, "a/") - XCTAssertEqual("a/./.".removingDotSegments, "a/") - XCTAssertEqual("a/./..".removingDotSegments, "/") - XCTAssertEqual("a/./../".removingDotSegments, "/") - XCTAssertEqual("a/././".removingDotSegments, "a/") - XCTAssertEqual("a/./b".removingDotSegments, "a/b") - XCTAssertEqual("a/./b/".removingDotSegments, "a/b/") - XCTAssertEqual("a/b".removingDotSegments, "a/b") - XCTAssertEqual("a/b/".removingDotSegments, "a/b/") - XCTAssertEqual("a/b/.".removingDotSegments, "a/b/") - XCTAssertEqual("a/b/..".removingDotSegments, "a/") - XCTAssertEqual("a/b/../".removingDotSegments, "a/") - XCTAssertEqual("a/b/../.".removingDotSegments, "a/") - XCTAssertEqual("a/b/../..".removingDotSegments, "/") - XCTAssertEqual("a/b/../../".removingDotSegments, "/") - XCTAssertEqual("a/b/.././".removingDotSegments, "a/") - XCTAssertEqual("a/b/../c".removingDotSegments, "a/c") - XCTAssertEqual("a/b/../c/".removingDotSegments, "a/c/") - XCTAssertEqual("a/b/./".removingDotSegments, "a/b/") - XCTAssertEqual("a/b/./.".removingDotSegments, "a/b/") - XCTAssertEqual("a/b/./..".removingDotSegments, "a/") - XCTAssertEqual("a/b/./../".removingDotSegments, "a/") - XCTAssertEqual("a/b/././".removingDotSegments, "a/b/") - XCTAssertEqual("a/b/./c".removingDotSegments, "a/b/c") - XCTAssertEqual("a/b/./c/".removingDotSegments, "a/b/c/") - XCTAssertEqual("a/b/c".removingDotSegments, "a/b/c") - XCTAssertEqual("a/b/c/".removingDotSegments, "a/b/c/") - XCTAssertEqual("a/b/c/.".removingDotSegments, "a/b/c/") - XCTAssertEqual("a/b/c/..".removingDotSegments, "a/b/") - XCTAssertEqual("a/b/c/../".removingDotSegments, "a/b/") - XCTAssertEqual("a/b/c/./".removingDotSegments, "a/b/c/") - - // None of the inputs below contain "." or ".." and should therefore be treated as regular path components - - XCTAssertEqual("...".removingDotSegments, "...") - XCTAssertEqual(".../".removingDotSegments, ".../") - XCTAssertEqual(".../...".removingDotSegments, ".../...") - XCTAssertEqual(".../.../".removingDotSegments, ".../.../") - XCTAssertEqual(".../..a".removingDotSegments, ".../..a") - XCTAssertEqual(".../..a/".removingDotSegments, ".../..a/") - XCTAssertEqual(".../.a".removingDotSegments, ".../.a") - XCTAssertEqual(".../.a/".removingDotSegments, ".../.a/") - XCTAssertEqual(".../a.".removingDotSegments, ".../a.") - XCTAssertEqual(".../a..".removingDotSegments, ".../a..") - XCTAssertEqual(".../a../".removingDotSegments, ".../a../") - XCTAssertEqual(".../a./".removingDotSegments, ".../a./") - XCTAssertEqual("..a".removingDotSegments, "..a") - XCTAssertEqual("..a/".removingDotSegments, "..a/") - XCTAssertEqual("..a/...".removingDotSegments, "..a/...") - XCTAssertEqual("..a/.../".removingDotSegments, "..a/.../") - XCTAssertEqual("..a/..b".removingDotSegments, "..a/..b") - XCTAssertEqual("..a/..b/".removingDotSegments, "..a/..b/") - XCTAssertEqual("..a/.b".removingDotSegments, "..a/.b") - XCTAssertEqual("..a/.b/".removingDotSegments, "..a/.b/") - XCTAssertEqual("..a/b.".removingDotSegments, "..a/b.") - XCTAssertEqual("..a/b..".removingDotSegments, "..a/b..") - XCTAssertEqual("..a/b../".removingDotSegments, "..a/b../") - XCTAssertEqual("..a/b./".removingDotSegments, "..a/b./") - XCTAssertEqual(".a".removingDotSegments, ".a") - XCTAssertEqual(".a/".removingDotSegments, ".a/") - XCTAssertEqual(".a/...".removingDotSegments, ".a/...") - XCTAssertEqual(".a/.../".removingDotSegments, ".a/.../") - XCTAssertEqual(".a/..b".removingDotSegments, ".a/..b") - XCTAssertEqual(".a/..b/".removingDotSegments, ".a/..b/") - XCTAssertEqual(".a/.b".removingDotSegments, ".a/.b") - XCTAssertEqual(".a/.b/".removingDotSegments, ".a/.b/") - XCTAssertEqual(".a/b.".removingDotSegments, ".a/b.") - XCTAssertEqual(".a/b..".removingDotSegments, ".a/b..") - XCTAssertEqual(".a/b../".removingDotSegments, ".a/b../") - XCTAssertEqual(".a/b./".removingDotSegments, ".a/b./") - XCTAssertEqual("/".removingDotSegments, "/") - XCTAssertEqual("/...".removingDotSegments, "/...") - XCTAssertEqual("/.../".removingDotSegments, "/.../") - XCTAssertEqual("/..a".removingDotSegments, "/..a") - XCTAssertEqual("/..a/".removingDotSegments, "/..a/") - XCTAssertEqual("/.a".removingDotSegments, "/.a") - XCTAssertEqual("/.a/".removingDotSegments, "/.a/") - XCTAssertEqual("/a.".removingDotSegments, "/a.") - XCTAssertEqual("/a..".removingDotSegments, "/a..") - XCTAssertEqual("/a../".removingDotSegments, "/a../") - XCTAssertEqual("/a./".removingDotSegments, "/a./") - XCTAssertEqual("a.".removingDotSegments, "a.") - XCTAssertEqual("a..".removingDotSegments, "a..") - XCTAssertEqual("a../".removingDotSegments, "a../") - XCTAssertEqual("a../...".removingDotSegments, "a../...") - XCTAssertEqual("a../.../".removingDotSegments, "a../.../") - XCTAssertEqual("a../..b".removingDotSegments, "a../..b") - XCTAssertEqual("a../..b/".removingDotSegments, "a../..b/") - XCTAssertEqual("a../.b".removingDotSegments, "a../.b") - XCTAssertEqual("a../.b/".removingDotSegments, "a../.b/") - XCTAssertEqual("a../b.".removingDotSegments, "a../b.") - XCTAssertEqual("a../b..".removingDotSegments, "a../b..") - XCTAssertEqual("a../b../".removingDotSegments, "a../b../") - XCTAssertEqual("a../b./".removingDotSegments, "a../b./") - XCTAssertEqual("a./".removingDotSegments, "a./") - XCTAssertEqual("a./...".removingDotSegments, "a./...") - XCTAssertEqual("a./.../".removingDotSegments, "a./.../") - XCTAssertEqual("a./..b".removingDotSegments, "a./..b") - XCTAssertEqual("a./..b/".removingDotSegments, "a./..b/") - XCTAssertEqual("a./.b".removingDotSegments, "a./.b") - XCTAssertEqual("a./.b/".removingDotSegments, "a./.b/") - XCTAssertEqual("a./b.".removingDotSegments, "a./b.") - XCTAssertEqual("a./b..".removingDotSegments, "a./b..") - XCTAssertEqual("a./b../".removingDotSegments, "a./b../") - XCTAssertEqual("a./b./".removingDotSegments, "a./b./") - - // Repeated slashes should not be resolved when only removing dot segments - - XCTAssertEqual("../..//".removingDotSegments, "/") - XCTAssertEqual(".././/".removingDotSegments, "/") - XCTAssertEqual("..//".removingDotSegments, "/") - XCTAssertEqual("..//.".removingDotSegments, "/") - XCTAssertEqual("..//..".removingDotSegments, "/") - XCTAssertEqual("..//../".removingDotSegments, "/") - XCTAssertEqual("..//./".removingDotSegments, "/") - XCTAssertEqual("..///".removingDotSegments, "//") - XCTAssertEqual("..//a".removingDotSegments, "/a") - XCTAssertEqual("..//a/".removingDotSegments, "/a/") - XCTAssertEqual("../a//".removingDotSegments, "a//") - XCTAssertEqual("./..//".removingDotSegments, "/") - XCTAssertEqual("././/".removingDotSegments, "/") - XCTAssertEqual(".//".removingDotSegments, "/") - XCTAssertEqual(".//.".removingDotSegments, "/") - XCTAssertEqual(".//..".removingDotSegments, "/") - XCTAssertEqual(".//../".removingDotSegments, "/") - XCTAssertEqual(".//./".removingDotSegments, "/") - XCTAssertEqual(".///".removingDotSegments, "//") - XCTAssertEqual(".//a".removingDotSegments, "/a") - XCTAssertEqual(".//a/".removingDotSegments, "/a/") - XCTAssertEqual("./a//".removingDotSegments, "a//") - XCTAssertEqual("/../..//".removingDotSegments, "//") - XCTAssertEqual("/.././/".removingDotSegments, "//") - XCTAssertEqual("/..//".removingDotSegments, "//") - XCTAssertEqual("/..//.".removingDotSegments, "//") - XCTAssertEqual("/..//..".removingDotSegments, "/") - XCTAssertEqual("/..//../".removingDotSegments, "/") - XCTAssertEqual("/..//./".removingDotSegments, "//") - XCTAssertEqual("/..///".removingDotSegments, "///") - XCTAssertEqual("/..//a".removingDotSegments, "//a") - XCTAssertEqual("/..//a/".removingDotSegments, "//a/") - XCTAssertEqual("/../a//".removingDotSegments, "/a//") - XCTAssertEqual("/./..//".removingDotSegments, "//") - XCTAssertEqual("/././/".removingDotSegments, "//") - XCTAssertEqual("/.//".removingDotSegments, "//") - XCTAssertEqual("/.//.".removingDotSegments, "//") - XCTAssertEqual("/.//..".removingDotSegments, "/") - XCTAssertEqual("/.//../".removingDotSegments, "/") - XCTAssertEqual("/.//./".removingDotSegments, "//") - XCTAssertEqual("/.///".removingDotSegments, "///") - XCTAssertEqual("/.//a".removingDotSegments, "//a") - XCTAssertEqual("/.//a/".removingDotSegments, "//a/") - XCTAssertEqual("/./a//".removingDotSegments, "/a//") - XCTAssertEqual("//".removingDotSegments, "//") - XCTAssertEqual("//.".removingDotSegments, "//") - XCTAssertEqual("//..".removingDotSegments, "/") - XCTAssertEqual("//../".removingDotSegments, "/") - XCTAssertEqual("//./".removingDotSegments, "//") - XCTAssertEqual("///".removingDotSegments, "///") - XCTAssertEqual("//a".removingDotSegments, "//a") - XCTAssertEqual("//a/".removingDotSegments, "//a/") - XCTAssertEqual("/a/..//".removingDotSegments, "//") - XCTAssertEqual("/a/.//".removingDotSegments, "/a//") - XCTAssertEqual("/a//".removingDotSegments, "/a//") - XCTAssertEqual("/a//.".removingDotSegments, "/a//") - XCTAssertEqual("/a//..".removingDotSegments, "/a/") - XCTAssertEqual("/a//../".removingDotSegments, "/a/") - XCTAssertEqual("/a//./".removingDotSegments, "/a//") - XCTAssertEqual("/a///".removingDotSegments, "/a///") - XCTAssertEqual("/a//b".removingDotSegments, "/a//b") - XCTAssertEqual("/a//b/".removingDotSegments, "/a//b/") - XCTAssertEqual("/a/b/..//".removingDotSegments, "/a//") - XCTAssertEqual("/a/b/.//".removingDotSegments, "/a/b//") - XCTAssertEqual("/a/b//".removingDotSegments, "/a/b//") - XCTAssertEqual("/a/b//.".removingDotSegments, "/a/b//") - XCTAssertEqual("/a/b//..".removingDotSegments, "/a/b/") - XCTAssertEqual("/a/b//../".removingDotSegments, "/a/b/") - XCTAssertEqual("/a/b//./".removingDotSegments, "/a/b//") - XCTAssertEqual("/a/b///".removingDotSegments, "/a/b///") - XCTAssertEqual("/a/b//c".removingDotSegments, "/a/b//c") - XCTAssertEqual("/a/b//c/".removingDotSegments, "/a/b//c/") - XCTAssertEqual("/a/b/c//".removingDotSegments, "/a/b/c//") - XCTAssertEqual("a/..//".removingDotSegments, "//") - XCTAssertEqual("a/.//".removingDotSegments, "a//") - XCTAssertEqual("a//".removingDotSegments, "a//") - XCTAssertEqual("a//.".removingDotSegments, "a//") - XCTAssertEqual("a//..".removingDotSegments, "a/") - XCTAssertEqual("a//../".removingDotSegments, "a/") - XCTAssertEqual("a//./".removingDotSegments, "a//") - XCTAssertEqual("a///".removingDotSegments, "a///") - XCTAssertEqual("a//b".removingDotSegments, "a//b") - XCTAssertEqual("a//b/".removingDotSegments, "a//b/") - XCTAssertEqual("a/b/..//".removingDotSegments, "a//") - XCTAssertEqual("a/b/.//".removingDotSegments, "a/b//") - XCTAssertEqual("a/b//".removingDotSegments, "a/b//") - XCTAssertEqual("a/b//.".removingDotSegments, "a/b//") - XCTAssertEqual("a/b//..".removingDotSegments, "a/b/") - XCTAssertEqual("a/b//../".removingDotSegments, "a/b/") - XCTAssertEqual("a/b//./".removingDotSegments, "a/b//") - XCTAssertEqual("a/b///".removingDotSegments, "a/b///") - XCTAssertEqual("a/b//c".removingDotSegments, "a/b//c") - XCTAssertEqual("a/b//c/".removingDotSegments, "a/b//c/") - XCTAssertEqual("a/b/c//".removingDotSegments, "a/b/c//") - } - - func testPathExtension() { - let stringNoExtension = "0123456789" - let stringWithExtension = "\(stringNoExtension).foo" - XCTAssertEqual(stringNoExtension.appendingPathExtension("foo"), stringWithExtension) - - var invalidExtensions = [String]() - for scalar in String.invalidExtensionScalars { - invalidExtensions.append("\(scalar)foo") - invalidExtensions.append("foo\(scalar)") - invalidExtensions.append("f\(scalar)oo") - } - let invalidExtensionStrings = invalidExtensions.map { "\(stringNoExtension).\($0)" } - - XCTAssertEqual(stringNoExtension.pathExtension, "") - XCTAssertEqual(stringWithExtension.pathExtension, "foo") - XCTAssertEqual(stringNoExtension.deletingPathExtension(), stringNoExtension) - XCTAssertEqual(stringWithExtension.deletingPathExtension(), stringNoExtension) - - for invalidExtensionString in invalidExtensionStrings { - if invalidExtensionString.last == "/" { - continue - } - XCTAssertEqual(invalidExtensionString.pathExtension, "") - XCTAssertEqual(invalidExtensionString.deletingPathExtension(), invalidExtensionString) - } - - for invalidExtension in invalidExtensions { - XCTAssertEqual(stringNoExtension.appendingPathExtension(invalidExtension), stringNoExtension) - } - } - - func testAppendingPathExtension() { - XCTAssertEqual("".appendingPathExtension("foo"), ".foo") - XCTAssertEqual("/".appendingPathExtension("foo"), "/.foo") - XCTAssertEqual("//".appendingPathExtension("foo"), "/.foo/") - XCTAssertEqual("/path".appendingPathExtension("foo"), "/path.foo") - XCTAssertEqual("/path.zip".appendingPathExtension("foo"), "/path.zip.foo") - XCTAssertEqual("/path/".appendingPathExtension("foo"), "/path.foo/") - XCTAssertEqual("/path//".appendingPathExtension("foo"), "/path.foo/") - XCTAssertEqual("path".appendingPathExtension("foo"), "path.foo") - XCTAssertEqual("path/".appendingPathExtension("foo"), "path.foo/") - XCTAssertEqual("path//".appendingPathExtension("foo"), "path.foo/") - } - - func testDeletingPathExtenstion() { - XCTAssertEqual("".deletingPathExtension(), "") - XCTAssertEqual("/".deletingPathExtension(), "/") - XCTAssertEqual("/foo/bar".deletingPathExtension(), "/foo/bar") - XCTAssertEqual("/foo/bar.zip".deletingPathExtension(), "/foo/bar") - XCTAssertEqual("/foo/bar.baz.zip".deletingPathExtension(), "/foo/bar.baz") - XCTAssertEqual(".".deletingPathExtension(), ".") - XCTAssertEqual(".zip".deletingPathExtension(), ".zip") - XCTAssertEqual("zip.".deletingPathExtension(), "zip.") - XCTAssertEqual(".zip.".deletingPathExtension(), ".zip.") - XCTAssertEqual("/foo/bar/.zip".deletingPathExtension(), "/foo/bar/.zip") - XCTAssertEqual("..".deletingPathExtension(), "..") - XCTAssertEqual("..zip".deletingPathExtension(), "..zip") - XCTAssertEqual("/foo/bar/..zip".deletingPathExtension(), "/foo/bar/..zip") - XCTAssertEqual("/foo/bar/baz..zip".deletingPathExtension(), "/foo/bar/baz.") - XCTAssertEqual("...".deletingPathExtension(), "...") - XCTAssertEqual("...zip".deletingPathExtension(), "...zip") - XCTAssertEqual("/foo/bar/...zip".deletingPathExtension(), "/foo/bar/...zip") - XCTAssertEqual("/foo/bar/baz...zip".deletingPathExtension(), "/foo/bar/baz..") - XCTAssertEqual("/foo.bar/bar.baz/baz.zip".deletingPathExtension(), "/foo.bar/bar.baz/baz") - XCTAssertEqual("/.././.././a.zip".deletingPathExtension(), "/.././.././a") - XCTAssertEqual("/.././.././.".deletingPathExtension(), "/.././.././.") - - XCTAssertEqual("path.foo".deletingPathExtension(), "path") - XCTAssertEqual("path.foo.zip".deletingPathExtension(), "path.foo") - XCTAssertEqual("/path.foo".deletingPathExtension(), "/path") - XCTAssertEqual("/path.foo.zip".deletingPathExtension(), "/path.foo") - XCTAssertEqual("path.foo/".deletingPathExtension(), "path/") - XCTAssertEqual("path.foo//".deletingPathExtension(), "path/") - XCTAssertEqual("/path.foo/".deletingPathExtension(), "/path/") - XCTAssertEqual("/path.foo//".deletingPathExtension(), "/path/") - } - - func testPathComponents() { - let tests: [(String, [String])] = [ - ("", []), - ("/", ["/"]), - ("//", ["/", "/"]), - ("a", ["a"]), - ("/a", ["/", "a"]), - ("a/", ["a", "/"]), - ("/a/", ["/", "a", "/"]), - ("///", ["/", "/"]), - ("//a", ["/", "a"]), - ("a//", ["a", "/"]), - ("//a//", ["/", "a", "/"]), - ("a/b/c", ["a", "b", "c"]), - ("/a/b/c", ["/", "a", "b", "c"]), - ("a/b/c/", ["a", "b", "c", "/"]), - ("/a/b/c/", ["/", "a", "b", "c", "/"]), - ("/abc//def///ghi/jkl//123///456/7890//", ["/", "abc", "def", "ghi", "jkl", "123", "456", "7890", "/"]), - ("/😎/😂/â¤ï¸/", ["/", "😎", "😂", "â¤ï¸", "/"]), - ("J'aime//le//café//☕ï¸", ["J'aime", "le", "café", "☕ï¸"]), - ("U+2215∕instead∕of∕slash(U+002F)", ["U+2215∕instead∕of∕slash(U+002F)"]), - ] - for (input, expected) in tests { - let result = input.pathComponents - XCTAssertEqual(result, expected) - } - } - - func test_dataUsingEncoding() { - let s = "hello 🧮" - - // Verify things work on substrings too - let s2 = "x" + s + "x" - let subString = s2[s2.index(after: s2.startIndex).. Bool { - let str = String(data: data, encoding: .utf8)! - let strAsUTF16BE = str.data(using: String._Encoding.utf16BigEndian)! - let strRoundTripUTF16BE = String(data: strAsUTF16BE, encoding: .utf16BigEndian)! - return strRoundTripUTF16BE == str - } - - // Verify that the BOM is preserved through a UTF8/16 transformation. - - // ASCII '2' followed by UTF8 BOM - XCTAssertTrue(roundTrip(Data([ 0x32, 0xef, 0xbb, 0xbf ]))) - - // UTF8 BOM followed by ASCII '4' - XCTAssertTrue(roundTrip(Data([ 0xef, 0xbb, 0xbf, 0x34 ]))) - } - - func test_dataUsingEncoding_ascii() { - XCTAssertEqual("abc".data(using: .ascii), Data([UInt8(ascii: "a"), UInt8(ascii: "b"), UInt8(ascii: "c")])) - XCTAssertEqual("abc".data(using: .nonLossyASCII), Data([UInt8(ascii: "a"), UInt8(ascii: "b"), UInt8(ascii: "c")])) - XCTAssertEqual("e\u{301}\u{301}f".data(using: String._Encoding.ascii), nil) - XCTAssertEqual("e\u{301}\u{301}f".data(using: String._Encoding.nonLossyASCII), nil) - - XCTAssertEqual("abc".data(using: .ascii, allowLossyConversion: true), Data([UInt8(ascii: "a"), UInt8(ascii: "b"), UInt8(ascii: "c")])) - XCTAssertEqual("abc".data(using: .nonLossyASCII, allowLossyConversion: true), Data([UInt8(ascii: "a"), UInt8(ascii: "b"), UInt8(ascii: "c")])) - XCTAssertEqual("e\u{301}\u{301}f".data(using: .ascii, allowLossyConversion: true), Data([UInt8(ascii: "e"), 0xFF, 0xFF, UInt8(ascii: "f")])) - XCTAssertEqual("e\u{301}\u{301}f".data(using: .nonLossyASCII, allowLossyConversion: true), Data([UInt8(ascii: "e"), UInt8(ascii: "?"), UInt8(ascii: "?"), UInt8(ascii: "f")])) - } - - func test_initWithBytes_ascii() { - XCTAssertEqual(String(bytes: "abc".utf8, encoding: String._Encoding.ascii), "abc") - XCTAssertEqual(String(bytes: "abc".utf8, encoding: String._Encoding.nonLossyASCII), "abc") - XCTAssertEqual(String(bytes: "e\u{301}\u{301}f".utf8, encoding: String._Encoding.ascii), nil) - XCTAssertEqual(String(bytes: "e\u{301}\u{301}f".utf8, encoding: String._Encoding.nonLossyASCII), nil) - } - - func test_compressingSlashes() { - let testCases: [(String, String)] = [ - ("", ""), // Empty string - ("/", "/"), // Single slash - ("/////", "/"), // All slashes - ("ABCDE", "ABCDE"), // No slashes - ("//ABC", "/ABC"), // Starts with multiple slashes - ("/ABCD", "/ABCD"), // Starts with single slash - ("ABC//", "ABC/"), // Ends with multiple slashes - ("ABCD/", "ABCD/"), // Ends with single slash - ("//ABC//", "/ABC/"), // Starts and ends with multiple slashes - ("AB/CD", "AB/CD"), // Single internal slash - ("AB//DF/GH//I", "AB/DF/GH/I"), // Internal slashes - ("//😎///😂/â¤ï¸//", "/😎/😂/â¤ï¸/") - ] - for (testString, expectedResult) in testCases { - let result = testString - ._compressingSlashes() - XCTAssertEqual(result, expectedResult) - } - } - - func test_pathHasDotDotComponent() { - let testCases: [(String, Bool)] = [ - ("../AB", true), // Begins with .. - ("/ABC/..", true), // Ends with .. - ("/ABC/../DEF", true), // Internal .. - ("/ABC/DEF..", false), // Ends with .. but not part of path - ("ABC/../../DEF", true), // Multiple internal dot dot - ("/AB/./CD", false), // Internal single dot - ("/AB/..../CD", false), // Internal multiple dots - ("..", true), // Dot dot only - ("...", false), - ("..AB", false), - ("..AB/", false), - ("..AB/..", true), - (".AB/./.", false), - ("/..AB/", false), - ("A../", false), - ("/..", true), - ("././/./.", false) - ] - for (testString, expectedResult) in testCases { - let result = testString - ._hasDotDotComponent() - XCTAssertEqual(result, expectedResult) - } - } - - func test_init_contentsOfFile_encoding() { - withTemporaryStringFile { existingURL, nonExistentURL in - do { - let content = try String(contentsOfFile: existingURL.path, encoding: String._Encoding.ascii) - expectEqual(temporaryFileContents, content) - } catch { - XCTFail(error.localizedDescription) - } - - do { - let _ = try String(contentsOfFile: nonExistentURL.path, encoding: String._Encoding.ascii) - XCTFail() - } catch { - } - } - } - - func test_init_contentsOfFile_usedEncoding() { - withTemporaryStringFile { existingURL, nonExistentURL in - do { - var usedEncoding: String._Encoding = String._Encoding(rawValue: 0) - let content = try String(contentsOfFile: existingURL.path(), usedEncoding: &usedEncoding) - expectNotEqual(0, usedEncoding.rawValue) - expectEqual(temporaryFileContents, content) - } catch { - XCTFail(error.localizedDescription) - } - } - - } - - - func test_init_contentsOf_encoding() { - withTemporaryStringFile { existingURL, nonExistentURL in - do { - let content = try String(contentsOf: existingURL, encoding: String._Encoding.ascii) - expectEqual(temporaryFileContents, content) - } catch { - XCTFail(error.localizedDescription) - } - - do { - _ = try String(contentsOf: nonExistentURL, encoding: String._Encoding.ascii) - XCTFail() - } catch { - } - } - - } - - func test_init_contentsOf_usedEncoding() { -#if FOUNDATION_FRAMEWORK - let encs : [String._Encoding] = [ - .ascii, - .nextstep, - .japaneseEUC, - .utf8, - .isoLatin1, - .nonLossyASCII, - .shiftJIS, - .isoLatin2, - .unicode, - .windowsCP1251, - .windowsCP1252, - .windowsCP1253, - .windowsCP1254, - .windowsCP1250, - .iso2022JP, - .macOSRoman, - .utf16, - .utf16BigEndian, - .utf16LittleEndian, - .utf32, - .utf32BigEndian, - .utf32LittleEndian - ] -#else - var encs : [String._Encoding] = [ - .utf8, - .utf16, - .utf32, - ] - - // A note about utf16/32 little/big endian - // Foundation will only write out the BOM for encoded string data when using the unspecified encoding versions (.utf16, .utf32). It will, however, write the extended attribute if it can. - // On non-Darwin platforms, where we have less guarantee that the extended attribute was succesfully written, we cannot actually promise that the round-trip below will work. If the xattr fails to write (which we do not report as an error, for both historical and practical reasons), and the BOM is not present, then we will just read the data back in as UTF8. - // Therefore, we only test here the utf8/16/32 encodings. - - #if canImport(Darwin) - // Only test non-UTF encodings on platforms where we successfully read/write the extended file attribute - encs += [ - .ascii, - .macOSRoman, - .isoLatin1 - ] - #endif -#endif - - for encoding in encs { - withTemporaryStringFile(encoding: encoding) { existingURL, _ in - do { - var usedEncoding = String._Encoding(rawValue: 0) - let content = try String(contentsOf: existingURL, usedEncoding: &usedEncoding) - - expectEqual(encoding, usedEncoding) - expectEqual(temporaryFileContents, content) - } catch { - XCTFail("\(error) - encoding \(encoding)") - } - } - } - - // Test non-existent file - withTemporaryStringFile { _, nonExistentURL in - var usedEncoding: String._Encoding = String._Encoding(rawValue: 0) - do { - _ = try String(contentsOf: nonExistentURL, usedEncoding: &usedEncoding) - XCTFail() - } catch { - expectEqual(0, usedEncoding.rawValue) - } - } - } - - func test_extendedAttributeData() { - // XAttr is supported on some platforms, but not all. For now we just test this code on Darwin. -#if FOUNDATION_FRAMEWORK - let encs : [String._Encoding] = [ - .ascii, - .nextstep, - .japaneseEUC, - .utf8, - .isoLatin1, - .nonLossyASCII, - .shiftJIS, - .isoLatin2, - .unicode, - .windowsCP1251, - .windowsCP1252, - .windowsCP1253, - .windowsCP1254, - .windowsCP1250, - .iso2022JP, - .macOSRoman, - .utf16, - .utf16BigEndian, - .utf16LittleEndian, - .utf32, - .utf32BigEndian, - .utf32LittleEndian - ] - - for encoding in encs { - // Round trip the - let packageData = extendedAttributeData(for: encoding) - XCTAssertNotNil(packageData) - - let back = encodingFromDataForExtendedAttribute(packageData!)! - XCTAssertEqual(back, encoding) - } - - XCTAssertEqual(encodingFromDataForExtendedAttribute("us-ascii;1536".data(using: .utf8)!)!.rawValue, String._Encoding.ascii.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("x-nextstep;2817".data(using: .utf8)!)!.rawValue, String._Encoding.nextstep.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("euc-jp;2336".data(using: .utf8)!)!.rawValue, String._Encoding.japaneseEUC.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("utf-8;134217984".data(using: .utf8)!)!.rawValue, String._Encoding.utf8.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("iso-8859-1;513".data(using: .utf8)!)!.rawValue, String._Encoding.isoLatin1.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute(";3071".data(using: .utf8)!)!.rawValue, String._Encoding.nonLossyASCII.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("cp932;1056".data(using: .utf8)!)!.rawValue, String._Encoding.shiftJIS.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("iso-8859-2;514".data(using: .utf8)!)!.rawValue, String._Encoding.isoLatin2.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("utf-16;256".data(using: .utf8)!)!.rawValue, String._Encoding.unicode.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("windows-1251;1282".data(using: .utf8)!)!.rawValue, String._Encoding.windowsCP1251.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("windows-1252;1280".data(using: .utf8)!)!.rawValue, String._Encoding.windowsCP1252.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("windows-1253;1283".data(using: .utf8)!)!.rawValue, String._Encoding.windowsCP1253.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("windows-1254;1284".data(using: .utf8)!)!.rawValue, String._Encoding.windowsCP1254.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("windows-1250;1281".data(using: .utf8)!)!.rawValue, String._Encoding.windowsCP1250.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("iso-2022-jp;2080".data(using: .utf8)!)!.rawValue, String._Encoding.iso2022JP.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("macintosh;0".data(using: .utf8)!)!.rawValue, String._Encoding.macOSRoman.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("utf-16;256".data(using: .utf8)!)!.rawValue, String._Encoding.utf16.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("utf-16be;268435712".data(using: .utf8)!)!.rawValue, String._Encoding.utf16BigEndian.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("utf-16le;335544576".data(using: .utf8)!)!.rawValue, String._Encoding.utf16LittleEndian.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("utf-32;201326848".data(using: .utf8)!)!.rawValue, String._Encoding.utf32.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("utf-32be;402653440".data(using: .utf8)!)!.rawValue, String._Encoding.utf32BigEndian.rawValue) - XCTAssertEqual(encodingFromDataForExtendedAttribute("utf-32le;469762304".data(using: .utf8)!)!.rawValue, String._Encoding.utf32LittleEndian.rawValue) -#endif - } - - func test_write_toFile() { - withTemporaryStringFile { existingURL, nonExistentURL in - let nonExistentPath = nonExistentURL.path() - do { - let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit" - try s.write(toFile: nonExistentPath, atomically: false, encoding: String._Encoding.ascii) - - let content = try String(contentsOfFile: nonExistentPath, encoding: String._Encoding.ascii) - - expectEqual(s, content) - } catch { - - XCTFail(error.localizedDescription) - } - } - - } - - func test_write_to() { - withTemporaryStringFile { existingURL, nonExistentURL in - let nonExistentPath = nonExistentURL.path() - do { - let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit" - try s.write(to: nonExistentURL, atomically: false, encoding: String._Encoding.ascii) - - let content = try String(contentsOfFile: nonExistentPath, encoding: String._Encoding.ascii) - - expectEqual(s, content) - } catch { - XCTFail(error.localizedDescription) - } - } - - } - - func verifyEncoding(_ encoding: String._Encoding, valid: [String], invalid: [String], file: StaticString = #file, line: UInt = #line) throws { - for string in valid { - let data = try XCTUnwrap(string.data(using: encoding), "Failed to encode \(string.debugDescription)", file: file, line: line) - XCTAssertNotNil(String(data: data, encoding: encoding), "Failed to decode \(data) (\(string.debugDescription))", file: file, line: line) - } - for string in invalid { - XCTAssertNil(string.data(using: String._Encoding.macOSRoman), "Incorrectly successfully encoded \(string.debugDescription)", file: file, line: line) - } - } - - func testISOLatin1Encoding() throws { - try verifyEncoding(.isoLatin1, valid: [ - "abcdefghijklmnopqrstuvwxyz", - "ABCDEFGHIJKLMNOPQRSTUVWXYZ", - "0123456789", - "!\"#$%&'()*+,-./", - "¡¶ÅÖæöÿ\u{0080}\u{00A0}~", - "Hello\nworld", - "Hello\r\nworld" - ], invalid: [ - "🎺", - "מ", - "âœ", - "abcd🎺efgh" - ]) - } - - func testMacRomanEncoding() throws { - try verifyEncoding(.macOSRoman, valid: [ - "abcdefghijklmnopqrstuvwxyz", - "ABCDEFGHIJKLMNOPQRSTUVWXYZ", - "0123456789", - "!\"#$%&'()*+,-./", - "ÄÇçÑû¶≠âˆ\u{00A0}÷Êˇ" - ], invalid: [ - "🎺", - "מ", - "âœ", - "abcd🎺efgh" - ]) - } -} - -// MARK: - Helper functions - -let temporaryFileContents = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." - -func withTemporaryStringFile(encoding: String._Encoding = .utf8, _ block: (_ existingURL: URL, _ nonExistentURL: URL) -> ()) { - - let rootURL = URL.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true) - let fileURL = rootURL.appending(path: "NSStringTest.txt", directoryHint: .notDirectory) - try! FileManager.default.createDirectory(at: rootURL, withIntermediateDirectories: true) - defer { - do { - try FileManager.default.removeItem(at: rootURL) - } catch { - XCTFail() - } - } - - try! temporaryFileContents.write(to: fileURL, atomically: true, encoding: encoding) - - let nonExisting = rootURL.appending(path: "-NonExist", directoryHint: .notDirectory) - block(fileURL, nonExisting) -} - -// MARK: - - -#if FOUNDATION_FRAMEWORK - -final class StringTestsStdlib: XCTestCase { - - // The most simple subclass of NSString that CoreFoundation does not know - // about. - class NonContiguousNSString : NSString { - required init(coder aDecoder: NSCoder) { - fatalError("don't call this initializer") - } - required init(itemProviderData data: Data, typeIdentifier: String) throws { - fatalError("don't call this initializer") - } - - override init() { - _value = [] - super.init() - } - - init(_ value: [UInt16]) { - _value = value - super.init() - } - -#if os(macOS) // for AppKit - required init?(pasteboardPropertyList propertyList: Any, ofType type: NSPasteboard.PasteboardType) { - fatalError("init(pasteboardPropertyList:ofType:) has not been implemented") - } -#endif - - @objc(copyWithZone:) override func copy(with zone: NSZone?) -> Any { - // Ensure that copying this string produces a class that CoreFoundation - // does not know about. - return self - } - - @objc override var length: Int { - return _value.count - } - - @objc override func character(at index: Int) -> unichar { - return _value[index] - } - - var _value: [UInt16] - } - - func test_Encodings() { - let availableEncodings: [String.Encoding] = String.availableStringEncodings - expectNotEqual(0, availableEncodings.count) - - let defaultCStringEncoding = String.defaultCStringEncoding - expectTrue(availableEncodings.contains(defaultCStringEncoding)) - - expectNotEqual("", String.localizedName(of: .utf8)) - } - - func test_NSStringEncoding() { - // Make sure NSStringEncoding and its values are type-compatible. - var enc: String.Encoding - enc = .windowsCP1250 - enc = .utf32LittleEndian - enc = .utf32BigEndian - enc = .ascii - enc = .utf8 - expectEqual(.utf8, enc) - } - - func test_NSStringEncoding_Hashable() { - let instances: [String.Encoding] = [ - .windowsCP1250, - .utf32LittleEndian, - .utf32BigEndian, - .ascii, - .utf8, - ] - checkHashable(instances, equalityOracle: { $0 == $1 }) - } - - func test_localizedStringWithFormat() { - let world: NSString = "world" - expectEqual("Hello, world!%42", String.localizedStringWithFormat( - "Hello, %@!%%%ld", world, 42)) - - expectEqual("0.5", String.init(format: "%g", locale: Locale(identifier: "en_US"), 0.5)) - expectEqual("0,5", String.init(format: "%g", locale: Locale(identifier: "uk"), 0.5)) - } - - func test_init_cString_encoding() { - "foo, a basmati bar!".withCString { - expectEqual("foo, a basmati bar!", - String(cString: $0, encoding: String.defaultCStringEncoding)) - } - } - - func test_init_utf8String() { - let s = "foo ã‚ã„ã†" - let up = UnsafeMutablePointer.allocate(capacity: 100) - var i = 0 - for b in s.utf8 { - up[i] = b - i += 1 - } - up[i] = 0 - let cstr = UnsafeMutableRawPointer(up) - .bindMemory(to: CChar.self, capacity: 100) - expectEqual(s, String(utf8String: cstr)) - up.deallocate() - } - - func test_canBeConvertedToEncoding() { - expectTrue("foo".canBeConverted(to: .ascii)) - expectFalse("ã‚ã„ã†".canBeConverted(to: .ascii)) - } - - func test_capitalized() { - expectEqual("Foo Foo Foo Foo", "foo Foo fOO FOO".capitalized) - expectEqual("Жжж", "жжж".capitalized) - } - - func test_localizedCapitalized() { - expectEqual( - "Foo Foo Foo Foo", - "foo Foo fOO FOO".capitalized(with: Locale(identifier: "en"))) - expectEqual("Жжж", "жжж".capitalized(with: Locale(identifier: "en"))) - - // - // Special casing. - // - - // U+0069 LATIN SMALL LETTER I - // to upper case: - // U+0049 LATIN CAPITAL LETTER I - expectEqual("Iii Iii", "iii III".capitalized(with: Locale(identifier: "en"))) - - // U+0069 LATIN SMALL LETTER I - // to upper case in Turkish locale: - // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE - expectEqual("\u{0130}ii Iıı", "iii III".capitalized(with: Locale(identifier: "tr"))) - } - - /// Checks that executing the operation in the locale with the given - /// `localeID` (or unlocalized if `localeID` is `nil`) gives - /// the expected result, and that executing the operation with a nil - /// locale gives the same result as explicitly passing the system - /// locale. - /// - /// - Parameter expected: the expected result when the operation is - /// executed in the given localeID - func expectLocalizedEquality( - _ expected: String, - _ op: (_: Locale?) -> String, - _ localeID: String? = nil, - _ message: @autoclosure () -> String = "", - showFrame: Bool = true, - file: String = #file, line: UInt = #line - ) { - - let locale = localeID.map { - Locale(identifier: $0) - } ?? nil - - expectEqual( - expected, op(locale), - message()) - } - - func test_capitalizedString() { - expectLocalizedEquality( - "Foo Foo Foo Foo", - { loc in "foo Foo fOO FOO".capitalized(with: loc) }) - - expectLocalizedEquality("Жжж", { loc in "жжж".capitalized(with: loc) }) - - expectEqual( - "Foo Foo Foo Foo", - "foo Foo fOO FOO".capitalized(with: nil)) - expectEqual("Жжж", "жжж".capitalized(with: nil)) - - // - // Special casing. - // - - // U+0069 LATIN SMALL LETTER I - // to upper case: - // U+0049 LATIN CAPITAL LETTER I - expectLocalizedEquality( - "Iii Iii", - { loc in "iii III".capitalized(with: loc) }, "en") - - // U+0069 LATIN SMALL LETTER I - // to upper case in Turkish locale: - // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE - expectLocalizedEquality( - "İii Iıı", - { loc in "iii III".capitalized(with: loc) }, "tr") - } - - func test_caseInsensitiveCompare() { - expectEqual(ComparisonResult.orderedSame, - "abCD".caseInsensitiveCompare("AbCd")) - expectEqual(ComparisonResult.orderedAscending, - "abCD".caseInsensitiveCompare("AbCdE")) - - expectEqual(ComparisonResult.orderedSame, - "абвг".caseInsensitiveCompare("ÐбВг")) - expectEqual(ComparisonResult.orderedAscending, - "абВГ".caseInsensitiveCompare("ÐбВгД")) - } - - func test_commonPrefix() { - expectEqual("ab", - "abcd".commonPrefix(with: "abdc", options: [])) - expectEqual("abC", - "abCd".commonPrefix(with: "abce", options: .caseInsensitive)) - - expectEqual("аб", - "абвг".commonPrefix(with: "абгв", options: [])) - expectEqual("абВ", - "абВг".commonPrefix(with: "абвд", options: .caseInsensitive)) - } - - func test_compare() { - expectEqual(ComparisonResult.orderedSame, - "abc".compare("abc")) - expectEqual(ComparisonResult.orderedAscending, - "абв".compare("где")) - - expectEqual(ComparisonResult.orderedSame, - "abc".compare("abC", options: .caseInsensitive)) - expectEqual(ComparisonResult.orderedSame, - "абв".compare("абВ", options: .caseInsensitive)) - - do { - let s = "abcd" - let r = s.index(after: s.startIndex).., sentenceRange: Range, stop: inout Bool) - in - tags.append(tag) - tokens.append(String(s[tokenRange])) - sentences.append(String(s[sentenceRange])) - if tags.count == 3 { - stop = true - } - } - expectEqual([ - NSLinguisticTag.word.rawValue, - NSLinguisticTag.whitespace.rawValue, - NSLinguisticTag.word.rawValue - ], tags) - expectEqual(["ГлокаÑ", " ", "куздра"], tokens) - let sentence = String(s[startIndex.., - enclosingRange: Range, stop: inout Bool) - in - substrings.append(substring!) - expectEqual(substring, String(s[substringRange])) - expectEqual(substring, String(s[enclosingRange])) - } - expectEqual(["\u{304b}\u{3099}", "ãŠ", "☺ï¸", "😀"], substrings) - } - do { - var substrings: [String] = [] - s.enumerateSubstrings(in: startIndex.., - enclosingRange: Range, stop: inout Bool) - in - XCTAssertNil(substring_) - let substring = s[substringRange] - substrings.append(String(substring)) - expectEqual(substring, s[enclosingRange]) - } - expectEqual(["\u{304b}\u{3099}", "ãŠ", "☺ï¸", "😀"], substrings) - } - } - - func test_fastestEncoding() { - let availableEncodings: [String.Encoding] = String.availableStringEncodings - expectTrue(availableEncodings.contains("abc".fastestEncoding)) - } - - func test_getBytes() { - let s = "abc абв def где gh жз zzz" - let startIndex = s.index(s.startIndex, offsetBy: 8) - let endIndex = s.index(s.startIndex, offsetBy: 22) - do { - // 'maxLength' is limiting. - let bufferLength = 100 - var expectedStr: [UInt8] = Array("def где ".utf8) - while (expectedStr.count != bufferLength) { - expectedStr.append(0xff) - } - var buffer = [UInt8](repeating: 0xff, count: bufferLength) - var usedLength = 0 - var remainingRange = startIndex..] = [] - let scheme = NSLinguisticTagScheme.tokenType - let tags = s.linguisticTags(in: startIndex.. NFKD normalization as implemented by - 'precomposedStringWithCompatibilityMapping:' is not idempotent - - expectEqual("\u{30c0}クテン", - "\u{ff80}\u{ff9e}クテï¾".precomposedStringWithCompatibilityMapping) - */ - expectEqual("ffi", "\u{fb03}".precomposedStringWithCompatibilityMapping) - } - - func test_propertyList() { - expectEqual(["foo", "bar"], - "(\"foo\", \"bar\")".propertyList() as! [String]) - } - - func test_propertyListFromStringsFileFormat() { - expectEqual(["foo": "bar", "baz": "baz"], - "/* comment */\n\"foo\" = \"bar\";\n\"baz\";" - .propertyListFromStringsFileFormat() as Dictionary) - } - - func test_rangeOfCharacterFrom() { - do { - let charset = CharacterSet(charactersIn: "абв") - do { - let s = "Ð“Ð»Ð¾ÐºÐ°Ñ ÐºÑƒÐ·Ð´Ñ€Ð°" - let r = s.rangeOfCharacter(from: charset)! - expectEqual(s.index(s.startIndex, offsetBy: 4), r.lowerBound) - expectEqual(s.index(s.startIndex, offsetBy: 5), r.upperBound) - } - do { - XCTAssertNil("клмн".rangeOfCharacter(from: charset)) - } - do { - let s = "абвклмнабвклмн" - let r = s.rangeOfCharacter(from: charset, - options: .backwards)! - expectEqual(s.index(s.startIndex, offsetBy: 9), r.lowerBound) - expectEqual(s.index(s.startIndex, offsetBy: 10), r.upperBound) - } - do { - let s = "абвклмнабв" - let r = s.rangeOfCharacter(from: charset, - range: s.index(s.startIndex, offsetBy: 3)..( - _ string: S, _ maybeRange: Range? - ) -> Range? where S.Index == String.Index { - guard let range = maybeRange else { return nil } - - return string.distance(from: string.startIndex, to: range.lowerBound) ..< string.distance(from: string.startIndex, to: range.upperBound) - } - - func test_range() { - do { - let s = "" - XCTAssertNil(s.range(of: "")) - XCTAssertNil(s.range(of: "abc")) - } - do { - let s = "abc" - XCTAssertNil(s.range(of: "")) - XCTAssertNil(s.range(of: "def")) - expectEqual(0..<3, toIntRange(s, s.range(of: "abc"))) - } - do { - let s = "ã•\u{3099}ã—\u{3099}ã™\u{3099}ã›\u{3099}ã\u{3099}" - expectEqual(2..<3, toIntRange(s, s.range(of: "ã™\u{3099}"))) - expectEqual(2..<3, toIntRange(s, s.range(of: "\u{305a}"))) - - XCTAssertNil(s.range(of: "\u{3099}ã™")) - XCTAssertNil(s.range(of: "ã™")) - - XCTAssertNil(s.range(of: "\u{3099}")) - expectEqual("\u{3099}", s[s.range(of: "\u{3099}", options: .literal)!]) - } - do { - let s = "а\u{0301}б\u{0301}в\u{0301}г\u{0301}" - expectEqual(0..<1, toIntRange(s, s.range(of: "а\u{0301}"))) - expectEqual(1..<2, toIntRange(s, s.range(of: "б\u{0301}"))) - - XCTAssertNil(s.range(of: "б")) - XCTAssertNil(s.range(of: "\u{0301}б")) - - XCTAssertNil(s.range(of: "\u{0301}")) - expectEqual("\u{0301}", s[s.range(of: "\u{0301}", options: .literal)!]) - } - } - - func test_contains() { - expectFalse("".contains("")) - expectFalse("".contains("a")) - expectFalse("a".contains("")) - expectFalse("a".contains("b")) - expectTrue("a".contains("a")) - expectFalse("a".contains("A")) - expectFalse("A".contains("a")) - expectFalse("a".contains("a\u{0301}")) - expectTrue("a\u{0301}".contains("a\u{0301}")) - expectFalse("a\u{0301}".contains("a")) - expectFalse("a\u{0301}".contains("\u{0301}")) // Update to match stdlib's `firstRange` and `contains` result - expectFalse("a".contains("\u{0301}")) - - expectFalse("i".contains("I")) - expectFalse("I".contains("i")) - expectFalse("\u{0130}".contains("i")) - expectFalse("i".contains("\u{0130}")) - expectFalse("\u{0130}".contains("ı")) - } - - func test_localizedCaseInsensitiveContains() { - let en = Locale(identifier: "en") - expectFalse("".localizedCaseInsensitiveContains("", locale: en)) - expectFalse("".localizedCaseInsensitiveContains("a", locale: en)) - expectFalse("a".localizedCaseInsensitiveContains("", locale: en)) - expectFalse("a".localizedCaseInsensitiveContains("b", locale: en)) - expectTrue("a".localizedCaseInsensitiveContains("a", locale: en)) - expectTrue("a".localizedCaseInsensitiveContains("A", locale: en)) - expectTrue("A".localizedCaseInsensitiveContains("a", locale: en)) - expectFalse("a".localizedCaseInsensitiveContains("a\u{0301}", locale: en)) - expectTrue("a\u{0301}".localizedCaseInsensitiveContains("a\u{0301}", locale: en)) - expectFalse("a\u{0301}".localizedCaseInsensitiveContains("a", locale: en)) - expectTrue("a\u{0301}".localizedCaseInsensitiveContains("\u{0301}", locale: en)) - expectFalse("a".localizedCaseInsensitiveContains("\u{0301}", locale: en)) - - expectTrue("i".localizedCaseInsensitiveContains("I", locale: en)) - expectTrue("I".localizedCaseInsensitiveContains("i", locale: en)) - expectFalse("\u{0130}".localizedCaseInsensitiveContains("i", locale: en)) - expectFalse("i".localizedCaseInsensitiveContains("\u{0130}", locale: en)) - - expectFalse("\u{0130}".localizedCaseInsensitiveContains("ı", locale: Locale(identifier: "tr"))) - } - - func test_localizedStandardContains() { - let en = Locale(identifier: "en") - expectFalse("".localizedStandardContains("", locale: en)) - expectFalse("".localizedStandardContains("a", locale: en)) - expectFalse("a".localizedStandardContains("", locale: en)) - expectFalse("a".localizedStandardContains("b", locale: en)) - expectTrue("a".localizedStandardContains("a", locale: en)) - expectTrue("a".localizedStandardContains("A", locale: en)) - expectTrue("A".localizedStandardContains("a", locale: en)) - expectTrue("a".localizedStandardContains("a\u{0301}", locale: en)) - expectTrue("a\u{0301}".localizedStandardContains("a\u{0301}", locale: en)) - expectTrue("a\u{0301}".localizedStandardContains("a", locale: en)) - expectTrue("a\u{0301}".localizedStandardContains("\u{0301}", locale: en)) - expectFalse("a".localizedStandardContains("\u{0301}", locale: en)) - - expectTrue("i".localizedStandardContains("I", locale: en)) - expectTrue("I".localizedStandardContains("i", locale: en)) - expectTrue("\u{0130}".localizedStandardContains("i", locale: en)) - expectTrue("i".localizedStandardContains("\u{0130}", locale: en)) - - expectTrue("\u{0130}".localizedStandardContains("ı", locale: Locale(identifier: "tr"))) - } - - func test_localizedStandardRange() { - func rangeOf(_ string: String, _ substring: String, locale: Locale) -> Range? { - return toIntRange( - string, string.localizedStandardRange(of: substring, locale: locale)) - } - - let en = Locale(identifier: "en") - - XCTAssertNil(rangeOf("", "", locale: en)) - XCTAssertNil(rangeOf("", "a", locale: en)) - XCTAssertNil(rangeOf("a", "", locale: en)) - XCTAssertNil(rangeOf("a", "b", locale: en)) - expectEqual(0..<1, rangeOf("a", "a", locale: en)) - expectEqual(0..<1, rangeOf("a", "A", locale: en)) - expectEqual(0..<1, rangeOf("A", "a", locale: en)) - expectEqual(0..<1, rangeOf("a", "a\u{0301}", locale: en)) - expectEqual(0..<1, rangeOf("a\u{0301}", "a\u{0301}", locale: en)) - expectEqual(0..<1, rangeOf("a\u{0301}", "a", locale: en)) - do { - // FIXME: Indices that don't correspond to grapheme cluster boundaries. - let s = "a\u{0301}" - expectEqual( - "\u{0301}", s[s.localizedStandardRange(of: "\u{0301}", locale: en)!]) - } - XCTAssertNil(rangeOf("a", "\u{0301}", locale: en)) - - expectEqual(0..<1, rangeOf("i", "I", locale: en)) - expectEqual(0..<1, rangeOf("I", "i", locale: en)) - expectEqual(0..<1, rangeOf("\u{0130}", "i", locale: en)) - expectEqual(0..<1, rangeOf("i", "\u{0130}", locale: en)) - - - let tr = Locale(identifier: "tr") - expectEqual(0..<1, rangeOf("\u{0130}", "ı", locale: tr)) - } - - func test_smallestEncoding() { - let availableEncodings: [String.Encoding] = String.availableStringEncodings - expectTrue(availableEncodings.contains("abc".smallestEncoding)) - } - - func test_addingPercentEncoding() { - expectEqual( - "abcd1234", - "abcd1234".addingPercentEncoding(withAllowedCharacters: .alphanumerics)) - expectEqual( - "abcd%20%D0%B0%D0%B1%D0%B2%D0%B3", - "abcd абвг".addingPercentEncoding(withAllowedCharacters: .alphanumerics)) - } - - func test_appendingFormat() { - expectEqual("", "".appendingFormat("")) - expectEqual("a", "a".appendingFormat("")) - expectEqual( - "abc абв \u{0001F60A}", - "abc абв \u{0001F60A}".appendingFormat("")) - - let formatArg: NSString = "привет мир \u{0001F60A}" - expectEqual( - "abc абв \u{0001F60A}def привет мир \u{0001F60A} 42", - "abc абв \u{0001F60A}" - .appendingFormat("def %@ %ld", formatArg, 42)) - } - - func test_appending() { - expectEqual("", "".appending("")) - expectEqual("a", "a".appending("")) - expectEqual("a", "".appending("a")) - expectEqual("ã•\u{3099}", "ã•".appending("\u{3099}")) - } - - func test_folding() { - - func fwo( - _ s: String, _ options: String.CompareOptions - ) -> (Locale?) -> String { - return { loc in s.folding(options: options, locale: loc) } - } - - expectLocalizedEquality("abcd", fwo("abCD", .caseInsensitive), "en") - - // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE - // to lower case: - // U+0069 LATIN SMALL LETTER I - // U+0307 COMBINING DOT ABOVE - expectLocalizedEquality( - "\u{0069}\u{0307}", fwo("\u{0130}", .caseInsensitive), "en") - - // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE - // to lower case in Turkish locale: - // U+0069 LATIN SMALL LETTER I - expectLocalizedEquality( - "\u{0069}", fwo("\u{0130}", .caseInsensitive), "tr") - - expectLocalizedEquality( - "example123", fwo("exï½ï½ï½ï½Œï½…123", .widthInsensitive), "en") - } - - func test_padding() { - expectEqual( - "abc абв \u{0001F60A}", - "abc абв \u{0001F60A}".padding( - toLength: 10, withPad: "XYZ", startingAt: 0)) - expectEqual( - "abc абв \u{0001F60A}XYZXY", - "abc абв \u{0001F60A}".padding( - toLength: 15, withPad: "XYZ", startingAt: 0)) - expectEqual( - "abc абв \u{0001F60A}YZXYZ", - "abc абв \u{0001F60A}".padding( - toLength: 15, withPad: "XYZ", startingAt: 1)) - } - - func test_replacingCharacters() { - do { - let empty = "" - expectEqual("", empty.replacingCharacters( - in: empty.startIndex.. Range { - return index(startIndex, offsetBy: fromStart) ..< - index(endIndex, offsetBy: fromEnd) - } - subscript(fromStart: Int, fromEnd: Int) -> SubSequence { - return self[range(fromStart: fromStart, fromEnd: fromEnd)] - } -} - -final class StdlibSubstringTests: XCTestCase { - - func test_range_of_NilRange() { - let ss = "aabcdd"[1, -1] - let range = ss.range(of: "bc") - expectEqual("bc", range.map { ss[$0] }) - } - - func test_range_of_NonNilRange() { - let s = "aabcdd" - let ss = s[1, -1] - let searchRange = s.range(fromStart: 2, fromEnd: -2) - let range = ss.range(of: "bc", range: searchRange) - expectEqual("bc", range.map { ss[$0] }) - } - - func test_rangeOfCharacter() { - let ss = "__hello__"[2, -2] - let range = ss.rangeOfCharacter(from: CharacterSet.alphanumerics) - expectEqual("h", range.map { ss[$0] }) - } - - func test_compare_optionsNilRange() { - let needle = "hello" - let haystack = "__hello__"[2, -2] - expectEqual(.orderedSame, haystack.compare(needle)) - } - - func test_compare_optionsNonNilRange() { - let needle = "hello" - let haystack = "__hello__" - let range = haystack.range(fromStart: 2, fromEnd: -2) - expectEqual(.orderedSame, haystack[range].compare(needle, range: range)) - } - - func test_replacingCharacters() { - let s = "__hello, world" - let range = s.range(fromStart: 2, fromEnd: -7) - let expected = "__goodbye, world" - let replacement = "goodbye" - expectEqual(expected, - s.replacingCharacters(in: range, with: replacement)) - expectEqual(expected[2, 0], - s[2, 0].replacingCharacters(in: range, with: replacement)) - - expectEqual(replacement, - s.replacingCharacters(in: s.startIndex..., with: replacement)) - expectEqual(replacement, - s.replacingCharacters(in: .. Data { + let head = #"{"nestedArray":["# + let tail = #"]}"# + var json = "" + for _ in 0...depth { + json = head + json + tail + } + return Data(json.utf8) + } + + func test_deepType() { + var theThing = Thing() + for depth in 0..<(JSONWriter.maximumRecursionDepth / 2 + 1) { + XCTAssertEqual(theThing.depth, depth, "Expected depth: \(depth)") + theThing = Thing([theThing]) + } + } + + func testDecoding() { + defer { fflush(stdout) } + + let decoder = JSONDecoder() + for depth in 0..<(JSONScanner.maximumRecursionDepth / 2 + 1) { + let json = _generateJSON(depth: depth) + do { + let decoded = try decoder.decode(Thing.self, from: json) + XCTAssertEqual(decoded.depth, depth, "Unexpected object. Depth: \(depth)") + print("✅ Decoding succeeded; Depth: \(depth)") + } catch { + print("⌠Decoding error is thrown at depth \(depth): \(error)") + break + } + } + } + + func testEncoding() { + defer { fflush(stdout) } + + let encoder = JSONEncoder() + var theThing = Thing() + for depth in 0..<(JSONWriter.maximumRecursionDepth / 2 + 1) { + let expectedJSON = _generateJSON(depth: depth) + do { + let encoded = try encoder.encode(theThing) + XCTAssertEqual(expectedJSON, encoded, "Unexpected JSON; Depth: \(depth)") + print("✅ Encoding succeeded; Depth: \(depth)") + theThing = Thing([theThing]) + } catch { + print("⌠Encoding error is thrown at depth \(depth): \(error)") + break + } + } + } +} diff --git a/Tests/FoundationEssentialsTests/URLTests.swift b/Tests/FoundationEssentialsTests/URLTests.swift deleted file mode 100644 index f940d104a..000000000 --- a/Tests/FoundationEssentialsTests/URLTests.swift +++ /dev/null @@ -1,1574 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - - -#if canImport(TestSupport) -import TestSupport -#endif // canImport(TestSupport) - -#if canImport(FoundationEssentials) -@testable import FoundationEssentials -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#endif - -private func checkBehavior(_ result: T, new: T, old: T, file: StaticString = #filePath, line: UInt = #line) { - #if FOUNDATION_FRAMEWORK - if foundation_swift_url_enabled() { - XCTAssertEqual(result, new, file: file, line: line) - } else { - XCTAssertEqual(result, old, file: file, line: line) - } - #else - XCTAssertEqual(result, new, file: file, line: line) - #endif -} - -final class URLTests : XCTestCase { - - func testURLBasics() throws { - let string = "https://username:password@example.com:80/path/path?query=value&q=v#fragment" - let url = try XCTUnwrap(URL(string: string)) - - XCTAssertEqual(url.scheme, "https") - XCTAssertEqual(url.user(), "username") - XCTAssertEqual(url.password(), "password") - XCTAssertEqual(url.host(), "example.com") - XCTAssertEqual(url.port, 80) - XCTAssertEqual(url.path(), "/path/path") - XCTAssertEqual(url.relativePath, "/path/path") - XCTAssertEqual(url.query(), "query=value&q=v") - XCTAssertEqual(url.fragment(), "fragment") - XCTAssertEqual(url.absoluteString, string) - XCTAssertEqual(url.absoluteURL, url) - XCTAssertEqual(url.relativeString, string) - XCTAssertNil(url.baseURL) - - let baseString = "https://user:pass@base.example.com:8080/base/" - let baseURL = try XCTUnwrap(URL(string: baseString)) - let absoluteURLWithBase = try XCTUnwrap(URL(string: string, relativeTo: baseURL)) - - // The URL is already absolute, so .baseURL is nil, and the components are unchanged - XCTAssertEqual(absoluteURLWithBase.scheme, "https") - XCTAssertEqual(absoluteURLWithBase.user(), "username") - XCTAssertEqual(absoluteURLWithBase.password(), "password") - XCTAssertEqual(absoluteURLWithBase.host(), "example.com") - XCTAssertEqual(absoluteURLWithBase.port, 80) - XCTAssertEqual(absoluteURLWithBase.path(), "/path/path") - XCTAssertEqual(absoluteURLWithBase.relativePath, "/path/path") - XCTAssertEqual(absoluteURLWithBase.query(), "query=value&q=v") - XCTAssertEqual(absoluteURLWithBase.fragment(), "fragment") - XCTAssertEqual(absoluteURLWithBase.absoluteString, string) - XCTAssertEqual(absoluteURLWithBase.absoluteURL, url) - XCTAssertEqual(absoluteURLWithBase.relativeString, string) - XCTAssertNil(absoluteURLWithBase.baseURL) - XCTAssertEqual(absoluteURLWithBase.absoluteURL, url) - - let relativeString = "relative/path?query#fragment" - let relativeURL = try XCTUnwrap(URL(string: relativeString)) - - XCTAssertNil(relativeURL.scheme) - XCTAssertNil(relativeURL.user()) - XCTAssertNil(relativeURL.password()) - XCTAssertNil(relativeURL.host()) - XCTAssertNil(relativeURL.port) - XCTAssertEqual(relativeURL.path(), "relative/path") - XCTAssertEqual(relativeURL.relativePath, "relative/path") - XCTAssertEqual(relativeURL.query(), "query") - XCTAssertEqual(relativeURL.fragment(), "fragment") - XCTAssertEqual(relativeURL.absoluteString, relativeString) - XCTAssertEqual(relativeURL.absoluteURL, relativeURL) - XCTAssertEqual(relativeURL.relativeString, relativeString) - XCTAssertNil(relativeURL.baseURL) - - let relativeURLWithBase = try XCTUnwrap(URL(string: relativeString, relativeTo: baseURL)) - - XCTAssertEqual(relativeURLWithBase.scheme, baseURL.scheme) - XCTAssertEqual(relativeURLWithBase.user(), baseURL.user()) - XCTAssertEqual(relativeURLWithBase.password(), baseURL.password()) - XCTAssertEqual(relativeURLWithBase.host(), baseURL.host()) - XCTAssertEqual(relativeURLWithBase.port, baseURL.port) - XCTAssertEqual(relativeURLWithBase.path(), "/base/relative/path") - XCTAssertEqual(relativeURLWithBase.relativePath, "relative/path") - XCTAssertEqual(relativeURLWithBase.query(), "query") - XCTAssertEqual(relativeURLWithBase.fragment(), "fragment") - XCTAssertEqual(relativeURLWithBase.absoluteString, "https://user:pass@base.example.com:8080/base/relative/path?query#fragment") - XCTAssertEqual(relativeURLWithBase.absoluteURL, URL(string: "https://user:pass@base.example.com:8080/base/relative/path?query#fragment")) - XCTAssertEqual(relativeURLWithBase.relativeString, relativeString) - XCTAssertEqual(relativeURLWithBase.baseURL, baseURL) - } - - func testURLResolvingAgainstBase() throws { - let base = URL(string: "http://a/b/c/d;p?q") - let tests = [ - // RFC 3986 5.4.1. Normal Examples - "g:h" : "g:h", - "g" : "http://a/b/c/g", - "./g" : "http://a/b/c/g", - "g/" : "http://a/b/c/g/", - "/g" : "http://a/g", - "//g" : "http://g", - "?y" : "http://a/b/c/d;p?y", - "g?y" : "http://a/b/c/g?y", - "#s" : "http://a/b/c/d;p?q#s", - "g#s" : "http://a/b/c/g#s", - "g?y#s" : "http://a/b/c/g?y#s", - ";x" : "http://a/b/c/;x", - "g;x" : "http://a/b/c/g;x", - "g;x?y#s" : "http://a/b/c/g;x?y#s", - "" : "http://a/b/c/d;p?q", - "." : "http://a/b/c/", - "./" : "http://a/b/c/", - ".." : "http://a/b/", - "../" : "http://a/b/", - "../g" : "http://a/b/g", - "../.." : "http://a/", - "../../" : "http://a/", - "../../g" : "http://a/g", - - // RFC 3986 5.4.1. Abnormal Examples - "../../../g" : "http://a/g", - "../../../../g" : "http://a/g", - "/./g" : "http://a/g", - "/../g" : "http://a/g", - "g." : "http://a/b/c/g.", - ".g" : "http://a/b/c/.g", - "g.." : "http://a/b/c/g..", - "..g" : "http://a/b/c/..g", - - "./../g" : "http://a/b/g", - "./g/." : "http://a/b/c/g/", - "g/./h" : "http://a/b/c/g/h", - "g/../h" : "http://a/b/c/h", - "g;x=1/./y" : "http://a/b/c/g;x=1/y", - "g;x=1/../y" : "http://a/b/c/y", - - "g?y/./x" : "http://a/b/c/g?y/./x", - "g?y/../x" : "http://a/b/c/g?y/../x", - "g#s/./x" : "http://a/b/c/g#s/./x", - "g#s/../x" : "http://a/b/c/g#s/../x", - - "http:g" : "http:g", // For strict parsers - ] - - let testsFailingWithoutSwiftURL = Set([ - "", - "../../../g", - "../../../../g", - "/./g", - "/../g", - ]) - - for test in tests { - if !foundation_swift_url_enabled(), testsFailingWithoutSwiftURL.contains(test.key) { - continue - } - - let url = URL(stringOrEmpty: test.key, relativeTo: base) - XCTAssertNotNil(url, "Got nil url for string: \(test.key)") - XCTAssertEqual(url?.absoluteString, test.value, "Failed test for string: \(test.key)") - } - } - - func testURLPathAPIsResolveAgainstBase() throws { - try XCTSkipIf(!foundation_swift_url_enabled()) - // Borrowing the same test cases from RFC 3986, but checking paths - let base = URL(string: "http://a/b/c/d;p?q") - let tests = [ - // RFC 3986 5.4.1. Normal Examples - "g:h" : "h", - "g" : "/b/c/g", - "./g" : "/b/c/g", - "g/" : "/b/c/g/", - "/g" : "/g", - "//g" : "", - "?y" : "/b/c/d;p", - "g?y" : "/b/c/g", - "#s" : "/b/c/d;p", - "g#s" : "/b/c/g", - "g?y#s" : "/b/c/g", - ";x" : "/b/c/;x", - "g;x" : "/b/c/g;x", - "g;x?y#s" : "/b/c/g;x", - "" : "/b/c/d;p", - "." : "/b/c/", - "./" : "/b/c/", - ".." : "/b/", - "../" : "/b/", - "../g" : "/b/g", - "../.." : "/", - "../../" : "/", - "../../g" : "/g", - - // RFC 3986 5.4.1. Abnormal Examples - "../../../g" : "/g", - "../../../../g" : "/g", - "/./g" : "/g", - "/../g" : "/g", - "g." : "/b/c/g.", - ".g" : "/b/c/.g", - "g.." : "/b/c/g..", - "..g" : "/b/c/..g", - - "./../g" : "/b/g", - "./g/." : "/b/c/g/", - "g/./h" : "/b/c/g/h", - "g/../h" : "/b/c/h", - "g;x=1/./y" : "/b/c/g;x=1/y", - "g;x=1/../y" : "/b/c/y", - - "g?y/./x" : "/b/c/g", - "g?y/../x" : "/b/c/g", - "g#s/./x" : "/b/c/g", - "g#s/../x" : "/b/c/g", - - "http:g" : "g", // For strict parsers - ] - for test in tests { - let url = URL(stringOrEmpty: test.key, relativeTo: base)! - XCTAssertEqual(url.absolutePath(), test.value) - if (url.hasDirectoryPath && url.absolutePath().count > 1) { - // The trailing slash is stripped in .path for file system compatibility - XCTAssertEqual(String(url.absolutePath().dropLast()), url.path) - } else { - XCTAssertEqual(url.absolutePath(), url.path) - } - } - } - - func testURLPathComponentsPercentEncodedSlash() throws { - try XCTSkipIf(!foundation_swift_url_enabled()) - - var url = try XCTUnwrap(URL(string: "https://example.com/https%3A%2F%2Fexample.com")) - XCTAssertEqual(url.pathComponents, ["/", "https://example.com"]) - - url = try XCTUnwrap(URL(string: "https://example.com/https:%2f%2fexample.com")) - XCTAssertEqual(url.pathComponents, ["/", "https://example.com"]) - - url = try XCTUnwrap(URL(string: "https://example.com/https:%2F%2Fexample.com%2Fpath")) - XCTAssertEqual(url.pathComponents, ["/", "https://example.com/path"]) - - url = try XCTUnwrap(URL(string: "https://example.com/https:%2F%2Fexample.com/path")) - XCTAssertEqual(url.pathComponents, ["/", "https://example.com", "path"]) - - url = try XCTUnwrap(URL(string: "https://example.com/https%3A%2F%2Fexample.com%2Fpath%3Fquery%23fragment")) - XCTAssertEqual(url.pathComponents, ["/", "https://example.com/path?query#fragment"]) - - url = try XCTUnwrap(URL(string: "https://example.com/https%3A%2F%2Fexample.com%2Fpath?query#fragment")) - XCTAssertEqual(url.pathComponents, ["/", "https://example.com/path"]) - } - - func testURLRootlessPath() throws { - try XCTSkipIf(!foundation_swift_url_enabled()) - - let paths = ["", "path"] - let queries = [nil, "query"] - let fragments = [nil, "fragment"] - - for path in paths { - for query in queries { - for fragment in fragments { - let queryString = query != nil ? "?\(query!)" : "" - let fragmentString = fragment != nil ? "#\(fragment!)" : "" - let urlString = "scheme:\(path)\(queryString)\(fragmentString)" - let url = try XCTUnwrap(URL(string: urlString)) - XCTAssertEqual(url.absoluteString, urlString) - XCTAssertEqual(url.scheme, "scheme") - XCTAssertNil(url.host()) - XCTAssertEqual(url.path(), path) - XCTAssertEqual(url.query(), query) - XCTAssertEqual(url.fragment(), fragment) - } - } - } - } - - func testURLNonSequentialIPLiteralAndPort() { - let urlString = "https://[fe80::3221:5634:6544]invalid:433/" - let url = URL(string: urlString) - XCTAssertNil(url) - } - - func testURLFilePathInitializer() throws { - let directory = URL(filePath: "/some/directory", directoryHint: .isDirectory) - XCTAssertTrue(directory.hasDirectoryPath) - - let notDirectory = URL(filePath: "/some/file", directoryHint: .notDirectory) - XCTAssertFalse(notDirectory.hasDirectoryPath) - - // directoryHint defaults to .inferFromPath - let directoryAgain = URL(filePath: "/some/directory.framework/") - XCTAssertTrue(directoryAgain.hasDirectoryPath) - - let notDirectoryAgain = URL(filePath: "/some/file") - XCTAssertFalse(notDirectoryAgain.hasDirectoryPath) - - // Test .checkFileSystem by creating a directory - let tempDirectory = URL.temporaryDirectory - let urlBeforeCreation = URL(filePath: "\(tempDirectory.path)/tmp-dir", directoryHint: .checkFileSystem) - XCTAssertFalse(urlBeforeCreation.hasDirectoryPath) - - try FileManager.default.createDirectory( - at: URL(filePath: "\(tempDirectory.path)/tmp-dir"), - withIntermediateDirectories: true - ) - let urlAfterCreation = URL(filePath: "\(tempDirectory.path)/tmp-dir", directoryHint: .checkFileSystem) - XCTAssertTrue(urlAfterCreation.hasDirectoryPath) - try FileManager.default.removeItem(at: URL(filePath: "\(tempDirectory.path)/tmp-dir")) - } - - #if os(Windows) - func testURLWindowsDriveLetterPath() throws { - var url = URL(filePath: #"C:\test\path"#, directoryHint: .notDirectory) - // .absoluteString and .path() use the RFC 8089 URL path - XCTAssertEqual(url.absoluteString, "file:///C:/test/path") - XCTAssertEqual(url.path(), "/C:/test/path") - // .path and .fileSystemPath() strip the leading slash - XCTAssertEqual(url.path, "C:/test/path") - XCTAssertEqual(url.fileSystemPath(), "C:/test/path") - - url = URL(filePath: #"C:\"#, directoryHint: .isDirectory) - XCTAssertEqual(url.absoluteString, "file:///C:/") - XCTAssertEqual(url.path(), "/C:/") - XCTAssertEqual(url.path, "C:/") - XCTAssertEqual(url.fileSystemPath(), "C:/") - - url = URL(filePath: #"C:\\\"#, directoryHint: .isDirectory) - XCTAssertEqual(url.absoluteString, "file:///C:///") - XCTAssertEqual(url.path(), "/C:///") - XCTAssertEqual(url.path, "C:/") - XCTAssertEqual(url.fileSystemPath(), "C:/") - - url = URL(filePath: #"\C:\"#, directoryHint: .isDirectory) - XCTAssertEqual(url.absoluteString, "file:///C:/") - XCTAssertEqual(url.path(), "/C:/") - XCTAssertEqual(url.path, "C:/") - XCTAssertEqual(url.fileSystemPath(), "C:/") - - let base = URL(filePath: #"\d:\path\"#, directoryHint: .isDirectory) - url = URL(filePath: #"%43:\fake\letter"#, directoryHint: .notDirectory, relativeTo: base) - // ":" is encoded to "%3A" in the first path segment so it's not mistaken as the scheme separator - XCTAssertEqual(url.relativeString, "%2543%3A/fake/letter") - XCTAssertEqual(url.path(), "/d:/path/%2543%3A/fake/letter") - XCTAssertEqual(url.path, "d:/path/%43:/fake/letter") - XCTAssertEqual(url.fileSystemPath(), "d:/path/%43:/fake/letter") - - let cwd = URL.currentDirectory() - var iter = cwd.path().utf8.makeIterator() - if iter.next() == ._slash, - let driveLetter = iter.next(), driveLetter.isLetter!, - iter.next() == ._colon { - let path = #"\\?\"# + "\(Unicode.Scalar(driveLetter))" + #":\"# - url = URL(filePath: path, directoryHint: .isDirectory) - XCTAssertEqual(url.path.last, "/") - XCTAssertEqual(url.fileSystemPath().last, "/") - } - } - #endif - - func testURLFilePathRelativeToBase() throws { - try FileManagerPlayground { - Directory("dir") { - "Foo" - "Bar" - } - }.test { - let currentDirectoryPath = $0.currentDirectoryPath - let baseURL = URL(filePath: currentDirectoryPath, directoryHint: .isDirectory) - let relativePath = "dir" - - let url1 = URL(filePath: relativePath, directoryHint: .isDirectory, relativeTo: baseURL) - - let url2 = URL(filePath: relativePath, directoryHint: .checkFileSystem, relativeTo: baseURL) - XCTAssertEqual(url1, url2, "\(url1) was not equal to \(url2)") - - // directoryHint is `.inferFromPath` by default - let url3 = URL(filePath: relativePath + "/", relativeTo: baseURL) - XCTAssertEqual(url1, url3, "\(url1) was not equal to \(url3)") - } - } - - func testURLFilePathDoesNotFollowLastSymlink() throws { - try FileManagerPlayground { - Directory("dir") { - "Foo" - SymbolicLink("symlink", destination: "../dir") - } - }.test { - let currentDirectoryPath = $0.currentDirectoryPath - let baseURL = URL(filePath: currentDirectoryPath, directoryHint: .isDirectory) - - let dirURL = baseURL.appending(path: "dir", directoryHint: .checkFileSystem) - XCTAssertTrue(dirURL.hasDirectoryPath) - - var symlinkURL = dirURL.appending(path: "symlink", directoryHint: .notDirectory) - - // FileManager uses stat(), which will follow the symlink to the directory. - - #if FOUNDATION_FRAMEWORK - var isDirectory: ObjCBool = false - XCTAssertTrue(FileManager.default.fileExists(atPath: symlinkURL.path, isDirectory: &isDirectory)) - XCTAssertTrue(isDirectory.boolValue) - #else - var isDirectory = false - XCTAssertTrue(FileManager.default.fileExists(atPath: symlinkURL.path, isDirectory: &isDirectory)) - XCTAssertTrue(isDirectory) - #endif - - // URL uses lstat(), which will not follow the symlink at the end of the path. - // Check that URL(filePath:) and .appending(path:) preserve this behavior. - - symlinkURL = URL(filePath: symlinkURL.path, directoryHint: .checkFileSystem) - XCTAssertFalse(symlinkURL.hasDirectoryPath) - - symlinkURL = dirURL.appending(path: "symlink", directoryHint: .checkFileSystem) - XCTAssertFalse(symlinkURL.hasDirectoryPath) - } - } - - func testURLRelativeDotDotResolution() throws { - let baseURL = URL(filePath: "/docs/src/") - var result = URL(filePath: "../images/foo.png", relativeTo: baseURL) - XCTAssertEqual(result.path, "/docs/images/foo.png") - - result = URL(filePath: "/../images/foo.png", relativeTo: baseURL) - XCTAssertEqual(result.path, "/../images/foo.png") - } - - func testAppendFamily() throws { - let base = URL(string: "https://www.example.com")! - - // Appending path - XCTAssertEqual( - base.appending(path: "/api/v2").absoluteString, - "https://www.example.com/api/v2" - ) - var testAppendPath = base - testAppendPath.append(path: "/api/v3") - XCTAssertEqual( - testAppendPath.absoluteString, - "https://www.example.com/api/v3" - ) - - // Appending component - XCTAssertEqual( - base.appending(component: "AC/DC").absoluteString, - "https://www.example.com/AC%2FDC" - ) - var testAppendComponent = base - testAppendComponent.append(component: "AC/DC") - XCTAssertEqual( - testAppendComponent.absoluteString, - "https://www.example.com/AC%2FDC" - ) - - // Append queryItems - let queryItems = [ - URLQueryItem(name: "id", value: "42"), - URLQueryItem(name: "color", value: "blue") - ] - XCTAssertEqual( - base.appending(queryItems: queryItems).absoluteString, - "https://www.example.com?id=42&color=blue" - ) - var testAppendQueryItems = base - testAppendQueryItems.append(queryItems: queryItems) - XCTAssertEqual( - testAppendQueryItems.absoluteString, - "https://www.example.com?id=42&color=blue" - ) - - // Appending components - XCTAssertEqual( - base.appending(components: "api", "artist", "AC/DC").absoluteString, - "https://www.example.com/api/artist/AC%2FDC" - ) - var testAppendComponents = base - testAppendComponents.append(components: "api", "artist", "AC/DC") - XCTAssertEqual( - testAppendComponents.absoluteString, - "https://www.example.com/api/artist/AC%2FDC" - ) - - // Chaining various appends - let chained = base - .appending(path: "api/v2") - .appending(queryItems: [ - URLQueryItem(name: "magic", value: "42"), - URLQueryItem(name: "color", value: "blue") - ]) - .appending(components: "get", "products") - XCTAssertEqual( - chained.absoluteString, - "https://www.example.com/api/v2/get/products?magic=42&color=blue" - ) - } - - func testAppendFamilyDirectoryHint() throws { - // Make sure directoryHint values are propagated correctly - let base = URL(string: "file:///var/mobile")! - - // Appending path - var url = base.appending(path: "/folder/item", directoryHint: .isDirectory) - XCTAssertTrue(url.hasDirectoryPath) - - url = base.appending(path: "folder/item", directoryHint: .notDirectory) - XCTAssertFalse(url.hasDirectoryPath) - - url = base.appending(path: "/folder/item.framework/") - XCTAssertTrue(url.hasDirectoryPath) - - url = base.appending(path: "/folder/item") - XCTAssertFalse(url.hasDirectoryPath) - - try runDirectoryHintCheckFilesystemTest { - $0.appending(path: "/folder/item", directoryHint: .checkFileSystem) - } - - // Appending component - url = base.appending(component: "AC/DC", directoryHint: .isDirectory) - XCTAssertTrue(url.hasDirectoryPath) - - url = base.appending(component: "AC/DC", directoryHint: .notDirectory) - XCTAssertFalse(url.hasDirectoryPath) - - url = base.appending(component: "AC/DC/", directoryHint: .isDirectory) - XCTAssertTrue(url.hasDirectoryPath) - - url = base.appending(component: "AC/DC") - XCTAssertFalse(url.hasDirectoryPath) - - try runDirectoryHintCheckFilesystemTest { - $0.appending(component: "AC/DC", directoryHint: .checkFileSystem) - } - - // Appending components - url = base.appending(components: "api", "v2", "AC/DC", directoryHint: .isDirectory) - XCTAssertTrue(url.hasDirectoryPath) - - url = base.appending(components: "api", "v2", "AC/DC", directoryHint: .notDirectory) - XCTAssertFalse(url.hasDirectoryPath) - - url = base.appending(components: "api", "v2", "AC/DC/", directoryHint: .isDirectory) - XCTAssertTrue(url.hasDirectoryPath) - - url = base.appending(components: "api", "v2", "AC/DC") - XCTAssertFalse(url.hasDirectoryPath) - - try runDirectoryHintCheckFilesystemTest { - $0.appending(components: "api", "v2", "AC/DC", directoryHint: .checkFileSystem) - } - } - - private func runDirectoryHintCheckFilesystemTest(_ builder: (URL) -> URL) throws { - let tempDirectory = URL.temporaryDirectory - // We should not have directory path before it's created - XCTAssertFalse(builder(tempDirectory).hasDirectoryPath) - // Create the folder - try FileManager.default.createDirectory( - at: builder(tempDirectory), - withIntermediateDirectories: true - ) - XCTAssertTrue(builder(tempDirectory).hasDirectoryPath) - try FileManager.default.removeItem(at: builder(tempDirectory)) - } - - func testURLEncodingInvalidCharacters() throws { - let urlStrings = [ - " ", - "path space", - "/absolute path space", - "scheme:path space", - "scheme://host/path space", - "scheme://host/path space?query space#fragment space", - "scheme://user space:pass space@host/", - "unsafe\"<>%{}\\|^~[]`##", - "http://example.com/unsafe\"<>%{}\\|^~[]`##", - "mailto:\"Your Name\" ", - "[This is not a valid URL without encoding.]", - "Encoding a relative path! 😎", - ] - for urlString in urlStrings { - var url = URL(string: urlString, encodingInvalidCharacters: true) - XCTAssertNotNil(url, "Expected a percent-encoded url for string \(urlString)") - url = URL(string: urlString, encodingInvalidCharacters: false) - XCTAssertNil(url, "Expected to fail strict url parsing for string \(urlString)") - } - } - - func testURLAppendingPathDoesNotEncodeColon() throws { - let baseURL = URL(string: "file:///var/mobile/")! - let url = URL(string: "relative", relativeTo: baseURL)! - let component = "no:slash" - let slashComponent = "/with:slash" - - // Make sure we don't encode ":" since `component` is not the first path segment - var appended = url.appending(path: component, directoryHint: .notDirectory) - XCTAssertEqual(appended.absoluteString, "file:///var/mobile/relative/no:slash") - XCTAssertEqual(appended.relativePath, "relative/no:slash") - - appended = url.appending(path: slashComponent, directoryHint: .notDirectory) - XCTAssertEqual(appended.absoluteString, "file:///var/mobile/relative/with:slash") - XCTAssertEqual(appended.relativePath, "relative/with:slash") - - appended = url.appending(component: component, directoryHint: .notDirectory) - XCTAssertEqual(appended.absoluteString, "file:///var/mobile/relative/no:slash") - XCTAssertEqual(appended.relativePath, "relative/no:slash") - - // .appending(component:) should explicitly treat slashComponent as a single - // path component, meaning "/" should be encoded to "%2F" before appending. - // However, the old behavior didn't do this for file URLs, so we maintain the - // old behavior to prevent breakage. - appended = url.appending(component: slashComponent, directoryHint: .notDirectory) - XCTAssertEqual(appended.absoluteString, "file:///var/mobile/relative/with:slash") - XCTAssertEqual(appended.relativePath, "relative/with:slash") - - appended = url.appendingPathComponent(component, isDirectory: false) - XCTAssertEqual(appended.absoluteString, "file:///var/mobile/relative/no:slash") - XCTAssertEqual(appended.relativePath, "relative/no:slash") - - // Test deprecated API, which acts like `appending(path:)` - appended = url.appendingPathComponent(slashComponent, isDirectory: false) - XCTAssertEqual(appended.absoluteString, "file:///var/mobile/relative/with:slash") - XCTAssertEqual(appended.relativePath, "relative/with:slash") - } - - func testURLDeletingLastPathComponent() throws { - var absolute = URL(filePath: "/absolute/path", directoryHint: .notDirectory) - // Note: .relativePath strips the trailing slash for compatibility - XCTAssertEqual(absolute.relativePath, "/absolute/path") - XCTAssertFalse(absolute.hasDirectoryPath) - - absolute.deleteLastPathComponent() - XCTAssertEqual(absolute.relativePath, "/absolute") - XCTAssertTrue(absolute.hasDirectoryPath) - - absolute.deleteLastPathComponent() - XCTAssertEqual(absolute.relativePath, "/") - XCTAssertTrue(absolute.hasDirectoryPath) - - // The old .deleteLastPathComponent() implementation appends ".." to the - // root directory "/", resulting in "/../". This resolves back to "/". - // The new implementation simply leaves "/" as-is. - absolute.deleteLastPathComponent() - checkBehavior(absolute.relativePath, new: "/", old: "/..") - XCTAssertTrue(absolute.hasDirectoryPath) - - absolute.append(path: "absolute", directoryHint: .isDirectory) - checkBehavior(absolute.path, new: "/absolute", old: "/../absolute") - - // Reset `var absolute` to "/absolute" to prevent having - // a "/../" prefix in all the old expectations. - absolute = URL(filePath: "/absolute", directoryHint: .isDirectory) - - var relative = URL(filePath: "relative/path", directoryHint: .notDirectory, relativeTo: absolute) - XCTAssertEqual(relative.relativePath, "relative/path") - XCTAssertFalse(relative.hasDirectoryPath) - XCTAssertEqual(relative.path, "/absolute/relative/path") - - relative.deleteLastPathComponent() - XCTAssertEqual(relative.relativePath, "relative") - XCTAssertTrue(relative.hasDirectoryPath) - XCTAssertEqual(relative.path, "/absolute/relative") - - relative.deleteLastPathComponent() - XCTAssertEqual(relative.relativePath, ".") - XCTAssertTrue(relative.hasDirectoryPath) - XCTAssertEqual(relative.path, "/absolute") - - relative.deleteLastPathComponent() - XCTAssertEqual(relative.relativePath, "..") - XCTAssertTrue(relative.hasDirectoryPath) - XCTAssertEqual(relative.path, "/") - - relative.deleteLastPathComponent() - XCTAssertEqual(relative.relativePath, "../..") - XCTAssertTrue(relative.hasDirectoryPath) - checkBehavior(relative.path, new:"/", old: "/..") - - relative.append(path: "path", directoryHint: .isDirectory) - XCTAssertEqual(relative.relativePath, "../../path") - XCTAssertTrue(relative.hasDirectoryPath) - checkBehavior(relative.path, new: "/path", old: "/../path") - - relative.deleteLastPathComponent() - XCTAssertEqual(relative.relativePath, "../..") - XCTAssertTrue(relative.hasDirectoryPath) - checkBehavior(relative.path, new: "/", old: "/..") - - relative = URL(filePath: "", relativeTo: absolute) - XCTAssertEqual(relative.relativePath, ".") - XCTAssertTrue(relative.hasDirectoryPath) - XCTAssertEqual(relative.path, "/absolute") - - relative.deleteLastPathComponent() - XCTAssertEqual(relative.relativePath, "..") - XCTAssertTrue(relative.hasDirectoryPath) - XCTAssertEqual(relative.path, "/") - - relative.deleteLastPathComponent() - XCTAssertEqual(relative.relativePath, "../..") - XCTAssertTrue(relative.hasDirectoryPath) - checkBehavior(relative.path, new: "/", old: "/..") - - relative = URL(filePath: "relative/./", relativeTo: absolute) - // According to RFC 3986, "." and ".." segments should not be removed - // until the path is resolved against the base URL (when calling .path) - checkBehavior(relative.relativePath, new: "relative/.", old: "relative") - XCTAssertTrue(relative.hasDirectoryPath) - XCTAssertEqual(relative.path, "/absolute/relative") - - relative.deleteLastPathComponent() - checkBehavior(relative.relativePath, new: "relative/..", old: ".") - XCTAssertTrue(relative.hasDirectoryPath) - XCTAssertEqual(relative.path, "/absolute") - - relative = URL(filePath: "relative/.", directoryHint: .isDirectory, relativeTo: absolute) - checkBehavior(relative.relativePath, new: "relative/.", old: "relative") - XCTAssertTrue(relative.hasDirectoryPath) - XCTAssertEqual(relative.path, "/absolute/relative") - - relative.deleteLastPathComponent() - checkBehavior(relative.relativePath, new: "relative/..", old: ".") - XCTAssertTrue(relative.hasDirectoryPath) - XCTAssertEqual(relative.path, "/absolute") - - relative = URL(filePath: "relative/..", relativeTo: absolute) - XCTAssertEqual(relative.relativePath, "relative/..") - checkBehavior(relative.hasDirectoryPath, new: true, old: false) - XCTAssertEqual(relative.path, "/absolute") - - relative.deleteLastPathComponent() - XCTAssertEqual(relative.relativePath, "relative/../..") - XCTAssertTrue(relative.hasDirectoryPath) - XCTAssertEqual(relative.path, "/") - - relative = URL(filePath: "relative/..", directoryHint: .isDirectory, relativeTo: absolute) - XCTAssertEqual(relative.relativePath, "relative/..") - XCTAssertTrue(relative.hasDirectoryPath) - XCTAssertEqual(relative.path, "/absolute") - - relative.deleteLastPathComponent() - XCTAssertEqual(relative.relativePath, "relative/../..") - XCTAssertTrue(relative.hasDirectoryPath) - XCTAssertEqual(relative.path, "/") - - var url = try XCTUnwrap(URL(string: "scheme://host.with.no.path")) - XCTAssertTrue(url.path().isEmpty) - - url.deleteLastPathComponent() - XCTAssertEqual(url.absoluteString, "scheme://host.with.no.path") - XCTAssertTrue(url.path().isEmpty) - - let unusedBase = URL(string: "base://url") - url = try XCTUnwrap(URL(string: "scheme://host.with.no.path", relativeTo: unusedBase)) - XCTAssertEqual(url.absoluteString, "scheme://host.with.no.path") - XCTAssertTrue(url.path().isEmpty) - - url.deleteLastPathComponent() - XCTAssertEqual(url.absoluteString, "scheme://host.with.no.path") - XCTAssertTrue(url.path().isEmpty) - - var schemeRelative = try XCTUnwrap(URL(string: "scheme:relative/path")) - // Bug in the old implementation where a relative path is not recognized - checkBehavior(schemeRelative.relativePath, new: "relative/path", old: "") - - schemeRelative.deleteLastPathComponent() - checkBehavior(schemeRelative.relativePath, new: "relative", old: "") - - schemeRelative.deleteLastPathComponent() - XCTAssertEqual(schemeRelative.relativePath, "") - - schemeRelative.deleteLastPathComponent() - XCTAssertEqual(schemeRelative.relativePath, "") - } - - func testURLFilePathDropsTrailingSlashes() throws { - var url = URL(filePath: "/path/slashes///") - XCTAssertEqual(url.path(), "/path/slashes///") - // TODO: Update this once .fileSystemPath uses backslashes for Windows - XCTAssertEqual(url.fileSystemPath(), "/path/slashes") - - url = URL(filePath: "/path/slashes/") - XCTAssertEqual(url.path(), "/path/slashes/") - XCTAssertEqual(url.fileSystemPath(), "/path/slashes") - - url = URL(filePath: "/path/slashes") - XCTAssertEqual(url.path(), "/path/slashes") - XCTAssertEqual(url.fileSystemPath(), "/path/slashes") - } - - func testURLNotDirectoryHintStripsTrailingSlash() throws { - // Supply a path with a trailing slash but say it's not a direcotry - var url = URL(filePath: "/path/", directoryHint: .notDirectory) - XCTAssertFalse(url.hasDirectoryPath) - XCTAssertEqual(url.path(), "/path") - - url = URL(fileURLWithPath: "/path/", isDirectory: false) - XCTAssertFalse(url.hasDirectoryPath) - XCTAssertEqual(url.path(), "/path") - - url = URL(filePath: "/path///", directoryHint: .notDirectory) - XCTAssertFalse(url.hasDirectoryPath) - XCTAssertEqual(url.path(), "/path") - - url = URL(fileURLWithPath: "/path///", isDirectory: false) - XCTAssertFalse(url.hasDirectoryPath) - XCTAssertEqual(url.path(), "/path") - - // With .checkFileSystem, don't modify the path for a non-existent file - url = URL(filePath: "/my/non/existent/path/", directoryHint: .checkFileSystem) - XCTAssertTrue(url.hasDirectoryPath) - XCTAssertEqual(url.path(), "/my/non/existent/path/") - - url = URL(fileURLWithPath: "/my/non/existent/path/") - XCTAssertTrue(url.hasDirectoryPath) - XCTAssertEqual(url.path(), "/my/non/existent/path/") - - url = URL(filePath: "/my/non/existent/path", directoryHint: .checkFileSystem) - XCTAssertFalse(url.hasDirectoryPath) - XCTAssertEqual(url.path(), "/my/non/existent/path") - - url = URL(fileURLWithPath: "/my/non/existent/path") - XCTAssertFalse(url.hasDirectoryPath) - XCTAssertEqual(url.path(), "/my/non/existent/path") - } - - func testURLHostRetainsIDNAEncoding() throws { - let url = URL(string: "ftp://user:password@*.xn--poema-9qae5a.com.br:4343/cat.txt")! - XCTAssertEqual(url.host, "*.xn--poema-9qae5a.com.br") - } - - func testURLHostIPLiteralCompatibility() throws { - var url = URL(string: "http://[::]")! - XCTAssertEqual(url.host, "::") - XCTAssertEqual(url.host(), "::") - - url = URL(string: "https://[::1]:433/")! - XCTAssertEqual(url.host, "::1") - XCTAssertEqual(url.host(), "::1") - - url = URL(string: "https://[2001:db8::]/")! - XCTAssertEqual(url.host, "2001:db8::") - XCTAssertEqual(url.host(), "2001:db8::") - - url = URL(string: "https://[2001:db8::]:433")! - XCTAssertEqual(url.host, "2001:db8::") - XCTAssertEqual(url.host(), "2001:db8::") - - url = URL(string: "http://[fe80::a%25en1]")! - XCTAssertEqual(url.absoluteString, "http://[fe80::a%25en1]") - XCTAssertEqual(url.host, "fe80::a%en1") - XCTAssertEqual(url.host(percentEncoded: true), "fe80::a%25en1") - XCTAssertEqual(url.host(percentEncoded: false), "fe80::a%en1") - - url = URL(string: "http://[fe80::a%en1]")! - XCTAssertEqual(url.absoluteString, "http://[fe80::a%25en1]") - XCTAssertEqual(url.host, "fe80::a%en1") - XCTAssertEqual(url.host(percentEncoded: true), "fe80::a%25en1") - XCTAssertEqual(url.host(percentEncoded: false), "fe80::a%en1") - - url = URL(string: "http://[fe80::a%100%CustomZone]")! - XCTAssertEqual(url.absoluteString, "http://[fe80::a%25100%25CustomZone]") - XCTAssertEqual(url.host, "fe80::a%100%CustomZone") - XCTAssertEqual(url.host(percentEncoded: true), "fe80::a%25100%25CustomZone") - XCTAssertEqual(url.host(percentEncoded: false), "fe80::a%100%CustomZone") - } - - #if !os(Windows) - func testURLTildeFilePath() throws { - func urlIsAbsolute(_ url: URL) -> Bool { - if url.relativePath.utf8.first == ._slash { - return true - } - guard url.baseURL != nil else { - return false - } - return url.path.utf8.first == ._slash - } - - // "~" must either be expanded to an absolute path or resolved against a base URL - var url = URL(filePath: "~") - XCTAssertTrue(urlIsAbsolute(url)) - - url = URL(filePath: "~", directoryHint: .isDirectory) - XCTAssertTrue(urlIsAbsolute(url)) - XCTAssertEqual(url.path().utf8.last, ._slash) - - url = URL(filePath: "~/") - XCTAssertTrue(urlIsAbsolute(url)) - XCTAssertEqual(url.path().utf8.last, ._slash) - } - #endif // !os(Windows) - - func testURLPathExtensions() throws { - var url = URL(filePath: "/path", directoryHint: .notDirectory) - url.appendPathExtension("foo") - XCTAssertEqual(url.path(), "/path.foo") - url.deletePathExtension() - XCTAssertEqual(url.path(), "/path") - - url = URL(filePath: "/path", directoryHint: .isDirectory) - url.appendPathExtension("foo") - XCTAssertEqual(url.path(), "/path.foo/") - url.deletePathExtension() - XCTAssertEqual(url.path(), "/path/") - - url = URL(filePath: "/path/", directoryHint: .inferFromPath) - url.appendPathExtension("foo") - XCTAssertEqual(url.path(), "/path.foo/") - url.append(path: "/////") - url.deletePathExtension() - // Old behavior only searches the last empty component, so the extension isn't actually removed - checkBehavior(url.path(), new: "/path/", old: "/path.foo///") - - url = URL(filePath: "/tmp/x") - url.appendPathExtension("") - XCTAssertEqual(url.path(), "/tmp/x") - XCTAssertEqual(url, url.deletingPathExtension().appendingPathExtension(url.pathExtension)) - - url = URL(filePath: "/tmp/x.") - url.deletePathExtension() - XCTAssertEqual(url.path(), "/tmp/x.") - } - - func testURLAppendingToEmptyPath() throws { - let baseURL = URL(filePath: "/base/directory", directoryHint: .isDirectory) - let emptyPathURL = URL(filePath: "", relativeTo: baseURL) - let url = emptyPathURL.appending(path: "main.swift") - XCTAssertEqual(url.relativePath, "./main.swift") - XCTAssertEqual(url.path, "/base/directory/main.swift") - - var example = try XCTUnwrap(URL(string: "https://example.com")) - XCTAssertEqual(example.host(), "example.com") - XCTAssertTrue(example.path().isEmpty) - - // Appending to an empty path should add a slash if an authority exists - // The appended path should never become part of the host - example.append(path: "foo") - XCTAssertEqual(example.host(), "example.com") - XCTAssertEqual(example.path(), "/foo") - XCTAssertEqual(example.absoluteString, "https://example.com/foo") - - var emptyHost = try XCTUnwrap(URL(string: "scheme://")) - XCTAssertTrue(emptyHost.host()?.isEmpty ?? true) - XCTAssertTrue(emptyHost.path().isEmpty) - - emptyHost.append(path: "foo") - XCTAssertTrue(emptyHost.host()?.isEmpty ?? true) - // Old behavior failed to append correctly to an empty host - // Modern parsers agree that "foo" relative to "scheme://" is "scheme:///foo" - checkBehavior(emptyHost.path(), new: "/foo", old: "") - checkBehavior(emptyHost.absoluteString, new: "scheme:///foo", old: "scheme://") - - var schemeOnly = try XCTUnwrap(URL(string: "scheme:")) - XCTAssertTrue(schemeOnly.host()?.isEmpty ?? true) - XCTAssertTrue(schemeOnly.path().isEmpty) - - schemeOnly.append(path: "foo") - XCTAssertTrue(schemeOnly.host()?.isEmpty ?? true) - // Old behavior appends to the string, but is missing the path - checkBehavior(schemeOnly.path(), new: "foo", old: "") - XCTAssertEqual(schemeOnly.absoluteString, "scheme:foo") - } - - func testURLEmptySchemeCompatibility() throws { - var url = try XCTUnwrap(URL(string: ":memory:")) - XCTAssertEqual(url.scheme, "") - - let base = try XCTUnwrap(URL(string: "://home")) - XCTAssertEqual(base.host(), "home") - - url = try XCTUnwrap(URL(string: "/path", relativeTo: base)) - XCTAssertEqual(url.scheme, "") - XCTAssertEqual(url.host(), "home") - XCTAssertEqual(url.path, "/path") - XCTAssertEqual(url.absoluteString, "://home/path") - XCTAssertEqual(url.absoluteURL.scheme, "") - } - - func testURLComponentsPercentEncodedUnencodedProperties() throws { - var comp = URLComponents() - - comp.user = "%25" - XCTAssertEqual(comp.user, "%25") - XCTAssertEqual(comp.percentEncodedUser, "%2525") - - comp.password = "%25" - XCTAssertEqual(comp.password, "%25") - XCTAssertEqual(comp.percentEncodedPassword, "%2525") - - // Host behavior differs since the addition of IDNA-encoding - comp.host = "%25" - XCTAssertEqual(comp.host, "%") - XCTAssertEqual(comp.percentEncodedHost, "%25") - - comp.path = "%25" - XCTAssertEqual(comp.path, "%25") - XCTAssertEqual(comp.percentEncodedPath, "%2525") - - comp.query = "%25" - XCTAssertEqual(comp.query, "%25") - XCTAssertEqual(comp.percentEncodedQuery, "%2525") - - comp.fragment = "%25" - XCTAssertEqual(comp.fragment, "%25") - XCTAssertEqual(comp.percentEncodedFragment, "%2525") - - comp.queryItems = [URLQueryItem(name: "name", value: "a%25b")] - XCTAssertEqual(comp.queryItems, [URLQueryItem(name: "name", value: "a%25b")]) - XCTAssertEqual(comp.percentEncodedQueryItems, [URLQueryItem(name: "name", value: "a%2525b")]) - XCTAssertEqual(comp.query, "name=a%25b") - XCTAssertEqual(comp.percentEncodedQuery, "name=a%2525b") - } - - func testURLPercentEncodedProperties() throws { - var url = URL(string: "https://%3Auser:%3Apassword@%3A.com/%3Apath?%3Aquery=%3A#%3Afragment")! - - XCTAssertEqual(url.user(), "%3Auser") - XCTAssertEqual(url.user(percentEncoded: false), ":user") - - XCTAssertEqual(url.password(), "%3Apassword") - XCTAssertEqual(url.password(percentEncoded: false), ":password") - - XCTAssertEqual(url.host(), "%3A.com") - XCTAssertEqual(url.host(percentEncoded: false), ":.com") - - XCTAssertEqual(url.path(), "/%3Apath") - XCTAssertEqual(url.path(percentEncoded: false), "/:path") - - XCTAssertEqual(url.query(), "%3Aquery=%3A") - XCTAssertEqual(url.query(percentEncoded: false), ":query=:") - - XCTAssertEqual(url.fragment(), "%3Afragment") - XCTAssertEqual(url.fragment(percentEncoded: false), ":fragment") - - // Lowercase input - url = URL(string: "https://%3auser:%3apassword@%3a.com/%3apath?%3aquery=%3a#%3afragment")! - - XCTAssertEqual(url.user(), "%3auser") - XCTAssertEqual(url.user(percentEncoded: false), ":user") - - XCTAssertEqual(url.password(), "%3apassword") - XCTAssertEqual(url.password(percentEncoded: false), ":password") - - XCTAssertEqual(url.host(), "%3a.com") - XCTAssertEqual(url.host(percentEncoded: false), ":.com") - - XCTAssertEqual(url.path(), "/%3apath") - XCTAssertEqual(url.path(percentEncoded: false), "/:path") - - XCTAssertEqual(url.query(), "%3aquery=%3a") - XCTAssertEqual(url.query(percentEncoded: false), ":query=:") - - XCTAssertEqual(url.fragment(), "%3afragment") - XCTAssertEqual(url.fragment(percentEncoded: false), ":fragment") - } - - func testURLComponentsUppercasePercentEncoding() throws { - // Always use uppercase percent-encoding when unencoded components are assigned - var comp = URLComponents() - comp.scheme = "https" - comp.user = "?user" - comp.password = "?password" - comp.path = "?path" - comp.query = "#query" - comp.fragment = "#fragment" - XCTAssertEqual(comp.percentEncodedUser, "%3Fuser") - XCTAssertEqual(comp.percentEncodedPassword, "%3Fpassword") - XCTAssertEqual(comp.percentEncodedPath, "%3Fpath") - XCTAssertEqual(comp.percentEncodedQuery, "%23query") - XCTAssertEqual(comp.percentEncodedFragment, "%23fragment") - } - - func testURLComponentsRangeCombinations() throws { - // This brute forces many combinations and takes a long time. - // Skip this for automated testing purposes and test manually when needed. - try XCTSkipIf(true) - - let schemes = [nil, "a", "aa"] - let users = [nil, "b", "bb"] - let passwords = [nil, "c", "cc"] - let hosts = [nil, "d", "dd"] - let ports = [nil, 80, 433] - let paths = ["", "/e", "/e/e"] - let queries = [nil, "f=f", "hh=hh"] - let fragments = [nil, "j", "jj"] - - func forAll(_ block: (String?, String?, String?, String?, Int?, String, String?, String?) throws -> ()) rethrows { - for scheme in schemes { - for user in users { - for password in passwords { - for host in hosts { - for port in ports { - for path in paths { - for query in queries { - for fragment in fragments { - try block(scheme, user, password, host, port, path, query, fragment) - } - } - } - } - } - } - } - } - } - - func validateRanges(_ comp: URLComponents, scheme: String?, user: String?, password: String?, host: String?, port: Int?, path: String, query: String?, fragment: String?) throws { - let string = try XCTUnwrap(comp.string) - if let scheme { - let range = try XCTUnwrap(comp.rangeOfScheme) - XCTAssertTrue(string[range] == scheme) - } else { - XCTAssertNil(comp.rangeOfScheme) - } - if let user { - let range = try XCTUnwrap(comp.rangeOfUser) - XCTAssertTrue(string[range] == user) - } else { - // Even if we set comp.user = nil, a non-nil password - // implies that user exists as the empty string. - let isEmptyUserWithPassword = ( - comp.user?.isEmpty ?? false && - comp.rangeOfUser?.isEmpty ?? false && - comp.password != nil - ) - XCTAssertTrue(comp.rangeOfUser == nil || isEmptyUserWithPassword) - } - if let password { - let range = try XCTUnwrap(comp.rangeOfPassword) - XCTAssertTrue(string[range] == password) - } else { - XCTAssertNil(comp.rangeOfPassword) - } - if let host { - let range = try XCTUnwrap(comp.rangeOfHost) - XCTAssertTrue(string[range] == host) - } else { - // Even if we set comp.host = nil, any non-nil authority component - // implies that host exists as the empty string. - let isEmptyHostWithAuthorityComponent = ( - comp.host?.isEmpty ?? false && - comp.rangeOfHost?.isEmpty ?? false && - (user != nil || password != nil || port != nil) - ) - XCTAssertTrue(comp.rangeOfHost == nil || isEmptyHostWithAuthorityComponent) - } - if let port { - let range = try XCTUnwrap(comp.rangeOfPort) - XCTAssertTrue(string[range] == String(port)) - } else { - XCTAssertNil(comp.rangeOfPort) - } - // rangeOfPath should never be nil. - let pathRange = try XCTUnwrap(comp.rangeOfPath) - XCTAssertTrue(string[pathRange] == path) - if let query { - let range = try XCTUnwrap(comp.rangeOfQuery) - XCTAssertTrue(string[range] == query) - } else { - XCTAssertNil(comp.rangeOfQuery) - } - if let fragment { - let range = try XCTUnwrap(comp.rangeOfFragment) - XCTAssertTrue(string[range] == fragment) - } else { - XCTAssertNil(comp.rangeOfFragment) - } - } - - try forAll { scheme, user, password, host, port, path, query, fragment in - - // Assign all components then get the ranges - - var comp = URLComponents() - comp.scheme = scheme - comp.user = user - comp.password = password - comp.host = host - comp.port = port - comp.path = path - comp.query = query - comp.fragment = fragment - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - let string = try XCTUnwrap(comp.string) - let fullComponents = URLComponents(string: string)! - - // Get the ranges directly from URLParseInfo - - comp = fullComponents - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - // Set components after parsing, which invalidates the URLParseInfo ranges - - comp = fullComponents - comp.scheme = scheme - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - comp.user = user - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - comp.password = password - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - comp.host = host - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - comp.port = port - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - comp.path = path - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - comp.query = query - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - comp.fragment = fragment - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - // Remove components from the string, set them back, and validate ranges - - comp = fullComponents - comp.scheme = nil - try validateRanges(comp, scheme: nil, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - let stringWithoutScheme = try XCTUnwrap(comp.string) - comp = URLComponents(string: stringWithoutScheme)! - comp.scheme = scheme - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - var expectedHost = host - if user != nil && host == nil { - // We parsed a string with a non-nil user, so expect host to - // be the empty string, even after we set comp.user = nil. - expectedHost = "" - } - comp.user = nil - try validateRanges(comp, scheme: scheme, user: nil, password: password, host: expectedHost, port: port, path: path, query: query, fragment: fragment) - - let stringWithoutUser = try XCTUnwrap(comp.string) - comp = URLComponents(string: stringWithoutUser)! - comp.user = user - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - var expectedUser = user - if password != nil && user == nil { - // We parsed a string with a non-nil password, so expect user to - // be the empty string, even after we set comp.password = nil. - expectedUser = "" - } - comp.password = nil - try validateRanges(comp, scheme: scheme, user: expectedUser, password: nil, host: host, port: port, path: path, query: query, fragment: fragment) - - let stringWithoutPassword = try XCTUnwrap(comp.string) - comp = URLComponents(string: stringWithoutPassword)! - comp.password = password - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - comp.host = nil - try validateRanges(comp, scheme: scheme, user: user, password: password, host: nil, port: port, path: path, query: query, fragment: fragment) - - let stringWithoutHost = try XCTUnwrap(comp.string) - comp = URLComponents(string: stringWithoutHost)! - comp.host = host - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - expectedHost = host - if port != nil && host == nil { - // We parsed a string with a non-nil port, so expect host to - // be the empty string, even after we set comp.port = nil. - expectedHost = "" - } - comp.port = nil - try validateRanges(comp, scheme: scheme, user: user, password: password, host: expectedHost, port: nil, path: path, query: query, fragment: fragment) - - let stringWithoutPort = try XCTUnwrap(comp.string) - comp = URLComponents(string: stringWithoutPort)! - comp.port = port - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - comp.path = "" - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: "", query: query, fragment: fragment) - - let stringWithoutPath = try XCTUnwrap(comp.string) - comp = URLComponents(string: stringWithoutPath)! - comp.path = path - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - comp.query = nil - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: nil, fragment: fragment) - - let stringWithoutQuery = try XCTUnwrap(comp.string) - comp = URLComponents(string: stringWithoutQuery)! - comp.query = query - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - - comp = fullComponents - comp.fragment = nil - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: nil) - - let stringWithoutFragment = try XCTUnwrap(comp.string) - comp = URLComponents(string: stringWithoutFragment)! - comp.fragment = fragment - try validateRanges(comp, scheme: scheme, user: user, password: password, host: host, port: port, path: path, query: query, fragment: fragment) - } - } - - func testURLComponentsEncodesFirstPathColon() throws { - let path = "first:segment:with:colons/second:segment:with:colons" - var comp = URLComponents() - comp.path = path - guard let compString = comp.string else { - XCTFail("compString was nil") - return - } - guard let slashIndex = compString.firstIndex(of: "/") else { - XCTFail("Could not find slashIndex") - return - } - let firstSegment = compString[.. equivalent representation.") - XCTAssertNotEqual(uuidC, uuidD, "Two different UUIDs must not be equal.") - } - - func test_UUIDInvalid() { - let invalid = UUID(uuidString: "Invalid UUID") - XCTAssertNil(invalid, "The convenience initializer `init?(uuidString string:)` must return nil for an invalid UUID string.") - } - - // `uuidString` should return an uppercase string - // See: https://bugs.swift.org/browse/SR-865 - func test_UUIDuuidString() { - let uuid = UUID(uuid: (0xe6,0x21,0xe1,0xf8,0xc3,0x6c,0x49,0x5a,0x93,0xfc,0x0c,0x24,0x7a,0x3e,0x6e,0x5f)) - XCTAssertEqual(uuid.uuidString, "E621E1F8-C36C-495A-93FC-0C247A3E6E5F", "The uuidString representation must be uppercase.") - } - - func test_UUIDdescription() { - let uuid = UUID() - let description: String = uuid.description - let uuidString: String = uuid.uuidString - XCTAssertEqual(description, uuidString, "The description must be the same as the uuidString.") - } - - func test_hash() { - let values: [UUID] = [ - // This list takes a UUID and tweaks every byte while - // leaving the version/variant intact. - UUID(uuidString: "a53baa1c-b4f5-48db-9467-9786b76b256c")!, - UUID(uuidString: "a63baa1c-b4f5-48db-9467-9786b76b256c")!, - UUID(uuidString: "a53caa1c-b4f5-48db-9467-9786b76b256c")!, - UUID(uuidString: "a53bab1c-b4f5-48db-9467-9786b76b256c")!, - UUID(uuidString: "a53baa1d-b4f5-48db-9467-9786b76b256c")!, - UUID(uuidString: "a53baa1c-b5f5-48db-9467-9786b76b256c")!, - UUID(uuidString: "a53baa1c-b4f6-48db-9467-9786b76b256c")!, - UUID(uuidString: "a53baa1c-b4f5-49db-9467-9786b76b256c")!, - UUID(uuidString: "a53baa1c-b4f5-48dc-9467-9786b76b256c")!, - UUID(uuidString: "a53baa1c-b4f5-48db-9567-9786b76b256c")!, - UUID(uuidString: "a53baa1c-b4f5-48db-9468-9786b76b256c")!, - UUID(uuidString: "a53baa1c-b4f5-48db-9467-9886b76b256c")!, - UUID(uuidString: "a53baa1c-b4f5-48db-9467-9787b76b256c")!, - UUID(uuidString: "a53baa1c-b4f5-48db-9467-9786b86b256c")!, - UUID(uuidString: "a53baa1c-b4f5-48db-9467-9786b76c256c")!, - UUID(uuidString: "a53baa1c-b4f5-48db-9467-9786b76b266c")!, - UUID(uuidString: "a53baa1c-b4f5-48db-9467-9786b76b256d")!, - ] - checkHashable(values, equalityOracle: { $0 == $1 }) - } - - func test_AnyHashableContainingUUID() { - let values: [UUID] = [ - UUID(uuidString: "e621e1f8-c36c-495a-93fc-0c247a3e6e5f")!, - UUID(uuidString: "f81d4fae-7dec-11d0-a765-00a0c91e6bf6")!, - UUID(uuidString: "f81d4fae-7dec-11d0-a765-00a0c91e6bf6")!, - ] - let anyHashables = values.map(AnyHashable.init) - expectEqual(UUID.self, type(of: anyHashables[0].base)) - expectEqual(UUID.self, type(of: anyHashables[1].base)) - expectEqual(UUID.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) - } - - // rdar://71190003 (UUID has no customMirror) - func test_UUID_custom_mirror() { - let uuid = UUID(uuidString: "89E90DC6-5EBA-41A8-A64D-81D3576EE46E")! - XCTAssertEqual(String(reflecting: uuid), "89E90DC6-5EBA-41A8-A64D-81D3576EE46E") - } - - func test_UUID_Comparable() throws { - var uuid1 = try XCTUnwrap(UUID(uuidString: "00000000-0000-0000-0000-000000000001")) - var uuid2 = try XCTUnwrap(UUID(uuidString: "00000000-0000-0000-0000-000000000002")) - XCTAssertTrue(uuid1 < uuid2) - XCTAssertFalse(uuid2 < uuid1) - XCTAssertFalse(uuid2 == uuid1) - - uuid1 = try XCTUnwrap(UUID(uuidString: "9707CE8D-251F-4858-8BF9-C9EC3D690FCE")) - uuid2 = try XCTUnwrap(UUID(uuidString: "9807CE8D-251F-4858-8BF9-C9EC3D690FCE")) - XCTAssertTrue(uuid1 < uuid2) - XCTAssertFalse(uuid2 < uuid1) - XCTAssertFalse(uuid2 == uuid1) - - uuid1 = try XCTUnwrap(UUID(uuidString: "9707CE8D-261F-4858-8BF9-C9EC3D690FCE")) - uuid2 = try XCTUnwrap(UUID(uuidString: "9707CE8D-251F-4858-8BF9-C9EC3D690FCE")) - XCTAssertTrue(uuid1 > uuid2) - XCTAssertFalse(uuid2 > uuid1) - XCTAssertFalse(uuid2 == uuid1) - - uuid1 = try XCTUnwrap(UUID(uuidString: "9707CE8D-251F-4858-8BF9-C9EC3D690FCE")) - uuid2 = try XCTUnwrap(UUID(uuidString: "9707CE8D-251F-4858-8BF9-C9EC3D690FCE")) - XCTAssertFalse(uuid1 > uuid2) - XCTAssertFalse(uuid2 > uuid1) - XCTAssertTrue(uuid2 == uuid1) - } -} diff --git a/Tests/FoundationInternationalizationTests/CalendarPerformanceTests.swift b/Tests/FoundationInternationalizationTests/CalendarPerformanceTests.swift deleted file mode 100644 index d53b1dc30..000000000 --- a/Tests/FoundationInternationalizationTests/CalendarPerformanceTests.swift +++ /dev/null @@ -1,92 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if FOUNDATION_FRAMEWORK -import Foundation -import XCTest - -final class TestCalendarPerformance: XCTestCase { - - var metrics: [XCTMetric] { - // XCTMemoryMetric is randomly reporting 0kb for memory usage. - [/*XCTMemoryMetric(),*/ XCTCPUMetric()] - } - - var options: XCTMeasureOptions { - let opts = XCTMeasureOptions.default - opts.iterationCount = 10 - return opts - } - - func test_nextThousandThanksgivings() { - measure(metrics: metrics, options: self.options) { - let dc = DateComponents(month: 11, weekday: 5, weekOfMonth: 4) - let cal = Calendar(identifier: .gregorian) - let start = Date(timeIntervalSinceReferenceDate: 496359355.795410) //2016-09-23T14:35:55-0700 - - var count = 1000 - cal.enumerateDates(startingAfter: start, matching: dc, matchingPolicy: .nextTime) { result, exactMatch, stop in - count -= 1 - if count == 0 { - stop = true - } - } - } - } - - func test_allocationsForFixedCalendars() { - let reference = Date(timeIntervalSinceReferenceDate: 496359355.795410) //2016-09-23T14:35:55-0700 - measure(metrics: metrics, options: self.options) { - // Fixed calendar - for _ in 0..<10000 { - let cal = Calendar(identifier: .gregorian) - let date = cal.date(byAdding: .day, value: 1, to: reference) - XCTAssertTrue(date != nil) - } - } - } - - func test_allocationsForCurrentCalendar() { - let reference = Date(timeIntervalSinceReferenceDate: 496359355.795410) //2016-09-23T14:35:55-0700 - measure(metrics: metrics, options: self.options) { - for _ in 0..<10000 { - let cal = Calendar.current - let date = cal.date(byAdding: .day, value: 1, to: reference) - XCTAssertTrue(date != nil) - } - } - } - - func test_allocationsForAutoupdatingCurrentCalendar() { - let reference = Date(timeIntervalSinceReferenceDate: 496359355.795410) //2016-09-23T14:35:55-0700 - measure(metrics: metrics, options: self.options) { - for _ in 0..<10000 { - let cal = Calendar.autoupdatingCurrent - let date = cal.date(byAdding: .day, value: 1, to: reference) - XCTAssertTrue(date != nil) - } - } - } - - func test_copyOnWritePerformance() { - let reference = Date(timeIntervalSinceReferenceDate: 496359355.795410) //2016-09-23T14:35:55-0700 - measure(metrics: metrics, options: self.options) { - var cal = Calendar(identifier: .gregorian) - for i in 0..<10000 { - cal.firstWeekday = i % 2 - let date = cal.date(byAdding: .day, value: 1, to: reference) - XCTAssertNotNil(date) - } - } - } -} -#endif diff --git a/Tests/FoundationInternationalizationTests/CalendarRecurrenceRuleTests.swift b/Tests/FoundationInternationalizationTests/CalendarRecurrenceRuleTests.swift deleted file mode 100644 index b220ea709..000000000 --- a/Tests/FoundationInternationalizationTests/CalendarRecurrenceRuleTests.swift +++ /dev/null @@ -1,138 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#else -@testable import FoundationInternationalization -@testable import FoundationEssentials -#endif // FOUNDATION_FRAMEWORK - -final class CalendarRecurrenceRuleTests: XCTestCase { - /// A Gregorian calendar with a time zone set to California - var gregorian: Calendar = { - var gregorian = Calendar(identifier: .gregorian) - gregorian.timeZone = .init(identifier: "US/Pacific")! - return gregorian - }() - - func testYearlyRecurrenceInLunarCalendar() { - // Find the first day of the lunar new year - let start = Date(timeIntervalSince1970: 1726876800.0) // 2024-09-21T00:00:00-0000 - let end = Date(timeIntervalSince1970: 1855699200.0) // 2028-10-21T00:00:00-0000 - - var lunarCalendar = Calendar(identifier: .chinese) - lunarCalendar.timeZone = .gmt - - var rule = Calendar.RecurrenceRule(calendar: lunarCalendar, frequency: .yearly) - rule.daysOfTheYear = [1] - - let eventStart = Date(timeIntervalSince1970: 1285077600.0) // 2010-09-21T14:00:00-0000 - let results = Array(rule.recurrences(of: eventStart, in: start.. String? { - let components: [Calendar.Component] = [.era, .year, .month, .day, .dayOfYear, .hour, .minute, .second, .weekday, .weekdayOrdinal, .weekOfYear, .yearForWeekOfYear, .weekOfMonth, .timeZone, .isLeapMonth, .calendar, .quarter, .nanosecond] - var diffStr = "" - var isEqual = true - for component in components { - let actualValue = d1?.value(for: component) - let expectedValue = d2?.value(for: component) - switch component { - case .era, .year, .month, .day, .dayOfYear, .hour, .minute, .second, .weekday, .weekdayOrdinal, .weekOfYear, .yearForWeekOfYear, .weekOfMonth, .timeZone, .isLeapMonth, .calendar: - if actualValue != expectedValue { - diffStr += "\ncomponent: \(component), 1st: \(String(describing: actualValue)), 2nd: \(String(describing: expectedValue))" - isEqual = false - } - case .quarter: - if compareQuarter && actualValue != expectedValue { - diffStr += "\ncomponent: \(component), 1st: \(String(describing: actualValue)), 2nd: \(String(describing: expectedValue))" - isEqual = false - } - case .nanosecond: - var nanosecondIsEqual = true - if let actualValue, let expectedValue, (abs(actualValue - expectedValue) > nanosecondAccuracy) { - nanosecondIsEqual = false - } else if actualValue != expectedValue { // one of them is nil - nanosecondIsEqual = false - } - - if !nanosecondIsEqual { - diffStr += "\ncomponent: \(component), 1st: \(String(describing: actualValue)), 2nd: \(String(describing: expectedValue))" - isEqual = false - } - } - } - - return isEqual ? nil : diffStr - } -} - -final class CalendarTests : XCTestCase { - - var allCalendars: [Calendar] = [ - Calendar(identifier: .gregorian), - Calendar(identifier: .buddhist), - Calendar(identifier: .chinese), - Calendar(identifier: .coptic), - Calendar(identifier: .ethiopicAmeteMihret), - Calendar(identifier: .ethiopicAmeteAlem), - Calendar(identifier: .hebrew), - Calendar(identifier: .iso8601), - Calendar(identifier: .indian), - Calendar(identifier: .islamic), - Calendar(identifier: .islamicCivil), - Calendar(identifier: .japanese), - Calendar(identifier: .persian), - Calendar(identifier: .republicOfChina), - Calendar(identifier: .islamicTabular), - Calendar(identifier: .islamicUmmAlQura) - ] - - func test_localeIsCached() { - let c = Calendar(identifier: .gregorian) - - let defaultLocale = Locale(identifier: "") - XCTAssertEqual(c.locale, defaultLocale) - XCTAssertIdentical(c.locale?._locale, defaultLocale._locale) - } - - func test_copyOnWrite() { - var c = Calendar(identifier: .gregorian) - let c2 = c - XCTAssertEqual(c, c2) - - // Change the weekday and check result - let firstWeekday = c.firstWeekday - let newFirstWeekday = firstWeekday < 7 ? firstWeekday + 1 : firstWeekday - 1 - - c.firstWeekday = newFirstWeekday - XCTAssertEqual(newFirstWeekday, c.firstWeekday) - XCTAssertEqual(c2.firstWeekday, firstWeekday) - - XCTAssertNotEqual(c, c2) - - // Change the time zone and check result - let c3 = c - XCTAssertEqual(c, c3) - - let tz = c.timeZone - // Use two different identifiers so we don't fail if the current time zone happens to be the one returned - let aTimeZoneId = TimeZone.knownTimeZoneIdentifiers[1] - let anotherTimeZoneId = TimeZone.knownTimeZoneIdentifiers[0] - - let newTz = tz.identifier == aTimeZoneId ? TimeZone(identifier: anotherTimeZoneId)! : TimeZone(identifier: aTimeZoneId)! - - c.timeZone = newTz - - // Do it again! Now it's unique - c.timeZone = newTz - - XCTAssertNotEqual(c, c3) - - } - - func test_equality() { - let autoupdating = Calendar.autoupdatingCurrent - let autoupdating2 = Calendar.autoupdatingCurrent - - XCTAssertEqual(autoupdating, autoupdating2) - - let current = Calendar.current - - XCTAssertNotEqual(autoupdating, current) - - // Make a copy of current - var current2 = current - XCTAssertEqual(current, current2) - - // Mutate something (making sure we don't use the current time zone) - if current2.timeZone.identifier == "America/Los_Angeles" { - current2.timeZone = TimeZone(identifier: "America/New_York")! - } else { - current2.timeZone = TimeZone(identifier: "America/Los_Angeles")! - } - XCTAssertNotEqual(current, current2) - - // Mutate something else - current2 = current - XCTAssertEqual(current, current2) - - current2.locale = Locale(identifier: "MyMadeUpLocale") - XCTAssertNotEqual(current, current2) - } - - func test_hash() { - let calendars: [Calendar] = [ - Calendar.autoupdatingCurrent, - Calendar(identifier: .buddhist), - Calendar(identifier: .gregorian), - Calendar(identifier: .islamic), - Calendar(identifier: .iso8601), - ] - checkHashable(calendars, equalityOracle: { $0 == $1 }) - - // autoupdating calendar isn't equal to the current, even though it's - // likely to be the same. - let calendars2: [Calendar] = [ - Calendar.autoupdatingCurrent, - Calendar.current, - ] - checkHashable(calendars2, equalityOracle: { $0 == $1 }) - } - - func test_AnyHashableContainingCalendar() { - let values: [Calendar] = [ - Calendar(identifier: .gregorian), - Calendar(identifier: .japanese), - Calendar(identifier: .japanese) - ] - let anyHashables = values.map(AnyHashable.init) - expectEqual(Calendar.self, type(of: anyHashables[0].base)) - expectEqual(Calendar.self, type(of: anyHashables[1].base)) - expectEqual(Calendar.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) - } - - func decodeHelper(_ l: Calendar) -> Calendar { - let je = JSONEncoder() - let data = try! je.encode(l) - let jd = JSONDecoder() - return try! jd.decode(Calendar.self, from: data) - } - - func test_serializationOfCurrent() { - let current = Calendar.current - let decodedCurrent = decodeHelper(current) - XCTAssertEqual(decodedCurrent, current) - - let autoupdatingCurrent = Calendar.autoupdatingCurrent - let decodedAutoupdatingCurrent = decodeHelper(autoupdatingCurrent) - XCTAssertEqual(decodedAutoupdatingCurrent, autoupdatingCurrent) - - XCTAssertNotEqual(decodedCurrent, decodedAutoupdatingCurrent) - XCTAssertNotEqual(current, autoupdatingCurrent) - XCTAssertNotEqual(decodedCurrent, autoupdatingCurrent) - XCTAssertNotEqual(current, decodedAutoupdatingCurrent) - - // Calendar, unlike TimeZone and Locale, has some mutable properties - var modified = Calendar.autoupdatingCurrent - modified.firstWeekday = 6 - let decodedModified = decodeHelper(modified) - XCTAssertNotEqual(decodedModified, autoupdatingCurrent) - XCTAssertEqual(modified, decodedModified) - } - - static func validateOrdinality(_ expected: Array>, calendar: Calendar, date: Date) { - let units: [Calendar.Component] = [.era, .year, .month, .day, .hour, .minute, .second, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .nanosecond] - - var smallerIndex = 0 - for smaller in units { - var largerIndex = 0 - for larger in units { - let ordinality = calendar.ordinality(of: smaller, in: larger, for: date) - let expected = expected[largerIndex][smallerIndex] - XCTAssertEqual(ordinality, expected, "Unequal for \(smaller) in \(larger)") - largerIndex += 1 - } - smallerIndex += 1 - } - } - - func validateRange(_ expected: Array?>>, calendar: Calendar, date: Date) { - let units: [Calendar.Component] = [.era, .year, .month, .day, .hour, .minute, .second, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .nanosecond] - - var smallerIndex = 0 - for smaller in units { - var largerIndex = 0 - for larger in units { - let range = calendar.range(of: smaller, in: larger, for: date) - let expected = expected[largerIndex][smallerIndex] - XCTAssertEqual(range, expected, "Unequal for \(smaller) in \(larger)") - largerIndex += 1 - } - smallerIndex += 1 - } - } - - func compareOrdinality(at date: Date, calendar1: Calendar, calendar2: Calendar) { - let units: [Calendar.Component] = [.era, .year, .month, .day, .hour, .minute, .second, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .nanosecond] - - var smallerIndex = 0 - for smaller in units { - print("--- \(smaller)") - var largerIndex = 0 - for larger in units { - let ordinality1 = calendar1.ordinality(of: smaller, in: larger, for: date) - let ordinality2 = calendar2.ordinality(of: smaller, in: larger, for: date) - if ordinality1 != ordinality2 { - print("Mismatch for \(smaller) in \(larger): \(String(describing: ordinality1)) \(String(describing: ordinality2))") - } - largerIndex += 1 - } - smallerIndex += 1 - } - } - - // This test requires 64-bit integers - #if arch(x86_64) || arch(arm64) - func test_ordinality() { - let expected: Array> = [ - /* [era, year, month, day, hour, minute, second, weekday, weekdayOrdinal, quarter, weekOfMonth, weekOfYear, yearForWeekOfYear, nanosecond] */ - /* era */ [nil, 2022, 24260, 738389, 17721328, 1063279623, 63796777359, 105484, 105484, 8087, 105485, 105485, 2022, nil], - /* year */ [nil, nil, 8, 234, 5608, 336423, 20185359, 34, 34, 3, nil, 35, nil, 20185358712306977], - /* month */ [nil, nil, nil, 22, 520, 31143, 1868559, 4, 4, nil, 4, nil, nil, 1868558712306977], - /* day */ [nil, nil, nil, nil, 16, 903, 54159, nil, nil, nil, nil, nil, nil, 54158712306977], - /* hour */ [nil, nil, nil, nil, nil, 3, 159, nil, nil, nil, nil, nil, nil, 158712306977], - /* minute */ [nil, nil, nil, nil, nil, nil, 39, nil, nil, nil, nil, nil, nil, 38712306977], - /* second */ [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 712306977], - /* weekday */ [nil, nil, nil, nil, 16, 903, 54159, nil, nil, nil, nil, nil, nil, 54158712306977], - /* weekdayOrdinal */ [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], - /* quarter */ [nil, nil, 2, 53, 1264, 75783, 4546959, 8, 8, nil, 9, 9, nil, 4546958712306977], - /* weekOfMonth */ [nil, nil, nil, 2, 40, 2343, 140559, 2, nil, nil, nil, nil, nil, 140558712306977], - /* weekOfYear */ [nil, nil, nil, 2, 40, 2343, 140559, 2, nil, nil, nil, nil, nil, 140558712306977], - /* yearForWeekOfYear */ [nil, nil, nil, 240, 5737, 344161, 20649601, 35, 35, nil, nil, 35, nil, 20649600712306977], - /* nanosecond */ [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil] - ] - - // An arbitrary date, for which we know the answers - // August 22, 2022 at 3:02:38 PM PDT - var calendar = Calendar(identifier: .gregorian) - calendar.timeZone = TimeZone(identifier: "America/Los_Angeles")! - Self.validateOrdinality(expected, calendar: calendar, date: Date(timeIntervalSinceReferenceDate: 682898558.712307)) - } - - func test_ordinality_dst() { - let expected: Array> = [ - /* [era, year, month, day, hour, minute, second, weekday, weekdayOrdinal, quarter, weekOfMonth, weekOfYear, yearForWeekOfYear, nanosecond] */ - /* era */ [nil, 2022, 24255, 738227, 17717428, 1063045623, 63782737329, 105461, 105461, 8085, 105461, 105461, 2022, nil], - /* year */ [nil, nil, 3, 72, 1708, 102423, 6145329, 11, 11, 1, nil, 12, nil, 6145328712000013], - /* month */ [nil, nil, nil, 13, 292, 17463, 1047729, 2, 2, nil, 3, nil, nil, 1047728712000013], - /* day */ [nil, nil, nil, nil, 4, 183, 10929, nil, nil, nil, nil, nil, nil, 10928712000013], - /* hour */ [nil, nil, nil, nil, nil, 3, 129, nil, nil, nil, nil, nil, nil, 128712000013], - /* minute */ [nil, nil, nil, nil, nil, nil, 9, nil, nil, nil, nil, nil, nil, 8712000013], - /* second */ [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 712000013], - /* weekday */ [nil, nil, nil, nil, 4, 183, 10929, nil, nil, nil, nil, nil, nil, 10928712000013], - /* weekdayOrdinal */ [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], - /* quarter */ [nil, nil, 3, 72, 1708, 102423, 6145329, 11, 11, nil, 12, 12, nil, 6145328712000013], - /* weekOfMonth */ [nil, nil, nil, 1, 4, 183, 10929, 1, nil, nil, nil, nil, nil, 10928712000013], - /* weekOfYear */ [nil, nil, nil, 1, 4, 183, 10929, 1, nil, nil, nil, nil, nil, 10928712000013], - /* yearForWeekOfYear */ [nil, nil, nil, 78, 1849, 110881, 6652801, 12, 12, nil, nil, 12, nil, 6652800712000013], - /* nanosecond */ [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil] - ] - - // A date which corresponds to a DST transition in Pacific Time - // let d = try! Date("2022-03-13T03:02:08.712-07:00", strategy: .iso8601) - var calendar = Calendar(identifier: .gregorian) - calendar.timeZone = TimeZone(identifier: "America/Los_Angeles")! - Self.validateOrdinality(expected, calendar: calendar, date: Date(timeIntervalSinceReferenceDate: 668858528.712)) - } - #endif // arch(x86_64) || arch(arm64) - - // This test requires 64-bit integers - #if (arch(x86_64) || arch(arm64)) && FOUNDATION_FRAMEWORK - func test_multithreadedCalendarAccess() { - let expected: Array> = [ - /* [era, year, month, day, hour, minute, second, weekday, weekdayOrdinal, quarter, weekOfMonth, weekOfYear, yearForWeekOfYear, nanosecond] */ - /* era */ [nil, 2022, 24260, 738389, 17721328, 1063279623, 63796777359, 105484, 105484, 8087, 105485, 105485, 2022, nil], - /* year */ [nil, nil, 8, 234, 5608, 336423, 20185359, 34, 34, 3, nil, 35, nil, 20185358712306977], - /* month */ [nil, nil, nil, 22, 520, 31143, 1868559, 4, 4, nil, 4, nil, nil, 1868558712306977], - /* day */ [nil, nil, nil, nil, 16, 903, 54159, nil, nil, nil, nil, nil, nil, 54158712306977], - /* hour */ [nil, nil, nil, nil, nil, 3, 159, nil, nil, nil, nil, nil, nil, 158712306977], - /* minute */ [nil, nil, nil, nil, nil, nil, 39, nil, nil, nil, nil, nil, nil, 38712306977], - /* second */ [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 712306977], - /* weekday */ [nil, nil, nil, nil, 16, 903, 54159, nil, nil, nil, nil, nil, nil, 54158712306977], - /* weekdayOrdinal */ [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], - /* quarter */ [nil, nil, 2, 53, 1264, 75783, 4546959, 8, 8, nil, 9, 9, nil, 4546958712306977], - /* weekOfMonth */ [nil, nil, nil, 2, 40, 2343, 140559, 2, nil, nil, nil, nil, nil, 140558712306977], - /* weekOfYear */ [nil, nil, nil, 2, 40, 2343, 140559, 2, nil, nil, nil, nil, nil, 140558712306977], - /* yearForWeekOfYear */ [nil, nil, nil, 240, 5737, 344161, 20649601, 35, 35, nil, nil, 35, nil, 20649600712306977], - /* nanosecond */ [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil] - ] - - // An arbitrary date, for which we know the answers - // August 22, 2022 at 3:02:38 PM PDT - let date = Date(timeIntervalSinceReferenceDate: 682898558.712307) - - // Explicitly shared amongst all the below threads - turn off Sendable checking because we are intentionally racing on this type to test its thread safety - var calendar = Calendar(identifier: .gregorian) - calendar.timeZone = TimeZone(identifier: "America/Los_Angeles")! - - let immutableCalendar = calendar - let group = DispatchGroup() - let queue = DispatchQueue(label: "calendar test", qos: .default, attributes: .concurrent, autoreleaseFrequency: .workItem) - for _ in 1..<10 { - queue.async(group: group) { - Self.validateOrdinality(expected, calendar: immutableCalendar, date: date) - } - } - XCTAssertEqual(.success, group.wait(timeout: .now().advanced(by: .seconds(3)))) - } - #endif // (arch(x86_64) || arch(arm64)) && FOUNDATION_FRAMEWORK - - func test_range() { - let expected : [[Range?]] = - [[nil, 1..<144684, 1..<13, 1..<32, 0..<24, 0..<60, 0..<60, 1..<8, 1..<6, 1..<5, 1..<7, 1..<54, nil, 0..<1_000_000_000], - [nil, nil, 1..<13, 1..<366, 0..<24, 0..<60, 0..<60, 1..<8, 1..<60, 1..<5, 1..<64, 1..<54, nil, 0..<1_000_000_000], - [nil, nil, nil, 1..<32, 0..<24, 0..<60, 0..<60, 1..<8, 1..<6, nil, 1..<6, 32..<37, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, 0..<24, 0..<60, 0..<60, nil, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, nil, 0..<60, 0..<60, nil, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, nil, nil, 0..<60, nil, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, 0..<24, 0..<60, 0..<60, nil, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], - [nil, nil, 7..<10, 1..<93, 0..<24, 0..<60, 0..<60, 1..<8, 1..<16, nil, 1..<17, 27..<41, nil, 0..<1_000_000_000], - [nil, nil, nil, 21..<28, 0..<24, 0..<60, 0..<60, 1..<8, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, 0..<24, 0..<60, 0..<60, 1..<8, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, 1..<397, 0..<24, 0..<60, 0..<60, 1..<8, 1..<65, nil, nil, 1..<54, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]] - - // An arbitrary date, for which we know the answers - // August 22, 2022 at 3:02:38 PM PDT - let date = Date(timeIntervalSinceReferenceDate: 682898558.712307) - let calendar = Calendar(identifier: .gregorian) - - validateRange(expected, calendar: calendar, date: date) - } - - func test_range_dst() { - let expected : [[Range?]] = - [[nil, 1..<144684, 1..<13, 1..<32, 0..<24, 0..<60, 0..<60, 1..<8, 1..<6, 1..<5, 1..<7, 1..<54, nil, 0..<1_000_000_000], - [nil, nil, 1..<13, 1..<366, 0..<24, 0..<60, 0..<60, 1..<8, 1..<60, 1..<5, 1..<64, 1..<54, nil, 0..<1_000_000_000], - [nil, nil, nil, 1..<32, 0..<24, 0..<60, 0..<60, 1..<8, 1..<6, nil, 1..<6, 10..<15, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, 0..<24, 0..<60, 0..<60, nil, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, nil, 0..<60, 0..<60, nil, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, nil, nil, 0..<60, nil, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, 0..<24, 0..<60, 0..<60, nil, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], - [nil, nil, 1..<4, 1..<91, 0..<24, 0..<60, 0..<60, 1..<8, 1..<15, nil, 1..<17, 1..<15, nil, 0..<1_000_000_000], - [nil, nil, nil, 13..<20, 0..<24, 0..<60, 0..<60, 1..<8, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, 0..<24, 0..<60, 0..<60, 1..<8, nil, nil, nil, nil, nil, 0..<1_000_000_000], - [nil, nil, nil, 1..<397, 0..<24, 0..<60, 0..<60, 1..<8, 1..<65, nil, nil, 1..<54, nil, 0..<1_000_000_000], - [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]] - - // A date which corresponds to a DST transition in Pacific Time - // let d = try! Date("2022-03-13T03:02:08.712-07:00", strategy: .iso8601) - validateRange(expected, calendar: Calendar(identifier: .gregorian), date: Date(timeIntervalSinceReferenceDate: 668858528.712)) - } - - // This test requires 64-bit integers - #if arch(x86_64) || arch(arm64) - func test_addingLargeValues() { - let dc = DateComponents(month: 3, day: Int(Int32.max) + 10) - let date = Date.now - let result = Calendar(identifier: .gregorian).date(byAdding: dc, to: date) - XCTAssertNotNil(result) - } - #endif // arch(x86_64) || arch(arm64) - - func test_chineseYearlessBirthdays() { - var gregorian = Calendar(identifier: .gregorian) - gregorian.timeZone = TimeZone(identifier: "UTC")! - let threshold = gregorian.date(from: DateComponents(era: 1, year: 1605, month: 1, day: 1, hour: 0, minute: 0, second: 0, nanosecond: 0))! - - var calendar = Calendar(identifier: .chinese) - calendar.timeZone = TimeZone(identifier: "UTC")! - var components = DateComponents(calendar: calendar, month: 9, day: 1) - components.isLeapMonth = true - // TimeZone.default points to GTC on Linux - components.timeZone = TimeZone(identifier: "America/Los_Angeles") - components.era = nil - - var foundDate: Date? - var count = 0 - var loopedForever = false - components.calendar!.enumerateDates(startingAfter: threshold, matching: components, matchingPolicy: .strict, direction: .backward) { result, exactMatch, stop in - count += 1 - if exactMatch { - foundDate = result - stop = true - } else if count > 5 { - loopedForever = true - stop = true - } - } - - XCTAssertFalse(loopedForever) - XCTAssertNotNil(foundDate) - // Expected 1126-10-18 07:52:58 +0000 - XCTAssertEqual(foundDate!.timeIntervalSinceReferenceDate, -27586714022) - } - - func test_dateFromComponentsNearDSTTransition() { - let comps = DateComponents(year: 2021, month: 11, day: 7, hour: 1, minute: 45) - var cal = Calendar(identifier: .gregorian) - cal.timeZone = TimeZone(abbreviation: "PDT")! - let result = cal.date(from: comps) - XCTAssertEqual(result?.timeIntervalSinceReferenceDate, 657967500) - } - - func test_dayInWeekOfMonth() { - let cal = Calendar(identifier: .chinese) - // A very specific date for which we know a call into ICU produces an unusual result - let date = Date(timeIntervalSinceReferenceDate: 1790212894.000224) - let result = cal.range(of: .day, in: .weekOfMonth, for: date) - XCTAssertNotNil(result) - } - - func test_dateBySettingNearDSTTransition() { - let cal = Calendar(identifier: .gregorian) - let midnightDate = Date(timeIntervalSinceReferenceDate: 689673600.0) // 2022-11-09 08:00:00 +0000 - // A compatibility behavior of `DateComponents` interop with `NSDateComponents` is that it must accept `Int.max` (NSNotFound) the same as `nil`. - let result = cal.date(bySettingHour: 15, minute: 6, second: Int.max, of: midnightDate) - XCTAssertNotNil(result) - } - - func test_properties() { - var c = Calendar(identifier: .gregorian) - // Use english localization - c.locale = Locale(identifier: "en_US") - c.timeZone = TimeZone(identifier: "America/Los_Angeles")! - - // The idea behind these tests is not to test calendrical math, but to simply verify that we are getting some kind of result from calling through to the underlying Foundation and ICU logic. If we move that logic into this struct in the future, then we will need to expand the test cases. - - // This is a very special Date in my life: the exact moment when I wrote these test cases and therefore knew all of the answers. - let d = Date(timeIntervalSince1970: 1468705593.2533731) - let earlierD = c.date(byAdding: DateComponents(day: -10), to: d)! - - XCTAssertEqual(1..<29, c.minimumRange(of: .day)) - XCTAssertEqual(1..<54, c.maximumRange(of: .weekOfYear)) - XCTAssertEqual(0..<60, c.range(of: .second, in: .minute, for: d)) - - var d1 = Date() - var ti : TimeInterval = 0 - - XCTAssertTrue(c.dateInterval(of: .day, start: &d1, interval: &ti, for: d)) - XCTAssertEqual(Date(timeIntervalSince1970: 1468652400.0), d1) - XCTAssertEqual(86400, ti) - - let dateInterval = c.dateInterval(of: .day, for: d) - XCTAssertEqual(DateInterval(start: d1, duration: ti), dateInterval) - - XCTAssertEqual(15, c.ordinality(of: .hour, in: .day, for: d)) - - XCTAssertEqual(Date(timeIntervalSince1970: 1468791993.2533731), c.date(byAdding: .day, value: 1, to: d)) - XCTAssertEqual(Date(timeIntervalSince1970: 1468791993.2533731), c.date(byAdding: DateComponents(day: 1), to: d)) - - XCTAssertEqual(Date(timeIntervalSince1970: 946627200.0), c.date(from: DateComponents(year: 1999, month: 12, day: 31))) - - let comps = c.dateComponents([.year, .month, .day], from: Date(timeIntervalSince1970: 946627200.0)) - XCTAssertEqual(1999, comps.year) - XCTAssertEqual(12, comps.month) - XCTAssertEqual(31, comps.day) - - XCTAssertEqual(10, c.dateComponents([.day], from: d, to: c.date(byAdding: DateComponents(day: 10), to: d)!).day) - - XCTAssertEqual(30, c.dateComponents([.day], from: DateComponents(year: 1999, month: 12, day: 1), to: DateComponents(year: 1999, month: 12, day: 31)).day) - - XCTAssertEqual(2016, c.component(.year, from: d)) - - XCTAssertEqual(Date(timeIntervalSince1970: 1468652400.0), c.startOfDay(for: d)) - - // Mac OS X 10.9 and iOS 7 had a bug in NSCalendar for hour, minute, and second granularities. - XCTAssertEqual(.orderedSame, c.compare(d, to: d + 10, toGranularity: .minute)) - - XCTAssertFalse(c.isDate(d, equalTo: d + 10, toGranularity: .second)) - XCTAssertTrue(c.isDate(d, equalTo: d + 10, toGranularity: .day)) - - XCTAssertFalse(c.isDate(earlierD, inSameDayAs: d)) - XCTAssertTrue(c.isDate(d, inSameDayAs: d)) - - XCTAssertFalse(c.isDateInToday(earlierD)) - XCTAssertFalse(c.isDateInYesterday(earlierD)) - XCTAssertFalse(c.isDateInTomorrow(earlierD)) - - XCTAssertTrue(c.isDateInWeekend(d)) // 😢 - - XCTAssertTrue(c.dateIntervalOfWeekend(containing: d, start: &d1, interval: &ti)) - - let thisWeekend = DateInterval(start: Date(timeIntervalSince1970: 1468652400.0), duration: 172800.0) - - XCTAssertEqual(thisWeekend, DateInterval(start: d1, duration: ti)) - XCTAssertEqual(thisWeekend, c.dateIntervalOfWeekend(containing: d)) - - XCTAssertTrue(c.nextWeekend(startingAfter: d, start: &d1, interval: &ti)) - - let nextWeekend = DateInterval(start: Date(timeIntervalSince1970: 1469257200.0), duration: 172800.0) - - XCTAssertEqual(nextWeekend, DateInterval(start: d1, duration: ti)) - XCTAssertEqual(nextWeekend, c.nextWeekend(startingAfter: d)) - - // Enumeration - - var count = 0 - var exactCount = 0 - - // Find the days numbered '31' after 'd', allowing the algorithm to move to the next day if required - c.enumerateDates(startingAfter: d, matching: DateComponents(day: 31), matchingPolicy: .nextTime) { result, exact, stop in - // Just stop some arbitrary time in the future - if result! > d + 86400*365 { stop = true } - count += 1 - if exact { exactCount += 1 } - } - - /* - Optional(2016-07-31 07:00:00 +0000) - Optional(2016-08-31 07:00:00 +0000) - Optional(2016-10-01 07:00:00 +0000) - Optional(2016-10-31 07:00:00 +0000) - Optional(2016-12-01 08:00:00 +0000) - Optional(2016-12-31 08:00:00 +0000) - Optional(2017-01-31 08:00:00 +0000) - Optional(2017-03-01 08:00:00 +0000) - Optional(2017-03-31 07:00:00 +0000) - Optional(2017-05-01 07:00:00 +0000) - Optional(2017-05-31 07:00:00 +0000) - Optional(2017-07-01 07:00:00 +0000) - Optional(2017-07-31 07:00:00 +0000) - */ - - XCTAssertEqual(count, 13) - XCTAssertEqual(exactCount, 8) - - - XCTAssertEqual(Date(timeIntervalSince1970: 1469948400.0), c.nextDate(after: d, matching: DateComponents(day: 31), matchingPolicy: .nextTime)) - - - XCTAssertEqual(Date(timeIntervalSince1970: 1468742400.0), c.date(bySetting: .hour, value: 1, of: d)) - - XCTAssertEqual(Date(timeIntervalSince1970: 1468656123.0), c.date(bySettingHour: 1, minute: 2, second: 3, of: d, matchingPolicy: .nextTime)) - - XCTAssertTrue(c.date(d, matchesComponents: DateComponents(month: 7))) - XCTAssertFalse(c.date(d, matchesComponents: DateComponents(month: 7, day: 31))) - } - - func test_leapMonthProperty() throws { - let c = Calendar(identifier: .chinese) - /// 2023-02-20 08:00:00 +0000 -- non-leap month in the Chinese calendar - let d1 = Date(timeIntervalSinceReferenceDate: 698572800.0) - /// 2023-03-22 07:00:00 +0000 -- leap month in the Chinese calendar - let d2 = Date(timeIntervalSinceReferenceDate: 701161200.0) - - var components = DateComponents() - components.isLeapMonth = true - XCTAssertFalse(c.date(d1, matchesComponents: components)) - XCTAssertTrue(c.date(d2, matchesComponents: components)) - components.isLeapMonth = false - XCTAssertTrue(c.date(d1, matchesComponents: components)) - XCTAssertFalse(c.date(d2, matchesComponents: components)) - components.day = 1 - components.isLeapMonth = true - XCTAssertFalse(c.date(d1, matchesComponents: components)) - XCTAssertTrue(c.date(d2, matchesComponents: components)) - } - - func test_addingDeprecatedWeek() throws { - let date = try Date("2024-02-24 01:00:00 UTC", strategy: .iso8601.dateTimeSeparator(.space)) - var dc = DateComponents() - dc.week = 1 - - let calendar = Calendar(identifier: .gregorian) - let oneWeekAfter = calendar.date(byAdding: dc, to: date) - - let expected = date.addingTimeInterval(86400*7) - XCTAssertEqual(oneWeekAfter, expected) - } - - func test_symbols() { - var c = Calendar(identifier: .gregorian) - // Use english localization - c.locale = Locale(identifier: "en_US") - c.timeZone = TimeZone(identifier: "America/Los_Angeles")! - - XCTAssertEqual("AM", c.amSymbol) - XCTAssertEqual("PM", c.pmSymbol) - XCTAssertEqual(["1st quarter", "2nd quarter", "3rd quarter", "4th quarter"], c.quarterSymbols) - XCTAssertEqual(["1st quarter", "2nd quarter", "3rd quarter", "4th quarter"], c.standaloneQuarterSymbols) - XCTAssertEqual(["BC", "AD"], c.eraSymbols) - XCTAssertEqual(["Before Christ", "Anno Domini"], c.longEraSymbols) - XCTAssertEqual(["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"], c.veryShortMonthSymbols) - XCTAssertEqual(["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"], c.veryShortStandaloneMonthSymbols) - XCTAssertEqual(["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], c.shortMonthSymbols) - XCTAssertEqual(["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], c.shortStandaloneMonthSymbols) - XCTAssertEqual(["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], c.monthSymbols) - XCTAssertEqual(["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], c.standaloneMonthSymbols) - XCTAssertEqual(["Q1", "Q2", "Q3", "Q4"], c.shortQuarterSymbols) - XCTAssertEqual(["Q1", "Q2", "Q3", "Q4"], c.shortStandaloneQuarterSymbols) - XCTAssertEqual(["S", "M", "T", "W", "T", "F", "S"], c.veryShortStandaloneWeekdaySymbols) - XCTAssertEqual(["S", "M", "T", "W", "T", "F", "S"], c.veryShortWeekdaySymbols) - XCTAssertEqual(["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], c.shortStandaloneWeekdaySymbols) - XCTAssertEqual(["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], c.shortWeekdaySymbols) - XCTAssertEqual(["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], c.standaloneWeekdaySymbols) - XCTAssertEqual(["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], c.weekdaySymbols) - } - - func test_symbols_not_gregorian() { - var c = Calendar(identifier: .hebrew) - c.locale = Locale(identifier: "en_US") - c.timeZone = TimeZone(identifier: "America/Los_Angeles")! - - XCTAssertEqual("AM", c.amSymbol) - XCTAssertEqual("PM", c.pmSymbol) - XCTAssertEqual( [ "1st quarter", "2nd quarter", "3rd quarter", "4th quarter" ], c.quarterSymbols) - XCTAssertEqual( [ "1st quarter", "2nd quarter", "3rd quarter", "4th quarter" ], c.standaloneQuarterSymbols) - XCTAssertEqual( [ "AM" ], c.eraSymbols) - XCTAssertEqual( [ "AM" ], c.longEraSymbols) - XCTAssertEqual( [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "7" ], c.veryShortMonthSymbols) - XCTAssertEqual( [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "7" ], c.veryShortStandaloneMonthSymbols) - XCTAssertEqual( [ "Tishri", "Heshvan", "Kislev", "Tevet", "Shevat", "Adar I", "Adar", "Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul", "Adar II" ], c.shortMonthSymbols) - XCTAssertEqual( [ "Tishri", "Heshvan", "Kislev", "Tevet", "Shevat", "Adar I", "Adar", "Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul", "Adar II" ], c.shortStandaloneMonthSymbols) - XCTAssertEqual( [ "Tishri", "Heshvan", "Kislev", "Tevet", "Shevat", "Adar I", "Adar", "Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul", "Adar II" ], c.monthSymbols) - XCTAssertEqual( [ "Tishri", "Heshvan", "Kislev", "Tevet", "Shevat", "Adar I", "Adar", "Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul", "Adar II" ], c.standaloneMonthSymbols) - XCTAssertEqual( [ "Q1", "Q2", "Q3", "Q4" ], c.shortQuarterSymbols) - XCTAssertEqual( [ "Q1", "Q2", "Q3", "Q4" ], c.shortStandaloneQuarterSymbols) - XCTAssertEqual( [ "S", "M", "T", "W", "T", "F", "S" ], c.veryShortStandaloneWeekdaySymbols) - XCTAssertEqual( [ "S", "M", "T", "W", "T", "F", "S" ], c.veryShortWeekdaySymbols) - XCTAssertEqual( [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], c.shortStandaloneWeekdaySymbols) - XCTAssertEqual( [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], c.shortWeekdaySymbols) - XCTAssertEqual( [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], c.standaloneWeekdaySymbols) - XCTAssertEqual( [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], c.weekdaySymbols) - - c.locale = Locale(identifier: "es_ES") - XCTAssertEqual("a.\u{202f}m.", c.amSymbol) - XCTAssertEqual("p.\u{202f}m.", c.pmSymbol) - XCTAssertEqual( [ "1.er trimestre", "2.\u{00ba} trimestre", "3.er trimestre", "4.\u{00ba} trimestre" ], c.quarterSymbols) - XCTAssertEqual( [ "1.er trimestre", "2.\u{00ba} trimestre", "3.er trimestre", "4.\u{00ba} trimestre" ], c.standaloneQuarterSymbols) - XCTAssertEqual( [ "AM" ], c.eraSymbols) - XCTAssertEqual( [ "AM" ], c.longEraSymbols) - XCTAssertEqual( [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "7" ], c.veryShortMonthSymbols) - XCTAssertEqual( [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "7" ], c.veryShortStandaloneMonthSymbols) - XCTAssertEqual( [ "tishri", "heshvan", "kislev", "tevet", "shevat", "adar I", "adar", "nisan", "iyar", "sivan", "tamuz", "av", "elul", "adar II" ], c.shortMonthSymbols) - XCTAssertEqual( [ "tishri", "heshvan", "kislev", "tevet", "shevat", "adar I", "adar", "nisan", "iyar", "sivan", "tamuz", "av", "elul", "adar II" ], c.shortStandaloneMonthSymbols) - XCTAssertEqual( [ "tishri", "heshvan", "kislev", "tevet", "shevat", "adar I", "adar", "nisan", "iyar", "sivan", "tamuz", "av", "elul", "adar II" ], c.monthSymbols) - XCTAssertEqual( [ "tishri", "heshvan", "kislev", "tevet", "shevat", "adar I", "adar", "nisan", "iyar", "sivan", "tamuz", "av", "elul", "adar II" ], c.standaloneMonthSymbols) - XCTAssertEqual( [ "T1", "T2", "T3", "T4" ], c.shortQuarterSymbols) - XCTAssertEqual( [ "T1", "T2", "T3", "T4" ], c.shortStandaloneQuarterSymbols) - XCTAssertEqual( [ "D", "L", "M", "X", "J", "V", "S" ], c.veryShortStandaloneWeekdaySymbols) - XCTAssertEqual( [ "D", "L", "M", "X", "J", "V", "S" ], c.veryShortWeekdaySymbols) - XCTAssertEqual( [ "dom", "lun", "mar", "mi\u{00e9}", "jue", "vie", "s\u{00e1}b" ], c.shortStandaloneWeekdaySymbols) - XCTAssertEqual( [ "dom", "lun", "mar", "mi\u{00e9}", "jue", "vie", "s\u{00e1}b" ], c.shortWeekdaySymbols) - XCTAssertEqual( [ "domingo", "lunes", "martes", "mi\u{00e9}rcoles", "jueves", "viernes", "s\u{00e1}bado" ], c.standaloneWeekdaySymbols) - XCTAssertEqual( [ "domingo", "lunes", "martes", "mi\u{00e9}rcoles", "jueves", "viernes", "s\u{00e1}bado" ], c.weekdaySymbols) - } - - func test_weekOfMonthLoop() { - // This test simply needs to not hang or crash - let date = Date(timeIntervalSinceReferenceDate: 2.4499581972890255e+18) - let calendar = Calendar(identifier: .gregorian) - let components = DateComponents(weekOfMonth: 3) - _ = calendar.nextDate(after: date, matching: components, matchingPolicy: .nextTime) - _ = calendar.nextDate(after: date, matching: components, matchingPolicy: .nextTimePreservingSmallerComponents) - _ = calendar.nextDate(after: date, matching: components, matchingPolicy: .previousTimePreservingSmallerComponents) - } - - func test_weekendRangeNilLocale() { - var c = Calendar(identifier: .gregorian) - c.locale = Locale(identifier: "en_001") - - var c_nilLocale = Calendar(identifier: .gregorian) - c_nilLocale.locale = nil - - let date = Date(timeIntervalSince1970: 0) - let weekend = c.nextWeekend(startingAfter: date) - let weekendForNilLocale = c_nilLocale.nextWeekend(startingAfter: date) - XCTAssertNotNil(weekend) - XCTAssertEqual(weekend, weekendForNilLocale) - } - - func test_datesAdding_range() { - let startDate = Date(timeIntervalSinceReferenceDate: 689292158.712307) // 2022-11-04 22:02:38 UTC - let endDate = startDate + (86400 * 3) + (3600 * 2) // 3 days + 2 hours later - cross a DST boundary which adds a day with an additional hour in it - var cal = Calendar(identifier: .gregorian) - let tz = TimeZone(name: "America/Los_Angeles")! - cal.timeZone = tz - - // Purpose of this test is not to test the addition itself (we have others for that), but to smoke test the wrapping API - let numberOfDays = Array(cal.dates(byAdding: .day, startingAt: startDate, in: startDate.. unboundedBackward.last!) - } - - func test_dayOfYear_bounds() { - let date = Date(timeIntervalSinceReferenceDate: 682898558.712307) // 2022-08-22 22:02:38 UTC, day 234 - var cal = Calendar(identifier: .gregorian) - let tz = TimeZone.gmt - cal.timeZone = tz - - // Test some invalid day of years - var dayOfYearComps = DateComponents() - dayOfYearComps.dayOfYear = 0 - let zeroDay = cal.nextDate(after: date, matching: dayOfYearComps, matchingPolicy: .previousTimePreservingSmallerComponents) - XCTAssertNil(zeroDay) - - dayOfYearComps.dayOfYear = 400 - let futureDay = cal.nextDate(after: date, matching: dayOfYearComps, matchingPolicy: .nextTime) - XCTAssertNil(futureDay) - - // Test subtraction over a year boundary - dayOfYearComps.dayOfYear = 1 - let firstDay = cal.nextDate(after: date, matching: dayOfYearComps, matchingPolicy: .nextTime, direction: .backward) - XCTAssertNotNil(firstDay) - let firstDayComps = cal.dateComponents([.year], from: firstDay!) - let expectationComps = DateComponents(year: 2022) - XCTAssertEqual(firstDayComps, expectationComps) - - var subtractMe = DateComponents() - subtractMe.dayOfYear = -1 - let previousDay = cal.date(byAdding: subtractMe, to: firstDay!) - XCTAssertNotNil(previousDay) - let previousDayComps = cal.dateComponents([.year, .dayOfYear], from: previousDay!) - var previousDayExpectationComps = DateComponents() - previousDayExpectationComps.year = 2021 - previousDayExpectationComps.dayOfYear = 365 - XCTAssertEqual(previousDayComps, previousDayExpectationComps) - } - - func test_dayOfYear() { - // An arbitrary date, for which we know the answers - let date = Date(timeIntervalSinceReferenceDate: 682898558.712307) // 2022-08-22 22:02:38 UTC, day 234 - let leapYearDate = Date(timeIntervalSinceReferenceDate: 745891200) // 2024-08-21 00:00:00 UTC, day 234 - var cal = Calendar(identifier: .gregorian) - let tz = TimeZone.gmt - cal.timeZone = tz - - // Ordinality - XCTAssertEqual(cal.ordinality(of: .dayOfYear, in: .year, for: date), 234) - XCTAssertEqual(cal.ordinality(of: .hour, in: .dayOfYear, for: date), 23) - XCTAssertEqual(cal.ordinality(of: .minute, in: .dayOfYear, for: date), 1323) - XCTAssertEqual(cal.ordinality(of: .second, in: .dayOfYear, for: date), 79359) - - // Nonsense ordinalities. Since day of year is already relative, we don't count the Nth day of year in an era. - XCTAssertEqual(cal.ordinality(of: .dayOfYear, in: .era, for: date), nil) - XCTAssertEqual(cal.ordinality(of: .year, in: .dayOfYear, for: date), nil) - - // Interval - let interval = cal.dateInterval(of: .dayOfYear, for: date) - XCTAssertEqual(interval, DateInterval(start: Date(timeIntervalSinceReferenceDate: 682819200), duration: 86400)) - - // Specific component values - XCTAssertEqual(cal.dateComponents(in: .gmt, from: date).dayOfYear, 234) - XCTAssertEqual(cal.component(.dayOfYear, from: date), 234) - - // Enumeration - let beforeDate = date - (86400 * 3) - let afterDate = date + (86400 * 3) - let startOfDate = cal.startOfDay(for: date) - - var matchingComps = DateComponents(); matchingComps.dayOfYear = 234 - var foundDate = cal.nextDate(after: beforeDate, matching: matchingComps, matchingPolicy: .nextTime) - XCTAssertEqual(foundDate, startOfDate) - - foundDate = cal.nextDate(after: afterDate, matching: matchingComps, matchingPolicy: .nextTime, direction: .backward) - XCTAssertEqual(foundDate, startOfDate) - - // Go over a leap year - let nextFive = Array(cal.dates(byMatching: matchingComps, startingAt: beforeDate).prefix(5)) - let expected = [ - Date(timeIntervalSinceReferenceDate: 682819200), // 2022-08-22 00:00:00 +0000 - Date(timeIntervalSinceReferenceDate: 714355200), // 2023-08-22 00:00:00 +0000 - Date(timeIntervalSinceReferenceDate: 745891200), // 2024-08-21 00:00:00 +0000 - Date(timeIntervalSinceReferenceDate: 777513600), // 2025-08-22 00:00:00 +0000 - Date(timeIntervalSinceReferenceDate: 809049600), // 2026-08-22 00:00:00 +0000 - ] - XCTAssertEqual(nextFive, expected) - - // Ranges - let min = cal.minimumRange(of: .dayOfYear) - let max = cal.maximumRange(of: .dayOfYear) - XCTAssertEqual(min, 1..<366) // hard coded for gregorian - XCTAssertEqual(max, 1..<367) - - XCTAssertEqual(cal.range(of: .dayOfYear, in: .year, for: date), 1..<366) - XCTAssertEqual(cal.range(of: .dayOfYear, in: .year, for: leapYearDate), 1..<367) - - // Addition - let d1 = cal.date(byAdding: .dayOfYear, value: 1, to: date) - XCTAssertEqual(d1, date + 86400) - - // Using setting to go to Jan 1 - let jan1 = cal.date(bySetting: .dayOfYear, value: 1, of: date)! - let jan1Comps = cal.dateComponents([.year, .month, .day], from: jan1) - XCTAssertEqual(jan1Comps.year, 2023) - XCTAssertEqual(jan1Comps.day, 1) - XCTAssertEqual(jan1Comps.month, 1) - - // Using setting to go to Jan 1 - let whatDay = cal.date(bySetting: .dayOfYear, value: 100, of: Date.now)! - let _ = cal.component(.weekday, from: whatDay) - let _ = Calendar.current.component(.weekday, from: Date.now - (86400 * 5)) - - - // Comparison - XCTAssertEqual(cal.compare(date, to: beforeDate, toGranularity: .dayOfYear), .orderedDescending) - XCTAssertEqual(cal.compare(date, to: afterDate, toGranularity: .dayOfYear), .orderedAscending) - XCTAssertEqual(cal.compare(date + 10, to: date, toGranularity: .dayOfYear), .orderedSame) - - // Nonsense day-of-year - var nonsenseDayOfYear = DateComponents() - nonsenseDayOfYear.dayOfYear = 500 - let shouldBeEmpty = Array(cal.dates(byMatching: nonsenseDayOfYear, startingAt: beforeDate)) - XCTAssertTrue(shouldBeEmpty.isEmpty) - } - - func test_dateComponentsFromFarDateCrash() { - // Calling dateComponents(:from:) on a remote date should not crash - let c = Calendar(identifier: .gregorian) - _ = c.dateComponents([.month], from: Date(timeIntervalSinceReferenceDate: 7.968993439840418e+23)) - } - - func test_dateBySettingDay() { - func firstDayOfMonth(_ calendar: Calendar, for date: Date) -> Date? { - var startOfCurrentMonthComponents = calendar.dateComponents(in: calendar.timeZone, from: date) - startOfCurrentMonthComponents.day = 1 - - return calendar.date(from: startOfCurrentMonthComponents) - } - - var iso8601calendar = Calendar(identifier: .iso8601) - iso8601calendar.timeZone = .gmt - - var gregorianCalendar = Calendar(identifier: .gregorian) - gregorianCalendar.timeZone = .gmt - - let date = Date(timeIntervalSince1970: 1609459199) // 2020-12-31T23:59:59Z - XCTAssertEqual(firstDayOfMonth(iso8601calendar, for: date), Date(timeIntervalSinceReferenceDate: 628559999.0)) // 2020-12-01T23:59:59Z - XCTAssertEqual(firstDayOfMonth(gregorianCalendar, for: date), Date(timeIntervalSinceReferenceDate: 628559999.0)) // 2020-12-01T23:59:59Z - - let date2 = Date(timeIntervalSinceReferenceDate: 730860719) // 2024-02-29T00:51:59Z - XCTAssertEqual(firstDayOfMonth(iso8601calendar, for: date2), Date(timeIntervalSinceReferenceDate: 728441519)) // 2024-02-01T00:51:59Z - XCTAssertEqual(firstDayOfMonth(gregorianCalendar, for: date2), Date(timeIntervalSinceReferenceDate: 728441519.0)) // 2024-02-01T00:51:59Z - } - - func test_dateFromComponents_componentsTimeZoneConversion() { - var calendar = Calendar(identifier: .gregorian) - calendar.timeZone = .gmt - - let startOfYearGMT = Date(timeIntervalSince1970: 1577836800) // January 1, 2020 00:00:00 GMT - var components = calendar.dateComponents([.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .dayOfYear, .calendar, .timeZone], from: startOfYearGMT) - let roundtrip = calendar.date(from: components) - XCTAssertEqual(roundtrip, startOfYearGMT) - - components.timeZone = TimeZone(abbreviation: "EST")! - let startOfYearEST = calendar.date(from: components) - - let expected = startOfYearGMT + 3600 * 5 // January 1, 2020 05:00:00 GMT, Jan 1, 2020 00:00:00 EST - XCTAssertEqual(startOfYearEST, expected) - } - - func test_dateComponentsFromDate_componentsTimeZoneConversion2() { - let gmtDate = Date(timeIntervalSinceReferenceDate: 441907261) // "2015-01-03T01:01:01+0900" - let localDate = Date(timeIntervalSinceReferenceDate: 441939661) // "2015-01-03T01:01:01+0000" - - var calendar = Calendar(identifier: .gregorian) - calendar.timeZone = .gmt - - let timeZoneOffset = localDate.timeIntervalSince(gmtDate) - let nearestTimeZone = TimeZone(secondsFromGMT: Int(timeZoneOffset))! - let dateComponents = calendar.dateComponents(in: nearestTimeZone, from: gmtDate) - - XCTAssertEqual(dateComponents.month, 1) - XCTAssertEqual(dateComponents.day, 3) - XCTAssertEqual(dateComponents.year, 2015) - - let date = calendar.date(from: dateComponents)! - let regeneratedDateComponents = calendar.dateComponents(in: nearestTimeZone, from: date) - XCTAssertEqual(dateComponents.month, regeneratedDateComponents.month) - XCTAssertEqual(dateComponents.day, regeneratedDateComponents.day) - XCTAssertEqual(dateComponents.year, regeneratedDateComponents.year) - } - - func test_dateFromComponents() { - var calendar = Calendar(identifier: .gregorian) - calendar.timeZone = .gmt - calendar.minimumDaysInFirstWeek = 1 - calendar.firstWeekday = 1 - - func test(_ dc: DateComponents, _ expectation: Date, file: StaticString = #filePath, line: UInt = #line) { - let date = calendar.date(from: dc)! - XCTAssertEqual(date, expectation, "expect: \(date.timeIntervalSinceReferenceDate)", file: file, line: line) - } - - // The first week of year 2000 is Dec 26, 1999...Jan 1, 2000 - test(.init(weekday: 3, weekOfYear: 1, yearForWeekOfYear: 2000), Date(timeIntervalSinceReferenceDate: -31968000.0)) // 1999-12-28 - test(.init(weekday: 3, weekOfYear: 2, yearForWeekOfYear: 2000), Date(timeIntervalSinceReferenceDate: -31363200.0)) // 2000-01-04 - - test(.init(day: 3, weekOfYear: 1, yearForWeekOfYear: 2000), Date(timeIntervalSinceReferenceDate: -31449600.0)) // 2000-01-03 - // day takes precedence over weekOfYear - test(.init(day: 3, weekOfYear: 2, yearForWeekOfYear: 2000), Date(timeIntervalSinceReferenceDate: -31449600.0)) // 2000-01-03 - - // Week 53 of 1998 is Dec 28, 1998... Jan 3, 1999 - // Monday in the last week of 1998 - test(.init(weekday: 2, weekOfYear: 53, yearForWeekOfYear: 1998), Date(timeIntervalSinceReferenceDate: -63504000.0)) // 1998-12-28 - - // Unreasonable configuration - // Month is ignored - test(.init(month: 3, weekOfYear: 1, yearForWeekOfYear: 2000), Date(timeIntervalSinceReferenceDate: -32140800.0)) // 1999-12-26 - test(.init(month: 1, weekOfYear: 53, yearForWeekOfYear: 1998), Date(timeIntervalSinceReferenceDate: -63590400.0)) // 1998-12-27 - - // year and yearForWeekOfYear - test(.init(year: 2024, weekOfYear: 30, yearForWeekOfYear: 2024), Date(timeIntervalSinceReferenceDate: 743212800.0)) // 2024-07-21 00:00:00 UTC - test(.init(year: 2023, weekOfYear: 1 ,yearForWeekOfYear: 2023), Date(timeIntervalSinceReferenceDate: 694224000.0)) // 2023-01-01T00:00:00Z - test(.init(year: 2023, weekOfYear: 52, yearForWeekOfYear: 2023), Date(timeIntervalSinceReferenceDate: 725068800.0)) // 2023-12-24T00:00:00Z - test(.init(year: 2023, weekOfYear: 53, yearForWeekOfYear: 2023), Date(timeIntervalSinceReferenceDate: 725673600.0)) // 2023-12-31T00:00:00Z - test(.init(year: 2024, weekOfYear: 30, yearForWeekOfYear: 2024), Date(timeIntervalSinceReferenceDate: 743212800.0)) // 2024-07-21T00:00:00Z - test(.init(year: 2024, weekOfYear: 53, yearForWeekOfYear: 2024), Date(timeIntervalSinceReferenceDate: 757123200.0)) // 2024-12-29T00:00:00Z - test(.init(year: 2025, weekOfYear: 1 ,yearForWeekOfYear: 2025), Date(timeIntervalSinceReferenceDate: 757123200.0)) // 2024-12-29T00:00:00Z - test(.init(year: 2024, weekOfYear: 1 ,yearForWeekOfYear: 2025), Date(timeIntervalSinceReferenceDate: 757123200.0)) // 2024-12-29T00:00:00Z - test(.init(year: 2025, weekOfYear: 1 ,yearForWeekOfYear: 2024), Date(timeIntervalSinceReferenceDate: 725673600.0)) // 2023-12-31T00:00:00Z - test(.init(year: 2024, weekOfYear: 52, yearForWeekOfYear: 2025), Date(timeIntervalSinceReferenceDate: 787968000.0)) // 2025-12-21T00:00:00Z - test(.init(year: 2025, weekOfYear: 52, yearForWeekOfYear: 2024), Date(timeIntervalSinceReferenceDate: 756518400.0)) // 2024-12-22T00:00:00Z - test(.init(year: 2024, weekOfYear: 53, yearForWeekOfYear: 2025), Date(timeIntervalSinceReferenceDate: 788572800.0)) // 2025-12-28T00:00:00Z - test(.init(year: 2025, weekOfYear: 53, yearForWeekOfYear: 2024), Date(timeIntervalSinceReferenceDate: 757123200.0)) // 2024-12-29T00:00:00Z - - // year and weekOfYear, not valid setting so the result is just the first day of the year - test(.init(year: 2023, weekOfYear: 1), Date(timeIntervalSinceReferenceDate: 694224000.0)) // 2023-01-01T00:00:00Z - test(.init(year: 2023, weekOfYear: 30), Date(timeIntervalSinceReferenceDate: 694224000.0)) // 2023-01-01T00:00:00Z - test(.init(year: 2023, weekOfYear: 52), Date(timeIntervalSinceReferenceDate: 694224000.0)) // 2023-01-01T00:00:00Z - test(.init(year: 2023, weekOfYear: 53), Date(timeIntervalSinceReferenceDate: 694224000.0)) // 2023-01-01T00:00:00Z - - // weekOfYear and yearForWeekOfYear - test(.init(weekOfYear: 1, yearForWeekOfYear: 2025), Date(timeIntervalSinceReferenceDate: 757123200.0)) // 2024-12-29T00:00:00Z - test(.init(weekOfYear: 52, yearForWeekOfYear: 2025), Date(timeIntervalSinceReferenceDate: 787968000.0)) // 2025-12-21T00:00:00Z - test(.init(weekOfYear: 53, yearForWeekOfYear: 2025), Date(timeIntervalSinceReferenceDate: 788572800.0)) // 2025-12-28T00:00:00Z - - test(.init(weekOfYear: 1, yearForWeekOfYear: 2024), Date(timeIntervalSinceReferenceDate: 725673600.0)) // 2023-12-31T00:00:00Z - test(.init(weekOfYear: 52, yearForWeekOfYear: 2024), Date(timeIntervalSinceReferenceDate: 756518400.0)) // 2024-12-22T00:00:00Z - test(.init(weekOfYear: 53, yearForWeekOfYear: 2024), Date(timeIntervalSinceReferenceDate: 757123200.0)) // 2024-12-29T00:00:00Z - - // weekday ordinal - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3), Date(timeIntervalSinceReferenceDate: -156124800.0)) // 1996-01-21T00:00:00Z - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2), Date(timeIntervalSinceReferenceDate: -156124800.0)) // 1996-01-21T00:00:00Z - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, weekOfYear: 2), Date(timeIntervalSinceReferenceDate: -156124800.0)) // 1996-01-21T00:00:00Z - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, weekOfYear: 4), Date(timeIntervalSinceReferenceDate: -156124800.0)) // 1996-01-21T00:00:00Z - - // yearForWeekOfYear takes precedence over year - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 3, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -188179200.0)) // 1995-01-15T00:00:00Z - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -188179200.0)) // 1995-01-15T00:00:00Z - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 3, weekOfYear: 2, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -188179200.0)) // 1995-01-15T00:00:00Z - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, weekOfYear: 4, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -188179200.0)) // 1995-01-15T00:00:00Z - - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 1, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -189388800.0)) // 1995-01-01T00:00:00Z - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 1, weekOfMonth: 2, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -189388800.0)) // 1995-01-01T00:00:00Z - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 1, weekOfYear: 2, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -189388800.0)) // 1995-01-01T00:00:00Z - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 1, weekOfMonth: 2, weekOfYear: 4, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -189388800.0)) // 1995-01-01T00:00:00Z - - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 1, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -189388800.0)) // 1995-01-01T00:00:00Z - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 1, weekOfMonth: 2, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -189388800.0)) // 1995-01-01T00:00:00Z - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 1, weekOfYear: 2, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -189388800.0)) // 1995-01-01T00:00:00Z - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 1, weekOfMonth: 2, weekOfYear: 4, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -189388800.0)) // 1995-01-01T00:00:00Z - - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -188179200.0)) // 1995-01-15T00:00:00Z - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -188179200.0)) // 1995-01-15T00:00:00Z - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, weekOfYear: 2, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -188179200.0)) // 1995-01-15T00:00:00Z - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, weekOfYear: 4, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -188179200.0)) // 1995-01-15T00:00:00Z - - // weekdayOrdinal takes precedence over other week fields when weekday is set - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 1, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -189388800.0)) // 1995-01-01T00:00:00Z - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 1, weekOfMonth: 2, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -189388800.0)) // 1995-01-01T00:00:00Z - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 1, weekOfYear: 2, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -189388800.0)) // 1995-01-01T00:00:00Z - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 1, weekOfMonth: 2, weekOfYear: 4, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -189388800.0)) // 1995-01-01T00:00:00Z - - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 3, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -188179200.0)) // 1995-01-15T00:00:00Z - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -188179200.0)) // 1995-01-15T00:00:00Z - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 3, weekOfYear: 2, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -188179200.0)) // 1995-01-15T00:00:00Z - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, weekOfYear: 4, yearForWeekOfYear: 1995), Date(timeIntervalSinceReferenceDate: -188179200.0)) // 1995-01-15T00:00:00Z - } - - func test_firstWeekday() { - var calendar = Calendar(identifier: .gregorian) - calendar.locale = Locale(identifier: "en_US") - XCTAssertEqual(calendar.firstWeekday, 1) - - calendar.locale = Locale(identifier: "en_GB") - XCTAssertEqual(calendar.firstWeekday, 2) - - var calendarWithCustomLocale = Calendar(identifier: .gregorian) - calendarWithCustomLocale.locale = Locale(identifier: "en_US", preferences: .init(firstWeekday: [.gregorian: 3])) - XCTAssertEqual(calendarWithCustomLocale.firstWeekday, 3) - - calendarWithCustomLocale.firstWeekday = 5 - XCTAssertEqual(calendarWithCustomLocale.firstWeekday, 5) // Returns the one set directly on Calendar - - var calendarWithCustomLocaleAndCustomWeekday = Calendar(identifier: .gregorian) - calendarWithCustomLocaleAndCustomWeekday.firstWeekday = 2 - calendarWithCustomLocaleAndCustomWeekday.locale = Locale(identifier: "en_US", preferences: .init(firstWeekday: [.gregorian: 3])) - XCTAssertEqual(calendarWithCustomLocaleAndCustomWeekday.firstWeekday, 2) // Returns the one set directly on Calendar even if `.locale` is set later - } - - func test_minDaysInFirstWeek() { - var calendar = Calendar(identifier: .gregorian) - calendar.locale = Locale(identifier: "en_GB") - XCTAssertEqual(calendar.minimumDaysInFirstWeek, 4) - - calendar.minimumDaysInFirstWeek = 5 - XCTAssertEqual(calendar.minimumDaysInFirstWeek, 5) - - var calendarWithCustomLocale = Calendar(identifier: .gregorian) - calendarWithCustomLocale.locale = Locale(identifier: "en_US", preferences: .init(minDaysInFirstWeek: [.gregorian: 6])) - XCTAssertEqual(calendarWithCustomLocale.minimumDaysInFirstWeek, 6) - - var calendarWithCustomLocaleAndCustomMinDays = Calendar(identifier: .gregorian) - calendarWithCustomLocaleAndCustomMinDays.minimumDaysInFirstWeek = 2 - calendarWithCustomLocaleAndCustomMinDays.locale = Locale(identifier: "en_US", preferences: .init(minDaysInFirstWeek: [.gregorian: 6])) - XCTAssertEqual(calendarWithCustomLocaleAndCustomMinDays.minimumDaysInFirstWeek, 2) - - } - - func test_addingZeroComponents() { - var calendar = Calendar(identifier: .gregorian) - let timeZone = TimeZone(identifier: "America/Los_Angeles")! - calendar.timeZone = timeZone - - // 2021-11-07 08:30:00 GMT, which is 2021-11-07 01:30:00 PDT. Daylight saving time ends 30 minutes after this. - let date = Date(timeIntervalSinceReferenceDate: 657966600) - let dateComponents = DateComponents(era: 0, year: 0, month: 0, day: 0, hour: 0, minute: 0, second: 0) - let result = calendar.date(byAdding: dateComponents, to: date) - XCTAssertEqual(date, result) - - let allComponents : [Calendar.Component] = [.era, .year, .month, .day, .hour, .minute, .second] - for component in allComponents { - let res = calendar.date(byAdding: component, value: 0, to: date) - XCTAssertEqual(res, date, "component: \(component)") - } - } - - - func test_addingDaysAndWeeks() throws { - let timeZone = TimeZone(identifier: "America/Los_Angeles")! - var c = Calendar(identifier: .gregorian) - c.timeZone = timeZone - - let s = Date.ISO8601FormatStyle(timeZone: timeZone) - let a = Date(timeIntervalSinceReferenceDate: 731673276) // "2024-03-09T02:34:36-0800", 10:34:36 UTC - let d1_w1 = c.date(byAdding: .init(day: 1, weekOfMonth: 1), to: a)! - let exp = try Date("2024-03-17T02:34:36-0700", strategy: s) - XCTAssertEqual(d1_w1, exp) - - let d8 = c.date(byAdding: .init(day: 8), to: a)! - XCTAssertEqual(d8, exp) - } - - func test_addingDifferencesRoundtrip() throws { - let timeZone = TimeZone(identifier: "America/Los_Angeles")! - var c = Calendar(identifier: .gregorian) - c.timeZone = timeZone - - let s = Date.ISO8601FormatStyle(timeZone: timeZone) - func test(_ start: Date, _ end: Date) throws { - let components = try XCTUnwrap(c.dateComponents([.year, .month, .day, .hour, .minute, .second, .nanosecond, .weekOfMonth], from: start, to: end)) - let added = try XCTUnwrap(c.date(byAdding: components, to: start)) - XCTAssertEqual(added, end, "actual: \(s.format(added)), expected: \(s.format(end))") - } - - // 2024-03-09T02:34:36-0800, 2024-03-17T03:34:36-0700, 10:34:36 UTC - try test(Date(timeIntervalSinceReferenceDate: 731673276), Date(timeIntervalSinceReferenceDate: 732364476)) - - // 2063-03-10T02:27:06-0800, 2063-03-18T03:27:06-0700 - try test(Date(timeIntervalSinceReferenceDate: 1962440826), Date(timeIntervalSinceReferenceDate: 1963132026)) - - // 2024-03-08T02:34:36-0800, 2063-03-18T11:27:06-0700 - try test(Date(timeIntervalSinceReferenceDate: 731586876.690495), Date(timeIntervalSinceReferenceDate: 1963160826.550588)) - - // 2024-03-03T02:34:36-0800, 2024-03-11T02:34:36-0700 - try test(Date(timeIntervalSinceReferenceDate: 731154876), Date(timeIntervalSinceReferenceDate: 731842476)) - } - -#if _pointerBitWidth(_64) // These tests assumes Int is Int64 - func test_dateFromComponentsOverflow() { - let calendar = Calendar(identifier: .gregorian) - - do { - let components = DateComponents(year: -1157442765409226769, month: -1157442765409226769, day: -1157442765409226769) - let date = calendar.date(from: components) - XCTAssertNil(date) - } - - do { - let components = DateComponents(year: -8935141660703064064, month: -8897841259083430780, day: -8897841259083430780) - let date = calendar.date(from: components) - XCTAssertNil(date) - } - - do { - let components = DateComponents(era: 3475652213542486016, year: -1, month: 72056757140062316, day: 7812738666521952255) - let date = calendar.date(from: components) - XCTAssertNil(date) - } - - do { - let components = DateComponents(weekOfYear: -5280832742222096118, yearForWeekOfYear: 182) - let date = calendar.date(from: components) - XCTAssertNil(date) - } - - } - - func test_addDateOverflow() throws { - - do { - let date = Date(timeIntervalSinceReferenceDate: 964779243.351134) - let calendar = Calendar(identifier: .gregorian) - let components = DateComponents(year: 788960010015224562) - let added = calendar.date(byAdding: components, to: date) - XCTAssertNil(added) - } - - do { - let date = Date(timeIntervalSinceReferenceDate: 849248301.169329) - let calendar = Calendar(identifier: .gregorian) - let components = DateComponents(year: 9223372036854775556) - let added = calendar.date(byAdding: components, to: date) - XCTAssertNil(added) - } - } - - func test_dateComponentsFromDateOverflow() { - let calendar = Calendar(identifier: .gregorian) - do { - let dc = calendar.dateComponents([.year], from: Date(timeIntervalSinceReferenceDate: Double(Int64.max))) - _ = calendar.date(from: dc) - } - - do { - let dc = calendar.dateComponents([.yearForWeekOfYear], from: Date(timeIntervalSinceReferenceDate: Double(Int64.max))) - _ = calendar.date(from: dc) - } - } - -#endif - -} - -// MARK: - Bridging Tests -#if FOUNDATION_FRAMEWORK -final class CalendarBridgingTests : XCTestCase { - func test_AnyHashableCreatedFromNSCalendar() { - let values: [NSCalendar] = [ - NSCalendar(identifier: .gregorian)!, - NSCalendar(identifier: .japanese)!, - NSCalendar(identifier: .japanese)!, - ] - let anyHashables = values.map(AnyHashable.init) - expectEqual(Calendar.self, type(of: anyHashables[0].base)) - expectEqual(Calendar.self, type(of: anyHashables[1].base)) - expectEqual(Calendar.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) - } -} -#endif - - -// This test validates the results against FoundationInternationalization's calendar implementation temporarily until we completely ported the calendar -#if false // Disabled because these tests are extensive and have long runtimes to validate full compatibility, they can be enabled locally to validate changes -final class GregorianCalendarCompatibilityTests: XCTestCase { - - func testDateFromComponentsCompatibility() { - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - func test(_ dateComponents: DateComponents, file: StaticString = #filePath, line: UInt = #line) { - let date_new = gregorianCalendar.date(from: dateComponents)! - let date_old = icuCalendar.date(from: dateComponents)! - expectEqual(date_new, date_old) - } - - test(.init(year: 1996, month: 3)) - test(.init(year: 1996, month: 3, day: 1)) - test(.init(year: 1996, month: 3, day: 1, hour: 1)) - test(.init(year: 1996, month: 3, day: 1, hour: 1, minute: 30)) - - test(.init(year: 1996, month: 3, day: 1, hour: 1, minute: 30, second: 49)) - test(.init(year: 1996, month: 3, day: 1, hour: 1, minute: 30, second: 49, nanosecond: 1234567)) - - // weekday - test(.init(year: 1996, month: 3, weekday: 3)) - test(.init(year: 1996, month: 3, weekday: 3, weekdayOrdinal: 2)) - - // week of month - test(.init(year: 1996, month: 3, weekOfMonth: 2)) - test(.init(year: 1996, month: 3, weekday: 3, weekOfMonth: 2)) - test(.init(year: 1996, month: 3, day: 1, weekOfMonth: 2)) - - // overflow - test(.init(year: 1996, month: 1, day: 1, hour: 25)) - - // Gregorian cut off - test(.init(year: 1582, month: 10, day: 14, hour: 23, minute: 59, second: 59)) - test(.init(year: 1582, month: 10, day: 15, hour: 0)) - test(.init(year: 1582, month: 10, day: 15, hour: 12)) - - // no year -- default to year 1 --> needed to use Julian - test(.init()) - test(.init(month: 1, day: 1)) - test(.init(month: 1, day: 1, hour: 1)) - - // both year and yearForWeekOfYear are set - test(.init(year: 2023, weekOfYear: 1, yearForWeekOfYear: 2023)) - test(.init(year: 2023, weekOfYear: 52, yearForWeekOfYear: 2023)) - test(.init(year: 2023, weekOfYear: 53, yearForWeekOfYear: 2023)) - - test(.init(year: 2024, weekOfYear: 30, yearForWeekOfYear: 2024)) - test(.init(year: 2024, weekOfYear: 53, yearForWeekOfYear: 2024)) - - test(.init(year: 2025, weekOfYear: 1, yearForWeekOfYear: 2025)) - - // Conflicting setting of year and yearForWeekOfYear - test(.init(year: 2024, weekOfYear: 1, yearForWeekOfYear: 2025)) - test(.init(year: 2025, weekOfYear: 1, yearForWeekOfYear: 2024)) - test(.init(year: 2024, weekOfYear: 52, yearForWeekOfYear: 2025)) - test(.init(year: 2025, weekOfYear: 52, yearForWeekOfYear: 2024)) - test(.init(year: 2024, weekOfYear: 53, yearForWeekOfYear: 2025)) - test(.init(year: 2025, weekOfYear: 53, yearForWeekOfYear: 2024)) - - test(.init(year: 2023, weekOfYear: 1)) - test(.init(year: 2023, weekOfYear: 30)) - test(.init(year: 2023, weekOfYear: 52)) - test(.init(year: 2023, weekOfYear: 53)) - - test(.init(weekOfYear: 1, yearForWeekOfYear: 2025)) - test(.init(weekOfYear: 1, yearForWeekOfYear: 2024)) - test(.init(weekOfYear: 52, yearForWeekOfYear: 2025)) - test(.init(weekOfYear: 52, yearForWeekOfYear: 2024)) - test(.init(weekOfYear: 53, yearForWeekOfYear: 2025)) - test(.init(weekOfYear: 53, yearForWeekOfYear: 2024)) - - // weekOfMonth and weekOfYear - test(.init(year: 1996, weekOfMonth: 2, weekOfYear: 10)) - test(.init(year: 1996, weekday: 3, weekOfMonth: 2, weekOfYear: 10)) - - // weekday ordinal - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3)) - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2)) - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, weekOfYear: 2)) - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, weekOfYear: 4)) - - // weekday ordinal, year, and WOY - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 1, yearForWeekOfYear: 1995)) - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 1, weekOfMonth: 2, yearForWeekOfYear: 1995)) - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 1, weekOfYear: 2, yearForWeekOfYear: 1995)) - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 1, weekOfMonth: 2, weekOfYear: 4, yearForWeekOfYear: 1995)) - - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 1, yearForWeekOfYear: 1995)) - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 1, weekOfMonth: 2, yearForWeekOfYear: 1995)) - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 1, weekOfYear: 2, yearForWeekOfYear: 1995)) - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 1, weekOfMonth: 2, weekOfYear: 4, yearForWeekOfYear: 1995)) - - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 1, yearForWeekOfYear: 1995)) - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 1, weekOfMonth: 2, yearForWeekOfYear: 1995)) - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 1, weekOfYear: 2, yearForWeekOfYear: 1995)) - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 1, weekOfMonth: 2, weekOfYear: 4, yearForWeekOfYear: 1995)) - - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, yearForWeekOfYear: 1995)) - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, yearForWeekOfYear: 1995)) - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, weekOfYear: 2, yearForWeekOfYear: 1995)) - test(.init(year: 1996, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, weekOfYear: 4, yearForWeekOfYear: 1995)) - - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 3, yearForWeekOfYear: 1995)) - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, yearForWeekOfYear: 1995)) - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 3, weekOfYear: 2, yearForWeekOfYear: 1995)) - test(.init(year: 1995, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, weekOfYear: 4, yearForWeekOfYear: 1995)) - - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 3, yearForWeekOfYear: 1995)) - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, yearForWeekOfYear: 1995)) - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 3, weekOfYear: 2, yearForWeekOfYear: 1995)) - test(.init(year: 1994, weekday: 1, weekdayOrdinal: 3, weekOfMonth: 2, weekOfYear: 4, yearForWeekOfYear: 1995)) - } - - - func testDateFromComponentsCompatibilityCustom() { - - self.continueAfterFailure = false - func test(_ dateComponents: DateComponents, icuCalendar: _CalendarICU, gregorianCalendar: _CalendarGregorian, file: StaticString = #filePath, line: UInt = #line) { - let date_new = gregorianCalendar.date(from: dateComponents)! - let date_old = icuCalendar.date(from: dateComponents)! - expectEqual(date_new, date_old, "dateComponents: \(dateComponents), first weekday: \(gregorianCalendar.firstWeekday), minimumDaysInFirstWeek: \(gregorianCalendar.minimumDaysInFirstWeek)") - } - - // first weekday, min days in first week - do { - for weekday in [0, 1, 4, 8] { - for daysInFirstWeek in [0, 1, 4, 8] { - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: weekday, minimumDaysInFirstWeek: daysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: weekday, minimumDaysInFirstWeek: daysInFirstWeek, gregorianStartDate: nil) - - for y in stride(from: 1582, to: 3000, by: 48) { - for m in stride(from: -30, to: 30, by: 4) { - for d in stride(from: -10, to: 10, by: 3) { - for wd in stride(from: -10, to: 30, by: 5) { - test(.init(year: y, month: m, weekday: d, weekdayOrdinal: wd), icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - } - } - - for d in stride(from: -30, to: 30, by: 5) { - test(.init(year: y, month: m, day: d), icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - } - - for w in stride(from: -8, to: 8, by: 3) { - test(.init(year: y, month: m, weekOfMonth: w), icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - } - } - - for wy in stride(from: 0, to: 60, by: 3) { - test(.init(weekOfYear: wy, yearForWeekOfYear: y), icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - } - } - } - } - } - - // time zone - do { - let tz = TimeZone(secondsFromGMT: 23400)! // UTC+0630 - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: 1, minimumDaysInFirstWeek: 4, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: 1, minimumDaysInFirstWeek: 4, gregorianStartDate: nil) - for m in [-13, -12, -10, -1, 0, 1, 2, 12, 13] { - for d in [-31, -30, -29, -1, 0, 1, 29, 30, 31] { - for h in [-25, -24, -1, 0, 1, 23, 24, 25] { - for mm in stride(from: -120, to: 121, by: 7) { - for ss in stride(from: -120, to: 121, by: 7) { - test(.init(year: 1996, month: m, day: d, hour: h, minute: mm, second: ss), icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(.init(year: 1997, month: m, day: d, hour: h, minute: mm, second: ss), icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(.init(year: 2000, month: m, day: d, hour: h, minute: mm, second: ss), icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - } - } - } - } - } - } - } - - func testDateFromComponentsCompatibility_DaylightSavingTimeZone() { - - let tz = TimeZone(identifier: "America/Los_Angeles")! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: 1, minimumDaysInFirstWeek: 4, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: 1, minimumDaysInFirstWeek: 4, gregorianStartDate: nil) - - func test(_ dateComponents: DateComponents, file: StaticString = #filePath, line: UInt = #line) { - let date_new = gregorianCalendar.date(from: dateComponents)! - let date_old = icuCalendar.date(from: dateComponents)! - expectEqual(date_new, date_old, "dateComponents: \(dateComponents)") - let roundtrip_new = gregorianCalendar.dateComponents([.hour], from: date_new) - let roundtrip_old = icuCalendar.dateComponents([.hour], from: date_new) - XCTAssertEqual(roundtrip_new.hour, roundtrip_old.hour, "dateComponents: \(dateComponents)") - } - - // In daylight saving time - test(.init(year: 2023, month: 10, day: 16)) - test(.init(year: 2023, month: 10, day: 16, hour: 1, minute: 34, second: 52)) - - // Not in daylight saving time - test(.init(year: 2023, month: 11, day: 6)) - - // Before daylight saving time starts - test(.init(year: 2023, month: 3, day: 12)) - test(.init(year: 2023, month: 3, day: 12, hour: 1, minute: 34, second: 52)) - test(.init(year: 2023, month: 3, day: 12, hour: 2, minute: 34, second: 52)) // this time does not exist - - // After daylight saving time starts - test(.init(year: 2023, month: 3, day: 12, hour: 3, minute: 34, second: 52)) - test(.init(year: 2023, month: 3, day: 13, hour: 00)) - - // Before daylight saving time ends - test(.init(year: 2023, month: 11, day: 5)) - test(.init(year: 2023, month: 11, day: 5, hour: 1, minute: 34, second: 52)) // this time happens twice - - // After daylight saving time ends - test(.init(year: 2023, month: 11, day: 5, hour: 2, minute: 34, second: 52)) - test(.init(year: 2023, month: 11, day: 5, hour: 3, minute: 34, second: 52)) - } - - func testDateFromComponents_componentsTimeZone() { - let timeZone = TimeZone.gmt - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - - func test(_ dateComponents: DateComponents, file: StaticString = #filePath, line: UInt = #line) { - let date_new = gregorianCalendar.date(from: dateComponents)! - let date_old = icuCalendar.date(from: dateComponents)! - expectEqual(date_new, date_old, "dateComponents: \(dateComponents)") - } - - let dcCalendar = Calendar(identifier: .japanese, locale: Locale(identifier: ""), timeZone: .init(secondsFromGMT: -25200), firstWeekday: 1, minimumDaysInFirstWeek: 1, gregorianStartDate: nil) - let dc = DateComponents(calendar: nil, timeZone: nil, era: 1, year: 2022, month: 7, day: 9, hour: 10, minute: 2, second: 55, nanosecond: 891000032, weekday: 7, weekdayOrdinal: 2, quarter: 0, weekOfMonth: 2, weekOfYear: 28, yearForWeekOfYear: 2022) - var dc_customCalendarAndTimeZone = dc - dc_customCalendarAndTimeZone.calendar = dcCalendar - dc_customCalendarAndTimeZone.timeZone = .init(secondsFromGMT: 28800) - test(dc_customCalendarAndTimeZone) // calendar.timeZone = .gmt, dc.calendar.timeZone = UTC-7, dc.timeZone = UTC+8 - - var dc_customCalendar = dc - dc_customCalendar.calendar = dcCalendar - dc_customCalendar.timeZone = nil - test(dc_customCalendar) // calendar.timeZone = .gmt, dc.calendar.timeZone = UTC-7, dc.timeZone = nil - - var dc_customTimeZone = dc_customCalendarAndTimeZone - dc_customTimeZone.calendar = nil - dc_customTimeZone.timeZone = .init(secondsFromGMT: 28800) - test(dc_customTimeZone) // calendar.timeZone = .gmt, dc.calendar = nil, dc.timeZone = UTC+8 - - let dcCalendar_noTimeZone = Calendar(identifier: .japanese, locale: Locale(identifier: ""), timeZone: nil, firstWeekday: 1, minimumDaysInFirstWeek: 1, gregorianStartDate: nil) - var dc_customCalendarNoTimeZone_customTimeZone = dc - dc_customCalendarNoTimeZone_customTimeZone.calendar = dcCalendar_noTimeZone - dc_customCalendarNoTimeZone_customTimeZone.timeZone = .init(secondsFromGMT: 28800) - test(dc_customCalendarNoTimeZone_customTimeZone) // calendar.timeZone = .gmt, dc.calendar.timeZone = nil, dc.timeZone = UTC+8 - } - - func testDateFromComponentsCompatibility_RemoveDates() { - - let tz = TimeZone(identifier: "America/Los_Angeles")! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: 1, minimumDaysInFirstWeek: 1, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: 1, minimumDaysInFirstWeek: 1, gregorianStartDate: nil) - - func test(_ dateComponents: DateComponents, file: StaticString = #filePath, line: UInt = #line) { - let date_new = gregorianCalendar.date(from: dateComponents)! - let date_old = icuCalendar.date(from: dateComponents)! - expectEqual(date_new, date_old, "dateComponents: \(dateComponents)") - let roundtrip_new = gregorianCalendar.dateComponents([.hour], from: date_new) - let roundtrip_old = icuCalendar.dateComponents([.hour], from: date_new) - XCTAssertEqual(roundtrip_new.hour, roundtrip_old.hour, "dateComponents: \(dateComponents)") - } - - test(.init(year: 4713, month: 1, day: 1, hour: 0, minute: 0, second: 0, nanosecond: 0, weekday: 2)) - test(.init(year: 4713, month: 1, day: 1, hour: 0, minute: 0, second: 0, nanosecond: 0)) - } - - func testDateComponentsFromDateCompatibility() { - let componentSet = Calendar.ComponentSet([.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .calendar]) - - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: nil, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: nil, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - func test(_ date: Date, icuCalendar: _CalendarICU, gregorianCalendar: _CalendarGregorian, timeZone: TimeZone = .gmt, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) { - let gregResult = gregorianCalendar.dateComponents(componentSet, from: date, in: timeZone) - let icuResult = icuCalendar.dateComponents(componentSet, from: date, in: timeZone) - // The original implementation does not set quarter - expectEqual(gregResult, icuResult, expectQuarter: false, expectCalendar: false, message().appending("\ndate: \(date.timeIntervalSinceReferenceDate), \(date.formatted(.iso8601))\nnew:\n\(gregResult)\nold:\n\(icuResult)"), file: file, line: line) - } - - self.continueAfterFailure = false - let testStrides = stride(from: -864000, to: 864000, by: 100) - let gmtPlusOne = TimeZone(secondsFromGMT: 3600)! - - for timeZoneOffset in stride(from: 0, to: 3600, by: 1800) { - for ti in testStrides { - let date = Date(timeIntervalSince1970: TimeInterval(ti)) - if let timeZone = TimeZone(secondsFromGMT: timeZoneOffset) { - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: timeZone) - } - } - - } - - // test near gregorian start date - do { - let ref = Date(timeIntervalSinceReferenceDate: -13197085200) // 1582-10-20 23:00:00 UTC - - for ti in testStrides { - let date = Date(timeInterval: TimeInterval(ti), since: ref) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: gmtPlusOne) - } - } - - // test day light saving time - do { - let tz = TimeZone(identifier: "America/Los_Angeles")! - XCTAssert(tz.nextDaylightSavingTimeTransition(after: Date(timeIntervalSinceReferenceDate: 0)) != nil) - - let intervalsAroundDSTTransition = [41418000.0, 41425200.0, 25689600.0, 73476000.0, 89197200.0, 57747600.0, 57744000.0, 9972000.0, 25693200.0, 9975600.0, 57751200.0, 25696800.0, 89193600.0, 41421600.0, 73479600.0, 89200800.0, 73472400.0, 9968400.0] - for ti in intervalsAroundDSTTransition { - let date = Date(timeIntervalSince1970: TimeInterval(ti)) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: tz) - } - } - - // test first weekday - do { - for firstWeekday in [0, 1, 3, 10] { - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: nil, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: nil, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - for ti in testStrides { - let date = Date(timeIntervalSince1970: TimeInterval(ti)) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: gmtPlusOne, "firstweekday: \(firstWeekday)") - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: gmtPlusOne) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: gmtPlusOne) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: gmtPlusOne) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: gmtPlusOne) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: gmtPlusOne) - } - } - } - - // test min days in first week - do { - for minDaysInFirstWeek in [0, 1, 3, 10] { - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: nil, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: minDaysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: nil, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: minDaysInFirstWeek, gregorianStartDate: nil) - for ti in testStrides { - let date = Date(timeIntervalSince1970: TimeInterval(ti)) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: gmtPlusOne) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: gmtPlusOne) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: gmtPlusOne) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: gmtPlusOne) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: gmtPlusOne) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, timeZone: gmtPlusOne) - } - } - } - } - - func testDateComponentsFromDateCompatibility_DST() { - let componentSet = Calendar.ComponentSet([.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .calendar]) - - let tz = TimeZone(identifier: "America/Los_Angeles")! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - func test(_ date: Date, icuCalendar: _CalendarICU, gregorianCalendar: _CalendarGregorian, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) { - let gregResult = gregorianCalendar.dateComponents(componentSet, from: date, in: tz) - let icuResult = icuCalendar.dateComponents(componentSet, from: date, in: tz) - // The original implementation does not set quarter - expectEqual(gregResult, icuResult, expectQuarter: false, expectCalendar: false, message().appending("\ndate: \(date.timeIntervalSinceReferenceDate), \(date.formatted(.iso8601))\nnew:\n\(gregResult)\nold:\n\(icuResult)"), file: file, line: line) - } - - let testStrides = stride(from: -864000, to: 864000, by: 100) - - for ti in testStrides { - let date = Date(timeIntervalSince1970: TimeInterval(ti)) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - } - - // test near gregorian start date - do { - let ref = Date(timeIntervalSinceReferenceDate: -13197085200) // 1582-10-20 23:00:00 UTC - - for ti in testStrides { - let date = Date(timeInterval: TimeInterval(ti), since: ref) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - } - } - - // test day light saving time - do { - let intervalsAroundDSTTransition = [41418000.0, 41425200.0, 25689600.0, 73476000.0, 89197200.0, 57747600.0, 57744000.0, 9972000.0, 25693200.0, 9975600.0, 57751200.0, 25696800.0, 89193600.0, 41421600.0, 73479600.0, 89200800.0, 73472400.0, 9968400.0] - for ti in intervalsAroundDSTTransition { - let date = Date(timeIntervalSince1970: TimeInterval(ti)) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - } - } - - // test first weekday - do { - for firstWeekday in [0, 1, 3, 10] { - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - for ti in testStrides { - let date = Date(timeIntervalSince1970: TimeInterval(ti)) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, "firstweekday: \(firstWeekday)") - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - } - } - } - - // test min days in first week - do { - for minDaysInFirstWeek in [0, 1, 3, 10] { - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: minDaysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: minDaysInFirstWeek, gregorianStartDate: nil) - for ti in testStrides { - let date = Date(timeIntervalSince1970: TimeInterval(ti)) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - } - } - } - } - - - func testDateComponentsFromDate_distantDates() { - - let componentSet = Calendar.ComponentSet([.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .calendar]) - func test(_ date: Date, icuCalendar: _CalendarICU, gregorianCalendar: _CalendarGregorian, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) { - let gregResult = gregorianCalendar.dateComponents(componentSet, from: date, in: gregorianCalendar.timeZone) - let icuResult = icuCalendar.dateComponents(componentSet, from: date, in: icuCalendar.timeZone) - // The original implementation does not set quarter - expectEqual(gregResult, icuResult, expectQuarter: false, expectCalendar: false, message().appending("\ndate: \(date.timeIntervalSince1970), \(date.formatted(Date.ISO8601FormatStyle(timeZone: gregorianCalendar.timeZone)))\nnew:\n\(gregResult)\nold:\n\(icuResult)\ndiff:\n\(DateComponents.differenceBetween(gregResult, icuResult, compareQuarter: false) ?? "nil")"), file: file, line: line) - } - - do { - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - test(.distantPast, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(.distantFuture, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(Date(timeIntervalSinceReferenceDate: -211845067200.0), icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - - } - - do { - let tz = TimeZone(identifier: "America/Los_Angeles")! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: tz, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - test(.distantPast, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(.distantFuture, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(Date(timeIntervalSince1970: -210866774822).capped, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - test(Date(timeIntervalSinceReferenceDate: 3161919600), icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - - } - } - - - func testDateComponentsFromDate() { - let componentSet = Calendar.ComponentSet([.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .calendar]) - func test(_ date: Date, icuCalendar: _CalendarICU, gregorianCalendar: _CalendarGregorian, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) { - let gregResult = gregorianCalendar.dateComponents(componentSet, from: date, in: gregorianCalendar.timeZone) - let icuResult = icuCalendar.dateComponents(componentSet, from: date, in: icuCalendar.timeZone) - // The original implementation does not set quarter - - expectEqual(gregResult, icuResult, expectQuarter: false, expectCalendar: false, message().appending("\ndate: \(date.timeIntervalSince1970), \(date.formatted(Date.ISO8601FormatStyle(timeZone: gregorianCalendar.timeZone)))\nnew:\n\(gregResult)\nold:\n\(icuResult)\ndiff:\n\(DateComponents.differenceBetween(gregResult, icuResult, compareQuarter: false) ?? "")"), file: file, line: line) - } - - do { - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - // Properly `floor`ed, the value below is -1 second from reference date - - var date: Date - - date = Date(timeIntervalSinceReferenceDate: -1) // 2001-01-01 00:00:00 +0000 - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - - date = Date(timeIntervalSinceReferenceDate: -1.0012654182354326e-43) // 2001-01-01 00:00:00 +0000 - test(date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) - } - - } - // MARK: - adding - func verifyAdding(_ components: DateComponents, to date: Date, icuCalendar: _CalendarICU, gregorianCalendar: _CalendarGregorian, wrap: Bool = false, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) { - let added_icu = icuCalendar.date(byAdding: components, to: date, wrappingComponents: wrap) - let added_greg = gregorianCalendar.date(byAdding: components, to: date, wrappingComponents: wrap) - guard let added_icu, let added_greg else { - XCTFail("\(message())", file: file, line: line) - return - } - let tz = icuCalendar.timeZone - assert(icuCalendar.timeZone == gregorianCalendar.timeZone) - - let dsc_greg = added_greg.formatted(Date.ISO8601FormatStyle(timeZone: tz)) - let dsc_icu = added_icu.formatted(Date.ISO8601FormatStyle(timeZone: tz)) - expectEqual(added_greg, added_icu, message().appending("components:\(components), greg: \(dsc_greg), icu: \(dsc_icu)"), file: file, line: line) - } - - func testAddComponentsCompatibility_singleField() { - - self.continueAfterFailure = false - func verify(_ date: Date, wrap: Bool, icuCalendar: _CalendarICU, gregorianCalendar: _CalendarGregorian, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) { - for v in stride(from: -100, through: 100, by: 3) { - verifyAdding(DateComponents(component: .era, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .year, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .month, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .day, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .hour, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .minute, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .second, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .weekday, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .weekdayOrdinal, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .weekOfYear, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .weekOfMonth, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .yearForWeekOfYear, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .nanosecond, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - } - } - - let firstWeekday = 1 - let minimumDaysInFirstWeek = 1 - let timeZone = TimeZone.gmt - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - - // Wrap - verify(Date(timeIntervalSince1970: 825638400), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1996 Mar 1, Fri 00:00 - verify(Date(timeIntervalSince1970: 825721200), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1996 Mar 1, Fri 23:00 - verify(Date(timeIntervalSince1970: 825723300), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1996 Mar 1, Fri 23:35 - verify(Date(timeIntervalSince1970: 825638400), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1996 Mar 5, Tue - verify(Date(timeIntervalSince1970: 826588800), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1996 Mar 12, Tue - - // Dates close to Gregorian cutover - verify(Date(timeIntervalSince1970: -12219638400), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1582 Oct 1 - verify(Date(timeIntervalSince1970: -12218515200), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1582 Oct 14 - verify(Date(timeIntervalSince1970: -12219292800), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1582 Oct 15 - verify(Date(timeIntervalSince1970: -12219206400), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1582 Oct 16 - verify(Date(timeIntervalSince1970: -62130067200), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // long time ago - - // No wrap - verify(Date(timeIntervalSince1970: 825638400), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1996 Mar 1, Fri 00:00 - verify(Date(timeIntervalSince1970: 825721200), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1996 Mar 1, Fri 23:00 - verify(Date(timeIntervalSince1970: 825723300), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1996 Mar 1, Fri 23:35 - verify(Date(timeIntervalSince1970: 825638400), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1996 Mar 5, Tue - verify(Date(timeIntervalSince1970: 826588800), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1996 Mar 12, Tue - - // Dates close to Gregorian cutover - verify(Date(timeIntervalSince1970: -12219638400), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1582 Oct 1 - verify(Date(timeIntervalSince1970: -12218515200), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1582 Oct 14 - verify(Date(timeIntervalSince1970: -12219292800), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1582 Oct 15 - verify(Date(timeIntervalSince1970: -12219206400), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // 1582 Oct 16 - verify(Date(timeIntervalSince1970: -62130067200), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar) // long time ago - } - - func testAddComponentsCompatibility_singleField_custom() { - - self.continueAfterFailure = false - func verify(_ date: Date, wrap: Bool, icuCalendar: _CalendarICU, gregorianCalendar: _CalendarGregorian, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) { - for v in stride(from: -100, through: 100, by: 23) { - verifyAdding(DateComponents(component: .era, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .year, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .month, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .day, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .hour, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .minute, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .second, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .weekday, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .weekdayOrdinal, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .weekOfYear, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .weekOfMonth, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .yearForWeekOfYear, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - verifyAdding(DateComponents(component: .nanosecond, value: v)!, to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: wrap, message(), file: file, line: line) - } - } - - for firstWeekday in [0, 1, 7] { - for minimumDaysInFirstWeek in [0, 1, 4, 7] { - for tzOffset in [ 3600, 7200] { - let timeZone = TimeZone(secondsFromGMT: tzOffset)! - let msg = "firstweekday: \(firstWeekday), minimumDaysInFirstWeek: \(minimumDaysInFirstWeek), timeZone: \(timeZone)" - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - // Wrap - verify(Date(timeIntervalSince1970: 825723300), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) // 1996 Mar 1, Fri 23:35 - verify(Date(timeIntervalSince1970: 826588800), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) // 1996 Mar 12, Tue - - // Dates close to Gregorian cutover - verify(Date(timeIntervalSince1970: -12219638400), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) // 1582 Oct 1 - verify(Date(timeIntervalSince1970: -12218515200), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) // 1582 Oct 14 - verify(Date(timeIntervalSince1970: -12219206400), wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) // 1582 Oct 16 - - // Far dates - // FIXME: This is failing - // verify(Date.distantPast, wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) - // verify(Date.distantFuture, wrap: true, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) - - // No Wrap - verify(Date(timeIntervalSince1970: 825723300), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) // 1996 Mar 1, Fri 23:35 - verify(Date(timeIntervalSince1970: 826588800), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) // 1996 Mar 12, Tue - - // Dates close to Gregorian cutover - verify(Date(timeIntervalSince1970: -12219638400), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) // 1582 Oct 1 - verify(Date(timeIntervalSince1970: -12218515200), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) // 1582 Oct 14 - verify(Date(timeIntervalSince1970: -12219206400), wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) // 1582 Oct 16 - - // Far dates - // verify(Date.distantPast, wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) - // verify(Date.distantFuture, wrap: false, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, msg) - } - } - } - } - - func testAddComponentsCompatibility() { - let firstWeekday = 2 - let minimumDaysInFirstWeek = 4 - let timeZone = TimeZone(secondsFromGMT: -3600 * 8)! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - - let march1_1996 = Date(timeIntervalSince1970: 825723300) // 1996 Mar 1, Fri 23:35 - - verifyAdding(.init(day: -1, hour: 1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(month: -1, hour: 1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(month: -1, day: 30), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(year: 4, day: -1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(day: -1, hour: 24), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(day: -1, weekday: 1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(day: -7, weekOfYear: 1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(day: -7, weekOfMonth: 1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(day: -7, weekOfMonth: 1, weekOfYear: 1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - - verifyAdding(.init(day: -1, hour: 1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(month: -1, hour: 1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(month: -1, day: 30), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(year: 4, day: -1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(day: -1, hour: 24), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(day: -1, weekday: 1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(day: -7, weekOfYear: 1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(day: -7, weekOfMonth: 1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(day: -7, weekOfMonth: 1, weekOfYear: 1), to: march1_1996, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - } - - func testAddComponentsCompatibility_DST() { - - - let firstWeekday = 3 - let minimumDaysInFirstWeek = 5 - let timeZone = TimeZone(identifier: "America/Los_Angeles")! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - - var date = Date(timeIntervalSince1970: 846403387.0) // 1996-10-27T01:03:07-0700 - - verifyAdding(.init(day: -1, hour: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(month: -1, hour: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(month: -1, day: 30), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(year: 4, day: -1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(day: -1, hour: 24), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(day: -1, weekday: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(day: -7, weekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(day: -7, weekOfMonth: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(day: -7, weekOfMonth: 1, weekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(hour: 1, yearForWeekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(hour: -1, yearForWeekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(hour: 1, yearForWeekOfYear: -1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(hour: -1, yearForWeekOfYear: -1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(year: -1, day: 2), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) // result is also DST transition day - verifyAdding(.init(weekOfMonth: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(weekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(month: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(month: -12, day: 2), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - - verifyAdding(.init(day: -1, hour: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(month: -1, hour: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(month: -1, day: 30), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(year: 4, day: -1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(year: -1, day: 2), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) // result is also DST transition day - verifyAdding(.init(day: -1, hour: 24), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(day: -1, weekday: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(day: -7, weekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(day: -7, weekOfMonth: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(day: -7, weekOfMonth: 1, weekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(hour: 1, yearForWeekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(hour: -1, yearForWeekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(hour: 1, yearForWeekOfYear: -1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(hour: -1, yearForWeekOfYear: -1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(weekOfMonth: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(weekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(month: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(month: -12, day: 2), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) // Also DST - - date = Date(timeIntervalSince1970: 814953787.0) // 1995-10-29T01:03:07-0700 - verifyAdding(.init(year: 1, day: -2), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) // result is also DST transition day - verifyAdding(.init(hour: 1, yearForWeekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(hour: -1, yearForWeekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(weekOfYear: 43), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(month: 12, day: -2), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) // Also DST - - verifyAdding(.init(year: 1, day: -2), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) // result is also DST transition day - verifyAdding(.init(hour: 1, yearForWeekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(hour: -1, yearForWeekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(weekOfYear: 43), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(month: 12, day: -2), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) // Also DST - - date = Date(timeIntervalSince1970: 846406987.0) // 1996-10-27T01:03:07-0800 - verifyAdding(.init(year: -1, day: 2), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) // result is also DST transition day - verifyAdding(.init(weekOfMonth: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(weekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(month: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - verifyAdding(.init(month: 12, day: -2), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) // Also DST - - verifyAdding(.init(year: -1, day: 2), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) // result is also DST transition day - verifyAdding(.init(weekOfMonth: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(weekOfYear: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(month: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(month: 12, day: -2), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) // Also DST - } - - func testAddComponents() { - let firstWeekday = 1 - let minimumDaysInFirstWeek = 1 - let timeZone = TimeZone(identifier: "America/Edmonton")! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - - var date = Date(timeIntervalSinceReferenceDate: -2976971168) // Some remote dates - verifyAdding(.init(weekday: -1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - - date = Date(timeIntervalSinceReferenceDate: -2977057568.0) - verifyAdding(.init(day: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: false) - } - - func testAddComponentsWrap() { - let timeZone = TimeZone(identifier: "Europe/Rome")! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - let date = Date(timeIntervalSinceReferenceDate: -702180000) // 1978-10-01T23:00:00+0100 - verifyAdding(.init(hour: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - - // Expected - // 10-01 23:00 +0100 - // 10-01 00:00 +0200 (start of 10-01) - // 10-01 01:00 +0200 - // -> 10-01 00:00 +0100 (DST, rewinds back) - } - - func testAddComponentsWrap2() { - let timeZone = TimeZone(identifier: "America/Los_Angeles")! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - var date = Date(timeIntervalSince1970: 814950000.0) // 1995-10-29T00:00:00-0700 - verifyAdding(.init(minute: -1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - verifyAdding(.init(second: 60), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - - date = Date(timeIntervalSince1970: 814953599.0) // 1995-10-29T00:59:59-0700 - verifyAdding(.init(minute: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - } - - func testAddComponentsWrap3_GMT() { - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: .gmt, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - let date = Date(timeIntervalSinceReferenceDate: 2557249259.5) // 2082-1-13 19:00:59.5 +0000 - verifyAdding(.init(day: 1), to: date, icuCalendar: icuCalendar, gregorianCalendar: gregorianCalendar, wrap: true) - } - - - - // MARK: DateInterval - - func testDateIntervalCompatibility() { - let firstWeekday = 2 - let minimumDaysInFirstWeek = 4 - let timeZone = TimeZone(secondsFromGMT: -3600 * 8)! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - - let units: [Calendar.Component] = [.era, .year, .month, .day, .hour, .minute, .second, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .nanosecond] - let dates: [Date] = [ - Date(timeIntervalSince1970: 851990400.0), // 1996-12-30T16:00:00-0800 (1996-12-31T00:00:00Z), - Date(timeIntervalSince1970: 820483200.0), // 1996-01-01T00:00:00-0800 (1996-01-01T08:00:00Z), - Date(timeIntervalSince1970: 828838987.0), // 1996-04-07T01:03:07Z - Date(timeIntervalSince1970: -62135765813.0), // 0001-01-01T01:03:07Z - Date(timeIntervalSince1970: 825723300), // 1996-03-01 - Date(timeIntervalSince1970: -12218515200.0), // 1582-10-14 - ] - - self.continueAfterFailure = false - for date in dates { - for unit in units { - let old = icuCalendar.dateInterval(of: unit, for: date) - let new = gregorianCalendar.dateInterval(of: unit, for: date) - let msg = "unit: \(unit), date: \(date)" - XCTAssertEqual(old?.start, new?.start, msg) - XCTAssertEqual(old?.end, new?.end, msg) - } - } - } - - func testDateIntervalCompatibility_DST() { - let firstWeekday = 2 - let minimumDaysInFirstWeek = 4 - let timeZone = TimeZone(identifier: "America/Los_Angeles")! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - - let units: [Calendar.Component] = [.era, .year, .month, .day, .hour, .minute, .second, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .nanosecond] - let dates: [Date] = [ - Date(timeIntervalSince1970: 828867787.0), // 1996-04-07T01:03:07-0800 - Date(timeIntervalSince1970: 828871387.0), // 1996-04-07T03:03:07-0700 - Date(timeIntervalSince1970: 828874987.0), // 1996-04-07T04:03:07-0700 - Date(timeIntervalSince1970: 846403387.0), // 1996-10-27T01:03:07-0700 - Date(timeIntervalSince1970: 846406987.0), // 1996-10-27T01:03:07-0800 - Date(timeIntervalSince1970: 846410587.0), // 1996-10-27T02:03:07-0800 - ] - - self.continueAfterFailure = false - for date in dates { - for unit in units { - let old = icuCalendar.dateInterval(of: unit, for: date) - let new = gregorianCalendar.dateInterval(of: unit, for: date) - let msg = "unit: \(unit), date: \(date)" - XCTAssertEqual(old?.start, new?.start, msg) - XCTAssertEqual(old?.end, new?.end, msg) - } - } - } - - func testDateInterval() { - let firstWeekday = 1 - let minimumDaysInFirstWeek = 1 - let timeZone = TimeZone(identifier: "America/Edmonton")! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - - let unit: Calendar.Component = .weekday - let date = Date(timeIntervalSinceReferenceDate: -2976971169.0) - let old = icuCalendar.dateInterval(of: unit, for: date) - let new = gregorianCalendar.dateInterval(of: unit, for: date) - let msg = "unit: \(unit), date: \(date)" - XCTAssertEqual(old?.start, new?.start, msg) - XCTAssertEqual(old?.end, new?.end, msg) - } - - func testDateIntervalRemoteDates() { - let firstWeekday = 2 - let minimumDaysInFirstWeek = 4 - let timeZone = TimeZone.gmt - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - - let allComponents : [Calendar.Component] = [.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .dayOfYear, .calendar, .timeZone] - - let dates: [Date] = [ - Date(timeIntervalSinceReferenceDate: -211845067200.0), // 4713-01-01T12:00:00Z - Date(timeIntervalSinceReferenceDate: 200000000000000.0), - Date(timeIntervalSinceReferenceDate: 15927175497600.0), - ] - for (i, date) in dates.enumerated() { - let dc1 = icuCalendar.dateComponents([.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .dayOfYear, .calendar, .timeZone], from: date) - let dc2 = gregorianCalendar.dateComponents([.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .dayOfYear, .calendar, .timeZone], from: date) - expectEqual(dc1, dc2, expectQuarter: false, expectCalendar: false, "failure: \(i)") - for component in allComponents { - let c1 = icuCalendar.dateInterval(of: component, for: date) - let c2 = gregorianCalendar.dateInterval(of: component, for: date) - guard let c1, let c2 else { - if c1 != c2 { - XCTFail("c1: \(String(describing: c1)), c2: \(String(describing: c2)), component: \(component)") - } - return - } - XCTAssertEqual(c1.start, c2.start, "\(component), start diff c1: \(c1.start.timeIntervalSince(date)), c2: \(c2.start.timeIntervalSince(date))") - XCTAssertEqual(c1.end, c2.end, "\(component), end diff c1: \(c1.end.timeIntervalSince(date)) c2: \(c2.end.timeIntervalSince(date))") - } - } - } - - - func testDateInterval_cappedDate_nonGMT() { - let firstWeekday = 2 - let minimumDaysInFirstWeek = 4 - let timeZone = TimeZone(identifier: "America/Los_Angeles")! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - - let allComponents : [Calendar.Component] = [.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .dayOfYear, .calendar, .timeZone] - - let dates: [Date] = [ - Date(timeIntervalSinceReferenceDate: -185185037675833.0).capped, - Date(timeIntervalSinceReferenceDate: -211845067200.0).capped, - Date(timeIntervalSinceReferenceDate: 200000000000000.0).capped, - Date(timeIntervalSinceReferenceDate: 15927175497600.0).capped, - - ] - for (i, date) in dates.enumerated() { - for component in allComponents { - let c1 = icuCalendar.dateInterval(of: component, for: date) - let c2 = gregorianCalendar.dateInterval(of: component, for: date) - XCTAssertEqual(c1, c2, "\(i)") - } - } - } - - // MARK: - First instant - - func testFirstInstant() { - let firstWeekday = 1 - let minimumDaysInFirstWeek = 1 - let timeZone = TimeZone.gmt - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: nil) - - let allComponents: [Calendar.Component] = [.day] - let dates: [Date] = [ - Date(timeIntervalSinceReferenceDate: 15927175497600.0), - ] - for date in dates { - for component in allComponents { - let c1 = icuCalendar.firstInstant(of: component, at: date) - let c2 = gregorianCalendar.firstInstant(of: component, at: date) - guard let c2 else { - XCTFail("unexpected nil first instant") - continue - } - XCTAssertEqual(c1, c2, "c1: \(c1.timeIntervalSinceReferenceDate), c2: \(c2.timeIntervalSinceReferenceDate), \(date.timeIntervalSinceReferenceDate)") - } - } - } - - func testFirstInstantDST() { - let timeZone = TimeZone(identifier: "Europe/Rome")! - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - let allComponents : [Calendar.Component] = [.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .dayOfYear, .calendar, .timeZone] - let date = Date(timeIntervalSinceReferenceDate: -702180000.0) // 1978-10-01T23:00:00+0100 DST date, rewinding back one hour, so 25 hour in this day - for component in allComponents { - let c1 = icuCalendar.firstInstant(of: component, at: date) - let c2 = gregorianCalendar.firstInstant(of: component, at: date) - XCTAssertEqual(c1, c2, "\(date.timeIntervalSinceReferenceDate)") - } - } - - func testDateComponentsFromTo() { - let timeZone = TimeZone(secondsFromGMT: -8*3600) - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let allComponents : Calendar.ComponentSet = [.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .dayOfYear, .calendar, .timeZone] - let d1 = Date(timeIntervalSinceReferenceDate: 0) // 2000-12-31 16:00:00 PT - let d2 = Date(timeIntervalSinceReferenceDate: 5458822.0) // 2001-03-04 20:20:22 PT - let a = icuCalendar.dateComponents(allComponents, from: d1, to: d2) - let b = gregorianCalendar.dateComponents(allComponents, from: d1, to: d2) - expectEqual(a, b) - } - - func testDifference() throws { - let timeZone = TimeZone(secondsFromGMT: -8*3600) - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let d1 = Date(timeIntervalSinceReferenceDate: 0) // 2000-12-31 16:00:00 PT - let d2 = Date(timeIntervalSinceReferenceDate: 5458822.0) // 2001-03-04 20:20:22 PT - let (_, newStart) = try gregorianCalendar.difference(inComponent: .month, from: d1, to: d2) - XCTAssertEqual(newStart.timeIntervalSince1970, 983404800) // 2001-03-01 00:00:00 UTC - } - - func testAdd() throws { - let timeZone = TimeZone(secondsFromGMT: -8*3600)! - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - let dc = DateComponents(year: 2000, month: 14, day: 28, hour: 16, minute: 0, second: 0) - let old = icuCalendar.date(from: dc)! - let new = gregorianCalendar.date(from: dc)! - XCTAssertEqual(old, new) - XCTAssertEqual(old.timeIntervalSince1970, 983404800) - - let d1 = Date(timeIntervalSinceReferenceDate: 0) // 2000-12-31 16:00:00 PT - let added = try gregorianCalendar.add(.month, to: d1, amount: 2, inTimeZone: timeZone) - let gregResult = gregorianCalendar.date(byAdding: .init(month: 2), to: d1, wrappingComponents: false)! - let icuResult = icuCalendar.date(byAdding: .init(month: 2), to: d1, wrappingComponents: false)! - XCTAssertEqual(gregResult, icuResult) - XCTAssertEqual(added, icuResult) - XCTAssertEqual(icuResult.timeIntervalSince1970, 983404800) // 2001-03-01 00:00:00 UTC, 2001-02-28 16:00:00 PT - } - - func testAdd_precision() throws { - let timeZone = TimeZone.gmt - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - - let d1 = Date(timeIntervalSinceReferenceDate: 729900523.547439) - let added = try gregorianCalendar.add(.month, to: d1, amount: -277, inTimeZone: timeZone) - var gregResult: Date - var icuResult: Date - - gregResult = gregorianCalendar.date(byAdding: .init(month: -277), to: d1, wrappingComponents: false)! - icuResult = icuCalendar.date(byAdding: .init(month: -277), to: d1, wrappingComponents: false)! - XCTAssertEqual(gregResult, icuResult, "greg: \(gregResult.timeIntervalSinceReferenceDate), icu: \(icuResult.timeIntervalSinceReferenceDate)") - XCTAssertEqual(added, icuResult) - - let d2 = Date(timeIntervalSinceReferenceDate: -0.4525610214656613) - gregResult = gregorianCalendar.date(byAdding: .init(nanosecond: 500000000), to: d2, wrappingComponents: false)! - icuResult = icuCalendar.date(byAdding: .init(nanosecond: 500000000), to: d2, wrappingComponents: false)! - XCTAssertEqual(gregResult, icuResult, "greg: \(gregResult.timeIntervalSinceReferenceDate), icu: \(icuResult.timeIntervalSinceReferenceDate)") - - let d3 = Date(timeIntervalSinceReferenceDate: 729900523.547439) - gregResult = gregorianCalendar.date(byAdding: .init(year: -60), to: d3, wrappingComponents: false)! - icuResult = icuCalendar.date(byAdding: .init(year: -60), to: d3, wrappingComponents: false)! - XCTAssertEqual(gregResult, icuResult, "greg: \(gregResult.timeIntervalSinceReferenceDate), icu: \(icuResult.timeIntervalSinceReferenceDate)") - } - - func testDateComponentsFromTo_precision() { - let timeZone = TimeZone.gmt - let gregorianCalendar = _CalendarGregorian(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - let icuCalendar = _CalendarICU(identifier: .gregorian, timeZone: timeZone, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil) - - let allComponents : Calendar.ComponentSet = [.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .dayOfYear, .calendar, .timeZone] - let tests: [(Double, Double)] = [ /*start, finish*/ - (0, 1.005), - (0, 1.0005), - (0, 1.4), - (0, 1.5), - (0, 1.6), - (1.005, 0), - ] - - var a: DateComponents - var b: DateComponents - for (i, (ti1, ti2)) in tests.enumerated() { - let d1 = Date(timeIntervalSinceReferenceDate: ti1) - let d2 = Date(timeIntervalSinceReferenceDate: ti2) - a = icuCalendar.dateComponents(allComponents, from: d1, to: d2) - b = gregorianCalendar.dateComponents(allComponents, from: d1, to: d2) - XCTAssertEqual(a, b, "test: \(i)") - - expectEqual(a, b, "test: \(i)") - } - - for (i, (ti1, ti2)) in tests.enumerated() { - let d1 = Date(timeIntervalSinceReferenceDate: ti1) - let d2 = Date(timeIntervalSinceReferenceDate: ti2) - a = icuCalendar.dateComponents([.nanosecond], from: d1, to: d2) - b = gregorianCalendar.dateComponents([.nanosecond], from: d1, to: d2) - XCTAssertEqual(a, b, "test: \(i)") - if ti1 < ti2 { - XCTAssertGreaterThanOrEqual(b.nanosecond!, 0, "test: \(i)") - } else { - XCTAssertLessThanOrEqual(b.nanosecond!, 0, "test: \(i)") - } - expectEqual(a, b, "test: \(i)") - } - - } - -} -#endif diff --git a/Tests/FoundationInternationalizationTests/DateComponentsTests.swift b/Tests/FoundationInternationalizationTests/DateComponentsTests.swift deleted file mode 100644 index e9c9c9242..000000000 --- a/Tests/FoundationInternationalizationTests/DateComponentsTests.swift +++ /dev/null @@ -1,151 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -final class DateComponentsTests : XCTestCase { - - func test_isValidDate() { - let dc = DateComponents(year: 2022, month: 11, day: 1) - XCTAssertTrue(dc.isValidDate(in: Calendar(identifier: .gregorian))) - - let dc2 = DateComponents(year: 2022, month: 11, day: 32) - XCTAssertFalse(dc2.isValidDate(in: Calendar(identifier: .gregorian))) - } - - func test_leapMonth() { - var components = DateComponents() - components.month = 1 - - XCTAssertFalse(components.isLeapMonth ?? true == false) - - components.isLeapMonth = true - - XCTAssertEqual(components.month, 1) - XCTAssertTrue(components.isLeapMonth ?? false == true) - } - - func test_valueForComponent() { - let comps = DateComponents(calendar: nil, timeZone: nil, era: 1, year: 2013, month: 4, day: 2, hour: 20, minute: 33, second: 49, nanosecond: 192837465, weekday: 3, weekdayOrdinal: 1, quarter: nil, weekOfMonth: 1, weekOfYear: 14, yearForWeekOfYear: 2013) - - XCTAssertEqual(comps.value(for: .calendar), nil) - XCTAssertEqual(comps.value(for: .timeZone), nil) - XCTAssertEqual(comps.value(for: .era), 1) - XCTAssertEqual(comps.value(for: .year), 2013) - XCTAssertEqual(comps.value(for: .month), 4) - XCTAssertEqual(comps.value(for: .day), 2) - XCTAssertEqual(comps.value(for: .hour), 20) - XCTAssertEqual(comps.value(for: .minute), 33) - XCTAssertEqual(comps.value(for: .second), 49) - XCTAssertEqual(comps.value(for: .nanosecond), 192837465) - XCTAssertEqual(comps.value(for: .weekday), 3) - XCTAssertEqual(comps.value(for: .weekdayOrdinal), 1) - XCTAssertEqual(comps.value(for: .quarter), nil) - XCTAssertEqual(comps.value(for: .weekOfMonth), 1) - XCTAssertEqual(comps.value(for: .weekOfYear), 14) - XCTAssertEqual(comps.value(for: .yearForWeekOfYear), 2013) - } - - func test_nanosecond() { - var comps = DateComponents(nanosecond: 123456789) - XCTAssertEqual(comps.nanosecond, 123456789) - - comps.year = 2013 - comps.month = 12 - comps.day = 2 - comps.hour = 12 - comps.minute = 30 - comps.second = 45 - - var cal = Calendar(identifier: .gregorian) - cal.timeZone = TimeZone(identifier: "UTC")! - - let dateWithNS = cal.date(from: comps)! - let newComps = cal.dateComponents([.nanosecond], from: dateWithNS) - - let nanosecondsApproximatelyEqual = labs(CLong(newComps.nanosecond!) - 123456789) <= 500 - XCTAssertTrue(nanosecondsApproximatelyEqual) - } - - func testDateComponents() { - // Make sure the optional init stuff works - let dc = DateComponents() - - XCTAssertNil(dc.year) - - let dc2 = DateComponents(year: 1999) - - XCTAssertNil(dc2.day) - XCTAssertEqual(1999, dc2.year) - } - - func test_AnyHashableContainingDateComponents() { - let values: [DateComponents] = [ - DateComponents(year: 2016), - DateComponents(year: 1995), - DateComponents(year: 1995), - ] - let anyHashables = values.map(AnyHashable.init) - expectEqual(DateComponents.self, type(of: anyHashables[0].base)) - expectEqual(DateComponents.self, type(of: anyHashables[1].base)) - expectEqual(DateComponents.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) - } - - func test_weekComponent() { - var calendar = Calendar(identifier: .gregorian) - calendar.timeZone = .gmt - // date(from: "2010-09-08 07:59:54 +0000") - let date = Date(timeIntervalSinceReferenceDate: 305625594.0) - let comps = calendar.dateComponents([.weekOfYear], from: date) - XCTAssertEqual(comps.weekOfYear, 37) - } - - func test_components_fromDate_toDate_options_withEraChange() { - // date(from: "1900-01-01 01:23:34 +0000") - let fromDate = Date(timeIntervalSinceReferenceDate: -3187290986.0) - // date(from: "2010-09-08 07:59:54 +0000") - let toDate = Date(timeIntervalSinceReferenceDate: 305625594.0) - - var calendar = Calendar(identifier: .japanese) - calendar.timeZone = .gmt - - let units: Set = [.era, .year, .month, .day, .hour, .minute, .second] - - let comps = calendar.dateComponents(units, from: fromDate, to: toDate) - - XCTAssertEqual(comps.era, 3) - XCTAssertEqual(comps.year, -10) - XCTAssertEqual(comps.month, -3) - XCTAssertEqual(comps.day, -22) - XCTAssertEqual(comps.hour, -17) - XCTAssertEqual(comps.minute, -23) - XCTAssertEqual(comps.second, -40) - } -} - -// MARK: - FoundationPreview disabled utils -#if FOUNDATION_FRAMEWORK -extension DateComponentsTests { - func date(from string: String, nanoseconds: Int? = nil) -> Date { - let d = try! Date(string, strategy: Date.ParseStrategy(format: "\(year: .extended(minimumLength: 4))-\(month: .twoDigits)-\(day: .twoDigits) \(hour: .twoDigits(clock: .twentyFourHour, hourCycle: .zeroBased)):\(minute: .twoDigits):\(second: .twoDigits) \(timeZone: .iso8601(.short))", locale: Locale(identifier: "en_US"), timeZone: TimeZone.gmt)) - if let nanoseconds { - var comps = Calendar(identifier: .gregorian).dateComponents([.era, .year, .month, .day, .hour, .minute, .second, .nanosecond, .weekday, .weekdayOrdinal, .quarter, .weekOfMonth, .weekOfYear, .yearForWeekOfYear, .timeZone, .calendar], from: d) - return Calendar(identifier: .gregorian).date(from: comps)! - } - return d - } -} -#endif // FOUNDATION_FRAMEWORK diff --git a/Tests/FoundationInternationalizationTests/DateTests+Locale.swift b/Tests/FoundationInternationalizationTests/DateTests+Locale.swift deleted file mode 100644 index 609e47476..000000000 --- a/Tests/FoundationInternationalizationTests/DateTests+Locale.swift +++ /dev/null @@ -1,91 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -// TODO: Reenable these tests once DateFormatStyle has been ported -final class DateLocaleTests : XCTestCase { -#if FOUNDATION_FRAMEWORK - func dateWithString(_ str: String) -> Date { - let formatter = DateFormatter() - // Note: Calendar(identifier:) is OSX 10.9+ and iOS 8.0+ whereas the CF version has always been available - formatter.calendar = Calendar(identifier: .gregorian) - formatter.locale = Locale(identifier: "en_US") - formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z" - return formatter.date(from: str)! as Date - } - - func testEquality() { - let date = dateWithString("2010-05-17 14:49:47 -0700") - let sameDate = dateWithString("2010-05-17 14:49:47 -0700") - XCTAssertEqual(date, sameDate) - XCTAssertEqual(sameDate, date) - - let differentDate = dateWithString("2010-05-17 14:49:46 -0700") - XCTAssertNotEqual(date, differentDate) - XCTAssertNotEqual(differentDate, date) - - let sameDateByTimeZone = dateWithString("2010-05-17 13:49:47 -0800") - XCTAssertEqual(date, sameDateByTimeZone) - XCTAssertEqual(sameDateByTimeZone, date) - - let differentDateByTimeZone = dateWithString("2010-05-17 14:49:47 -0800") - XCTAssertNotEqual(date, differentDateByTimeZone) - XCTAssertNotEqual(differentDateByTimeZone, date) - } - - func testTimeIntervalSinceDate() { - let referenceDate = dateWithString("1900-01-01 00:00:00 +0000") - let sameDate = dateWithString("1900-01-01 00:00:00 +0000") - let laterDate = dateWithString("2010-05-17 14:49:47 -0700") - let earlierDate = dateWithString("1810-05-17 14:49:47 -0700") - - let laterSeconds = laterDate.timeIntervalSince(referenceDate) - XCTAssertEqual(laterSeconds, 3483121787.0) - - let earlierSeconds = earlierDate.timeIntervalSince(referenceDate) - XCTAssertEqual(earlierSeconds, -2828311813.0) - - let sameSeconds = sameDate.timeIntervalSince(referenceDate) - XCTAssertEqual(sameSeconds, 0.0) - } - - func test_DateHashing() { - let values: [Date] = [ - dateWithString("2010-05-17 14:49:47 -0700"), - dateWithString("2011-05-17 14:49:47 -0700"), - dateWithString("2010-06-17 14:49:47 -0700"), - dateWithString("2010-05-18 14:49:47 -0700"), - dateWithString("2010-05-17 15:49:47 -0700"), - dateWithString("2010-05-17 14:50:47 -0700"), - dateWithString("2010-05-17 14:49:48 -0700"), - ] - checkHashable(values, equalityOracle: { $0 == $1 }) - } - - func test_AnyHashableContainingDate() { - let values: [Date] = [ - dateWithString("2016-05-17 14:49:47 -0700"), - dateWithString("2010-05-17 14:49:47 -0700"), - dateWithString("2010-05-17 14:49:47 -0700"), - ] - let anyHashables = values.map(AnyHashable.init) - expectEqual(Date.self, type(of: anyHashables[0].base)) - expectEqual(Date.self, type(of: anyHashables[1].base)) - expectEqual(Date.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) - } -#endif -} diff --git a/Tests/FoundationInternationalizationTests/DecimalTests+Locale.swift b/Tests/FoundationInternationalizationTests/DecimalTests+Locale.swift deleted file mode 100644 index c39b7ff16..000000000 --- a/Tests/FoundationInternationalizationTests/DecimalTests+Locale.swift +++ /dev/null @@ -1,67 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -final class DecimalLocaleTests : XCTestCase { - func test_stringWithLocale() { - let en_US = Locale(identifier: "en_US") - let fr_FR = Locale(identifier: "fr_FR") - - XCTAssertEqual(Decimal(string: "1,234.56")! * 1000, Decimal(1000)) - XCTAssertEqual(Decimal(string: "1,234.56", locale: en_US)! * 1000, Decimal(1000)) - XCTAssertEqual(Decimal(string: "1,234.56", locale: fr_FR)! * 1000, Decimal(1234)) - XCTAssertEqual(Decimal(string: "1.234,56", locale: en_US)! * 1000, Decimal(1234)) - XCTAssertEqual(Decimal(string: "1.234,56", locale: fr_FR)! * 1000, Decimal(1000)) - - XCTAssertEqual(Decimal(string: "-1,234.56")! * 1000, Decimal(-1000)) - XCTAssertEqual(Decimal(string: "+1,234.56")! * 1000, Decimal(1000)) - XCTAssertEqual(Decimal(string: "+1234.56e3"), Decimal(1234560)) - XCTAssertEqual(Decimal(string: "+1234.56E3"), Decimal(1234560)) - XCTAssertEqual(Decimal(string: "+123456000E-3"), Decimal(123456)) - - XCTAssertNil(Decimal(string: "")) - XCTAssertNil(Decimal(string: "x")) - XCTAssertEqual(Decimal(string: "-x"), Decimal.zero) - XCTAssertEqual(Decimal(string: "+x"), Decimal.zero) - XCTAssertEqual(Decimal(string: "-"), Decimal.zero) - XCTAssertEqual(Decimal(string: "+"), Decimal.zero) - XCTAssertEqual(Decimal(string: "-."), Decimal.zero) - XCTAssertEqual(Decimal(string: "+."), Decimal.zero) - - XCTAssertEqual(Decimal(string: "-0"), Decimal.zero) - XCTAssertEqual(Decimal(string: "+0"), Decimal.zero) - XCTAssertEqual(Decimal(string: "-0."), Decimal.zero) - XCTAssertEqual(Decimal(string: "+0."), Decimal.zero) - XCTAssertEqual(Decimal(string: "e1"), Decimal.zero) - XCTAssertEqual(Decimal(string: "e-5"), Decimal.zero) - XCTAssertEqual(Decimal(string: ".3e1"), Decimal(3)) - - XCTAssertEqual(Decimal(string: "."), Decimal.zero) - XCTAssertEqual(Decimal(string: ".", locale: en_US), Decimal.zero) - XCTAssertNil(Decimal(string: ".", locale: fr_FR)) - - XCTAssertNil(Decimal(string: ",")) - XCTAssertEqual(Decimal(string: ",", locale: fr_FR), Decimal.zero) - XCTAssertNil(Decimal(string: ",", locale: en_US)) - - let s1 = "1234.5678" - XCTAssertEqual(Decimal(string: s1, locale: en_US)?.description, s1) - XCTAssertEqual(Decimal(string: s1, locale: fr_FR)?.description, "1234") - - let s2 = "1234,5678" - XCTAssertEqual(Decimal(string: s2, locale: en_US)?.description, "1234") - XCTAssertEqual(Decimal(string: s2, locale: fr_FR)?.description, s1) - } -} diff --git a/Tests/FoundationInternationalizationTests/DurationExtensionTests.swift b/Tests/FoundationInternationalizationTests/DurationExtensionTests.swift deleted file mode 100644 index 75235ab31..000000000 --- a/Tests/FoundationInternationalizationTests/DurationExtensionTests.swift +++ /dev/null @@ -1,104 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2020 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(FoundationInternationalization) -@testable import FoundationEssentials -@testable import FoundationInternationalization -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#endif - -final class DurationExtensionTests : XCTestCase { - - func testRoundingMode() { - - func verify(_ tests: [Int64], increment: Int64, expected: [FloatingPointRoundingRule: [Int64]], file: StaticString = #filePath, line: UInt = #line) { - let modes: [FloatingPointRoundingRule] = [.down, .up, .towardZero, .awayFromZero, .toNearestOrEven, .toNearestOrAwayFromZero] - for mode in modes { - var actual: [Duration] = [] - for test in tests { - actual.append(Duration.seconds(test).rounded(increment: Duration.seconds(increment), rule: mode)) - } - XCTAssertEqual(actual, expected[mode]?.map { Duration.seconds($0) }, "\(mode) does not match", file: file, line: line) - } - } - - verify([9223372036854775018, 18, 15, 12, 8, 5, 2, 0], increment: 10, expected: [ - .down : [9223372036854775010, 10, 10, 10, 0, 0, 0, 0], - .up : [9223372036854775020, 20, 20, 20, 10, 10, 10, 0], - .towardZero: [9223372036854775010, 10, 10, 10, 0, 0, 0, 0], - .awayFromZero: [9223372036854775020, 20, 20, 20, 10, 10, 10, 0], - .toNearestOrEven: [9223372036854775020, 20, 20, 10, 10, 0, 0, 0], - .toNearestOrAwayFromZero: [9223372036854775020, 20, 20, 10, 10, 10, 0, 0] - ]) - - verify([ -2, -5, -8, -12, -15, -18, -9223372036854775018 ], increment: 10, expected: [ - .down : [-10, -10, -10, -20, -20, -20, -9223372036854775020], - .up : [ 0, 0, 0, -10, -10, -10, -9223372036854775010], - .towardZero: [ 0, 0, 0, -10, -10, -10, -9223372036854775010], - .awayFromZero: [-10, -10, -10, -20, -20, -20, -9223372036854775020], - .toNearestOrEven: [ 0, 0, -10, -10, -20, -20, -9223372036854775020], - .toNearestOrAwayFromZero: [ 0, -10, -10, -10, -20, -20, -9223372036854775020] - ]) - - verify([9223372036854775018, 18, 15, 12, 8, 5, 2, 0], increment: 5, expected: [ - .down : [9223372036854775015, 15, 15, 10, 5, 5, 0, 0], - .up : [9223372036854775020, 20, 15, 15, 10, 5, 5, 0], - .towardZero: [9223372036854775015, 15, 15, 10, 5, 5, 0, 0], - .awayFromZero: [9223372036854775020, 20, 15, 15, 10, 5, 5, 0], - .toNearestOrEven: [9223372036854775020, 20, 15, 10, 10, 5, 0, 0], - .toNearestOrAwayFromZero: [9223372036854775020, 20, 15, 10, 10, 5, 0, 0] - ]) - - verify([ -2, -5, -8, -12, -15, -18, -9223372036854775018 ], increment: 5, expected: [ - .down : [ -5, -5, -10, -15, -15, -20, -9223372036854775020], - .up : [ 0, -5, -5, -10, -15, -15, -9223372036854775015], - .towardZero: [ 0, -5, -5, -10, -15, -15, -9223372036854775015], - .awayFromZero: [ -5, -5, -10, -15, -15, -20, -9223372036854775020], - .toNearestOrEven: [ 0, -5, -10, -10, -15, -20, -9223372036854775020], - .toNearestOrAwayFromZero: [ 0, -5, -10, -10, -15, -20, -9223372036854775020] - ]) - - verify([9223372036854775018, 18, 15, 12, 8, 5, 2, 0], increment: -10, expected: [ - .down : [9223372036854775010, 10, 10, 10, 0, 0, 0, 0], - .up : [9223372036854775020, 20, 20, 20, 10, 10, 10, 0], - .towardZero: [9223372036854775010, 10, 10, 10, 0, 0, 0, 0], - .awayFromZero: [9223372036854775020, 20, 20, 20, 10, 10, 10, 0], - .toNearestOrEven: [9223372036854775020, 20, 20, 10, 10, 0, 0, 0], - .toNearestOrAwayFromZero: [9223372036854775020, 20, 20, 10, 10, 10, 0, 0] - ]) - - verify([ -2, -5, -8, -12, -15, -18, -9223372036854775018 ], increment: -10, expected: [ - .down : [-10, -10, -10, -20, -20, -20, -9223372036854775020], - .up : [ 0, 0, 0, -10, -10, -10, -9223372036854775010], - .towardZero: [ 0, 0, 0, -10, -10, -10, -9223372036854775010], - .awayFromZero: [-10, -10, -10, -20, -20, -20, -9223372036854775020], - .toNearestOrEven: [ 0, 0, -10, -10, -20, -20, -9223372036854775020], - .toNearestOrAwayFromZero: [ 0, -10, -10, -10, -20, -20, -9223372036854775020] - ]) - - verify([9223372036854775018, 18, 15, 12, 8, 5, 2, 0], increment: 9223372036854775807, expected: [ - .down : [0, 0, 0, 0, 0, 0, 0, 0], - .up : [9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 0], - .towardZero: [0, 0, 0, 0, 0, 0, 0, 0], - .awayFromZero: [9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 0], - .toNearestOrEven: [9223372036854775807, 0, 0, 0, 0, 0, 0, 0], - .toNearestOrAwayFromZero: [9223372036854775807, 0, 0, 0, 0, 0, 0, 0] - ]) - } -} diff --git a/Tests/FoundationInternationalizationTests/Formatting/ByteCountFormatStyleTests.swift b/Tests/FoundationInternationalizationTests/Formatting/ByteCountFormatStyleTests.swift deleted file mode 100644 index 3b6822383..000000000 --- a/Tests/FoundationInternationalizationTests/Formatting/ByteCountFormatStyleTests.swift +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// RUN: %target-run-simple-swift -// REQUIRES: executable_test -// REQUIRES: objc_interop - -#if canImport(TestSupport) -import TestSupport -#endif - -final class ByteCountFormatStyleTests : XCTestCase { - let locales = [Locale(identifier: "en_US"), .init(identifier: "fr_FR"), .init(identifier: "zh_TW"), .init(identifier: "zh_CN"), .init(identifier: "ar")] - - func test_zeroSpelledOutKb() { - let localizedZerosSpelledOutKb: [Locale: String] = [ - Locale(identifier: "en_US"): "Zero kB", - Locale(identifier: "fr_FR"): "Zéro ko", - Locale(identifier: "zh_TW"): "0 kB", - Locale(identifier: "zh_CN"): "0 kB", - Locale(identifier: "ar"): "ØµÙØ± كيلوبايت", - ] - - for locale in locales { - XCTAssertEqual(0.formatted(.byteCount(style: .memory, spellsOutZero: true).locale(locale)), localizedZerosSpelledOutKb[locale], "locale: \(locale.identifier) failed expectation" ) - } - } - - func test_zeroSpelledOutBytes() { - let localizedZerosSpelledOutBytes: [Locale: String] = [ - Locale(identifier: "en_US"): "Zero bytes", - Locale(identifier: "fr_FR"): "Zéro octet", - Locale(identifier: "zh_TW"): "0 byte", - Locale(identifier: "zh_CN"): "0字节", - Locale(identifier: "ar"): "ØµÙØ± بايت", - ] - - for locale in locales { - XCTAssertEqual(0.formatted(.byteCount(style: .memory, allowedUnits: .bytes, spellsOutZero: true).locale(locale)), localizedZerosSpelledOutBytes[locale], "locale: \(locale.identifier) failed expectation") - } - } - - let localizedSingular: [Locale: [String]] = [ - Locale(identifier: "en_US"): [ - "1 byte", - "1 kB", - "1 MB", - "1 GB", - "1 TB", - "1 PB", - ], - Locale(identifier: "fr_FR"): [ - "1 octet", - "1 ko", - "1 Mo", - "1 Go", - "1 To", - "1 Po", - ], - Locale(identifier: "zh_TW"): [ - "1 byte", - "1 kB", - "1 MB", - "1 GB", - "1 TB", - "1 PB", - ], - Locale(identifier: "zh_CN"): [ - "1 byte", - "1 kB", - "1 MB", - "1 GB", - "1 TB", - "1 PB", - ], - Locale(identifier: "ar"): [ - "Ù¡ بايت", - "Ù¡ كيلوبايت", - "Ù¡ ميغابايت", - "Ù¡ غيغابايت", - "Ù¡ تيرابايت", - "Ù¡ بيتابايت", - ] - ] - -#if FIXED_86386674 - func test_singularUnitsBinary() { - for locale in locales { - for i in 0...5 { - let value: Int64 = (1 << (i*10)) - XCTAssertEqual((value).formatted(.byteCount(style: .memory).locale(locale)), localizedSingular[locale]![i]) - } - } - } -#endif - -#if FIXED_86386684 - func test_singularUnitsDecimal() { - for locale in locales { - for i in 0...5 { - XCTAssertEqual(Int64(pow(10.0, Double(i*3))).formatted(.byteCount(style: .file).locale(locale)), localizedSingular[locale]![i]) - } - } - } -#endif - - func test_localizedParens() { - XCTAssertEqual(1024.formatted(.byteCount(style: ByteCountFormatStyle.Style.binary, includesActualByteCount: true).locale(.init(identifier: "zh_TW"))), "1 kB(1,024 byte)") - XCTAssertEqual(1024.formatted(.byteCount(style: ByteCountFormatStyle.Style.binary, includesActualByteCount: true).locale(.init(identifier: "en_US"))), "1 kB (1,024 bytes)") - } - - func testActualByteCount() { - XCTAssertEqual(1024.formatted(.byteCount(style: ByteCountFormatStyle.Style.file, includesActualByteCount: true)), "1 kB (1,024 bytes)") - } - - func test_RTL() { - XCTAssertEqual(1024.formatted(.byteCount(style: ByteCountFormatStyle.Style.binary, includesActualByteCount: true).locale(.init(identifier: "ar_SA"))), "Ù¡ كيلوبايت (١٬٠٢٤ بايت)") - } - - func testAttributed() { - var expected: [Segment] - - // Zero kB - expected = [ - .init(string: "Zero", number: nil, symbol: nil, byteCount: .spelledOutValue), - .space, - .init(string: "kB", number: nil, symbol: nil, byteCount: .unit(.kb))] - XCTAssertEqual(0.formatted(.byteCount(style: .file, spellsOutZero: true).attributed), expected.attributedString) - - // 1 byte - expected = [ - .init(string: "1", number: .integer, symbol: nil, byteCount: .value), - .space, - .init(string: "byte", number: nil, symbol: nil, byteCount: .unit(.byte))] - XCTAssertEqual(1.formatted(.byteCount(style: .file).attributed), expected.attributedString) - - // 1,000 bytes - expected = [ - .init(string: "1", number: .integer, symbol: nil, byteCount: .value), - .init(string: ",", number: .integer, symbol: .groupingSeparator, byteCount: .value), - .init(string: "000", number: .integer, symbol: nil, byteCount: .value), - .space, - .init(string: "bytes", number: nil, symbol: nil, byteCount: .unit(.byte))] - XCTAssertEqual(1000.formatted(.byteCount(style: .memory).attributed), expected.attributedString) - - // 1,016 kB - expected = [ - .init(string: "1", number: .integer, symbol: nil, byteCount: .value), - .init(string: ",", number: .integer, symbol: .groupingSeparator, byteCount: .value), - .init(string: "016", number: .integer, symbol: nil, byteCount: .value), - .space, - .init(string: "kB", number: nil, symbol: nil, byteCount: .unit(.kb))] - XCTAssertEqual(1_040_000.formatted(.byteCount(style: .memory).attributed), expected.attributedString) - - // 1.1 MB - expected = [ - .init(string: "1", number: .integer, symbol: nil, byteCount: .value), - .init(string: ".", number: nil, symbol: .decimalSeparator, byteCount: .value), - .init(string: "1", number: .fraction, symbol: nil, byteCount: .value), - .space, - .init(string: "MB", number: nil, symbol: nil, byteCount: .unit(.mb))] - XCTAssertEqual(1_100_000.formatted(.byteCount(style: .file).attributed), expected.attributedString) - - // 4.2 GB (4,200,000 bytes) - expected = [ - .init(string: "4", number: .integer, symbol: nil, byteCount: .value), - .init(string: ".", number: nil, symbol: .decimalSeparator, byteCount: .value), - .init(string: "2", number: .fraction, symbol: nil, byteCount: .value), - .space, - .init(string: "GB", number: nil, symbol: nil, byteCount: .unit(.gb)), - .space, - .openParen, - .init(string: "4", number: .integer, symbol: nil, byteCount: .actualByteCount), - .init(string: ",", number: .integer, symbol: .groupingSeparator, byteCount: .actualByteCount), - .init(string: "200", number: .integer, symbol: nil, byteCount: .actualByteCount), - .init(string: ",", number: .integer, symbol: .groupingSeparator, byteCount: .actualByteCount), - .init(string: "000", number: .integer, symbol: nil, byteCount: .actualByteCount), - .init(string: ",", number: .integer, symbol: .groupingSeparator, byteCount: .actualByteCount), - .init(string: "000", number: .integer, symbol: nil, byteCount: .actualByteCount), - .space, - .init(string: "bytes", number: nil, symbol: nil, byteCount: .unit(.byte)), - .closedParen] - XCTAssertEqual(Int64(4_200_000_000).formatted(.byteCount(style: .file, includesActualByteCount: true).attributed), expected.attributedString) - } - -#if !os(watchOS) - func testEveryAllowedUnit() { - // 84270854: The largest unit supported currently is pb - let expectations: [ByteCountFormatStyle.Units: String] = [ - .bytes: "10,000,000,000,000,000 bytes", - .kb: "10,000,000,000,000 kB", - .mb: "10,000,000,000 MB", - .gb: "10,000,000 GB", - .tb: "10,000 TB", - .pb: "10 PB", - .eb: "10 PB", - .zb: "10 PB", - .ybOrHigher: "10 PB" - ] - - for (units, expectation) in expectations { - XCTAssertEqual(10_000_000_000_000_000.formatted(.byteCount(style: .file, allowedUnits: units).locale(Locale(identifier: "en_US"))), expectation) - } - } -#endif -} - -fileprivate struct Segment { - let string: String - let number: AttributeScopes.FoundationAttributes.NumberFormatAttributes.NumberPartAttribute.NumberPart? - let symbol: AttributeScopes.FoundationAttributes.NumberFormatAttributes.SymbolAttribute.Symbol? - let byteCount: AttributeScopes.FoundationAttributes.ByteCountAttribute.Component? - - static var space: Self { - return .init(string: " ", number: nil, symbol: nil, byteCount: nil) - } - - static var openParen: Self { - return .init(string: "(", number: nil, symbol: nil, byteCount: nil) - } - - static var closedParen: Self { - return .init(string: ")", number: nil, symbol: nil, byteCount: nil) - } - -} - -extension Sequence where Element == Segment { - var attributedString: AttributedString { - self.map { segment in - var attributed = AttributedString(segment.string) - - if let symbol = segment.symbol { - attributed.numberSymbol = symbol - } - if let number = segment.number { - attributed.numberPart = number - } - if let byteCount = segment.byteCount { - attributed.byteCount = byteCount - } - - return attributed - }.reduce(into: AttributedString()) { $0 += $1 } - } -} diff --git a/Tests/FoundationInternationalizationTests/Formatting/DateFormatStyleTests.swift b/Tests/FoundationInternationalizationTests/Formatting/DateFormatStyleTests.swift deleted file mode 100644 index c40b59741..000000000 --- a/Tests/FoundationInternationalizationTests/Formatting/DateFormatStyleTests.swift +++ /dev/null @@ -1,1804 +0,0 @@ -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// RUN: %target-run-simple-swift -// REQUIRES: executable_test -// REQUIRES: objc_interop - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(FoundationEssentials) -@testable import FoundationEssentials -@testable import FoundationInternationalization -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#endif - -final class DateFormatStyleTests : XCTestCase { - let referenceDate = Date(timeIntervalSinceReferenceDate: 0) - - func test_constructorSyntax() { - let style = Date.FormatStyle(locale: .init(identifier: "en_US"), calendar: .init(identifier: .gregorian), timeZone: TimeZone(identifier: "America/Los_Angeles")!) - .year(.defaultDigits) - .month(.abbreviated) - .day(.twoDigits) - .hour(.twoDigits(amPM: .omitted)) - .minute(.defaultDigits) - XCTAssertEqual(referenceDate.formatted(style), "Dec 31, 2000 at 04:00") - } - - func test_era() { - let abbreviatedStyle = Date.FormatStyle(locale: .init(identifier: "en_US"), calendar: .init(identifier: .gregorian), timeZone: TimeZone(identifier: "America/Los_Angeles")!) - .era(.abbreviated) - XCTAssertEqual(referenceDate.formatted(abbreviatedStyle), "AD") - - let narrowStyle = Date.FormatStyle(locale: .init(identifier: "en_US"), calendar: .init(identifier: .gregorian), timeZone: TimeZone(identifier: "America/Los_Angeles")!) - .era(.narrow) - XCTAssertEqual(referenceDate.formatted(narrowStyle), "A") - - let wideStyle = Date.FormatStyle(locale: .init(identifier: "en_US"), calendar: .init(identifier: .gregorian), timeZone: TimeZone(identifier: "America/Los_Angeles")!) - .era(.wide) - XCTAssertEqual(referenceDate.formatted(wideStyle), "Anno Domini") - } - - func test_dateFormatString() { - // dateFormatter.date(from: "2021-04-12 15:04:32")! - let date = Date(timeIntervalSinceReferenceDate: 639932672.0) - - func _verify(_ format: Date.FormatString, rawExpectation: String, formattedExpectation: String, line: UInt = #line) { - XCTAssertEqual(format.rawFormat, rawExpectation, "raw expectation failed", line: line) - XCTAssertEqual( - Date.VerbatimFormatStyle(format: format, timeZone: .gmt, calendar: .init(identifier: .gregorian)) - .locale(.init(identifier: "en_US")) - .format(date), - formattedExpectation, - "formatted expectation failed", - line: line - ) - } - - _verify("", rawExpectation: "", formattedExpectation: "\(date)") - _verify("some latin characters", rawExpectation: "'some latin characters'", formattedExpectation: "some latin characters") - _verify(" ", rawExpectation: "' '", formattedExpectation: " ") - _verify("😀😀", rawExpectation: "'😀😀'", formattedExpectation: "😀😀") - _verify("'", rawExpectation: "''", formattedExpectation: "'") - _verify(" ' ", rawExpectation: "' '' '", formattedExpectation: " ' ") - _verify("' ", rawExpectation: "''' '", formattedExpectation: "' ") - _verify(" '", rawExpectation: "' '''", formattedExpectation: " '") - _verify("''", rawExpectation: "''''", formattedExpectation: "''") - _verify("'some strings in single quotes'", rawExpectation: "'''some strings in single quotes'''", formattedExpectation: "'some strings in single quotes'") - - _verify("\(day: .twoDigits)\(month: .twoDigits)", rawExpectation: "ddMM", formattedExpectation: "1204") - _verify("\(day: .twoDigits)/\(month: .twoDigits)", rawExpectation: "dd'/'MM", formattedExpectation: "12/04") - _verify("\(day: .twoDigits)-\(month: .twoDigits)", rawExpectation: "dd'-'MM", formattedExpectation: "12-04") - _verify("\(day: .twoDigits)'\(month: .twoDigits)", rawExpectation: "dd''MM", formattedExpectation: "12'04") - _verify(" \(day: .twoDigits) \(month: .twoDigits) ", rawExpectation: "' 'dd' 'MM' '", formattedExpectation: " 12 04 ") - - _verify("\(hour: .defaultDigits(clock: .twelveHour, hourCycle: .oneBased)) o'clock", rawExpectation: "h' o''clock'", formattedExpectation: "3 o'clock") - - _verify("Day:\(day: .defaultDigits) Month:\(month: .abbreviated) Year:\(year: .padded(4))", rawExpectation: "'Day:'d' Month:'MMM' Year:'yyyy", formattedExpectation: "Day:12 Month:Apr Year:2021") - } - - func test_parsingThrows() { - // Literal symbols are treated as literals, so they won't parse when parsing strictly - let invalidFormats: [(Date.FormatString, String)] = [ - ("ddMMyy", "010599"), - ("dd/MM/yy", "01/05/99"), - ("d/MMM/yyyy", "1/Sep/1999"), - ] - - let locale = Locale(identifier: "en_US") - let timeZone = TimeZone(secondsFromGMT: 0)! - - for (format, dateString) in invalidFormats { - let parseStrategy = Date.ParseStrategy(format: format, locale: locale, timeZone: timeZone, isLenient: false) - XCTAssertThrowsError(try parseStrategy.parse(dateString), "Date string: \(dateString); Format: \(format.rawFormat)") - } - } - - func test_codable() { - let style = Date.FormatStyle(date: .long, time: .complete, capitalizationContext: .unknown) - .era() - .year() - .quarter() - .month() - .week() - .day() - .dayOfYear() - .weekday() - .hour() - .minute() - .second() - .secondFraction(.milliseconds(2)) - .timeZone() - let jsonEncoder = JSONEncoder() - let encodedStyle = try? jsonEncoder.encode(style) - XCTAssertNotNil(encodedStyle) - let jsonDecoder = JSONDecoder() - let decodedStyle = try? jsonDecoder.decode(Date.FormatStyle.self, from: encodedStyle!) - XCTAssertNotNil(decodedStyle) - - XCTAssert(referenceDate.formatted(decodedStyle!) == referenceDate.formatted(style), "\(referenceDate.formatted(decodedStyle!)) should be \(referenceDate.formatted(style))") - - } - - func test_createFormatStyleMultithread() { - let group = DispatchGroup() - let testLocales: [String] = [ "en_US", "en_US", "en_GB", "es_SP", "zh_TW", "fr_FR", "en_US", "en_GB", "fr_FR"] - let expectations: [String : String] = [ - "en_US": "Dec 31, 1969", - "en_GB": "31 Dec 1969", - "es_SP": "31 dic 1969", - "zh_TW": "1969å¹´12月31æ—¥", - "fr_FR": "31 déc. 1969", - ] - let date = Date(timeIntervalSince1970: 0) - - for localeIdentifier in testLocales { - DispatchQueue.global(qos: .userInitiated).async(group:group) { - let locale = Locale(identifier: localeIdentifier) - XCTAssertNotNil(locale) - let timeZone = TimeZone(secondsFromGMT: -3600)! - - let formatStyle = Date.FormatStyle(date: .abbreviated, locale: locale, timeZone: timeZone) - guard let formatterFromCache = ICUDateFormatter.cachedFormatter(for: formatStyle) else { - XCTFail("Unexpected nil formatter") - return - } - - let expected = expectations[localeIdentifier]! - let result = formatterFromCache.format(date) - XCTAssertEqual(result, expected) - } - } - - let result = group.wait(timeout: DispatchTime.now() + DispatchTimeInterval.seconds(105)) - XCTAssertEqual(result, .success) - } - - func test_createPatternMultithread() { - let group = DispatchGroup() - let testLocales = [ "en_US", "en_US", "en_GB", "es_SP", "zh_TW", "fr_FR", "en_US", "en_GB", "fr_FR"].map { Locale(identifier: $0) } - let expectations: [String : String] = [ - "en_US": "MMM d, y", - "en_GB": "d MMM y", - "es_SP": "d MMM y", - "zh_TW": "yå¹´M月dæ—¥", - "fr_FR": "d MMM y", - ] - - let gregorian = Calendar(identifier: .gregorian) - let symbols = Date.FormatStyle.DateFieldCollection(year: .defaultDigits, month: .abbreviated, day: .defaultDigits) - for testLocale in testLocales { - DispatchQueue.global(qos: .userInitiated).async(group:group) { - let pattern = ICUPatternGenerator.localizedPattern(symbols: symbols, locale: testLocale, calendar: gregorian) - - let expected = expectations[testLocale.identifier] - XCTAssertEqual(pattern, expected) - } - } - - let result = group.wait(timeout: DispatchTime.now() + DispatchTimeInterval.seconds(105)) - XCTAssertEqual(result, .success) - } - - func test_roundtrip() { - let date = Date.now - let style = Date.FormatStyle(date: .numeric, time: .shortened) - let format = date.formatted(style) - let parsed = try? Date(format, strategy: style.parseStrategy) - XCTAssertNotNil(parsed) - XCTAssertEqual(parsed?.formatted(style), format) - } - - func testLeadingDotSyntax() { - let date = Date.now - XCTAssertEqual(date.formatted(date: .long, time: .complete), date.formatted(Date.FormatStyle(date: .long, time: .complete))) - XCTAssertEqual( - date.formatted( - .dateTime - .day() - .month() - .year() - ), - date.formatted( - Date.FormatStyle() - .day() - .month() - .year() - ) - ) - } - - func testDateFormatStyleIndividualFields() { - let date = Date(timeIntervalSince1970: 0) - - let style = Date.FormatStyle(date: nil, time: nil, locale: Locale(identifier: "en_US"), calendar: Calendar(identifier: .gregorian), timeZone: TimeZone(abbreviation: "UTC")!, capitalizationContext: .unknown) - - XCTAssertEqual(date.formatted(style.era(.abbreviated)), "AD") - XCTAssertEqual(date.formatted(style.era(.wide)), "Anno Domini") - XCTAssertEqual(date.formatted(style.era(.narrow)), "A") - - XCTAssertEqual(date.formatted(style.year(.defaultDigits)), "1970") - XCTAssertEqual(date.formatted(style.year(.twoDigits)), "70") - XCTAssertEqual(date.formatted(style.year(.padded(0))), "1970") - XCTAssertEqual(date.formatted(style.year(.padded(1))), "1970") - XCTAssertEqual(date.formatted(style.year(.padded(2))), "70") - XCTAssertEqual(date.formatted(style.year(.padded(3))), "1970") - XCTAssertEqual(date.formatted(style.year(.padded(999))), "0000001970") - - XCTAssertEqual(date.formatted(style.year(.relatedGregorian(minimumLength: 0))), "1970") - XCTAssertEqual(date.formatted(style.year(.relatedGregorian(minimumLength: 999))), "0000001970") - - XCTAssertEqual(date.formatted(style.year(.extended(minimumLength: 0))), "1970") - XCTAssertEqual(date.formatted(style.year(.extended(minimumLength: 999))), "0000001970") - - XCTAssertEqual(date.formatted(style.quarter(.oneDigit)), "1") - XCTAssertEqual(date.formatted(style.quarter(.twoDigits)), "01") - XCTAssertEqual(date.formatted(style.quarter(.abbreviated)), "Q1") - XCTAssertEqual(date.formatted(style.quarter(.wide)), "1st quarter") - XCTAssertEqual(date.formatted(style.quarter(.narrow)), "1") - - XCTAssertEqual(date.formatted(style.month(.defaultDigits)), "1") - XCTAssertEqual(date.formatted(style.month(.twoDigits)), "01") - XCTAssertEqual(date.formatted(style.month(.abbreviated)), "Jan") - XCTAssertEqual(date.formatted(style.month(.wide)), "January") - XCTAssertEqual(date.formatted(style.month(.narrow)), "J") - - XCTAssertEqual(date.formatted(style.week(.defaultDigits)), "1") - XCTAssertEqual(date.formatted(style.week(.twoDigits)), "01") - XCTAssertEqual(date.formatted(style.week(.weekOfMonth)), "1") - - XCTAssertEqual(date.formatted(style.day(.defaultDigits)), "1") - XCTAssertEqual(date.formatted(style.day(.twoDigits)), "01") - XCTAssertEqual(date.formatted(style.day(.ordinalOfDayInMonth)), "1") - - XCTAssertEqual(date.formatted(style.day(.julianModified(minimumLength: 0))), "2440588") - XCTAssertEqual(date.formatted(style.day(.julianModified(minimumLength: 999))), "0002440588") - - XCTAssertEqual(date.formatted(style.dayOfYear(.defaultDigits)), "1") - XCTAssertEqual(date.formatted(style.dayOfYear(.twoDigits)), "01") - XCTAssertEqual(date.formatted(style.dayOfYear(.threeDigits)), "001") - - XCTAssertEqual(date.formatted(style.weekday(.oneDigit)), "5") - XCTAssertEqual(date.formatted(style.weekday(.twoDigits)), "5") // This is an ICU bug - XCTAssertEqual(date.formatted(style.weekday(.abbreviated)), "Thu") - XCTAssertEqual(date.formatted(style.weekday(.wide)), "Thursday") - XCTAssertEqual(date.formatted(style.weekday(.narrow)), "T") - XCTAssertEqual(date.formatted(style.weekday(.short)), "Th") - - XCTAssertEqual(date.formatted(style.hour(.defaultDigits(amPM: .omitted))), "12") - XCTAssertEqual(date.formatted(style.hour(.defaultDigits(amPM: .narrow))), "12 a") - XCTAssertEqual(date.formatted(style.hour(.defaultDigits(amPM: .abbreviated))), "12 AM") - XCTAssertEqual(date.formatted(style.hour(.defaultDigits(amPM: .wide))), "12 AM") - - XCTAssertEqual(date.formatted(style.hour(.twoDigits(amPM: .omitted))), "12") - XCTAssertEqual(date.formatted(style.hour(.twoDigits(amPM: .narrow))), "12 a") - XCTAssertEqual(date.formatted(style.hour(.twoDigits(amPM: .abbreviated))), "12 AM") - XCTAssertEqual(date.formatted(style.hour(.twoDigits(amPM: .wide))), "12 AM") - } - - func testFormattingWithHourCycleOverrides() throws { - let date = Date(timeIntervalSince1970: 0) - let enUS = "en_US" - let esES = "es_ES" - - let style = Date.FormatStyle(date: .omitted, time: .standard, calendar: Calendar(identifier: .gregorian), timeZone: TimeZone(identifier: "PST")!, capitalizationContext: .standalone) - XCTAssertEqual(date.formatted(style.locale(Locale.localeAsIfCurrent(name: enUS, overrides: .init()))), "4:00:00 PM") - XCTAssertEqual(date.formatted(style.locale(Locale.localeAsIfCurrent(name: enUS, overrides: .init(force12Hour: true)))), "4:00:00 PM") - XCTAssertEqual(date.formatted(style.locale(Locale.localeAsIfCurrent(name: enUS, overrides: .init(force24Hour: true)))), "16:00:00") - - XCTAssertEqual(date.formatted(style.locale(Locale.localeAsIfCurrent(name: esES, overrides: .init()))), "16:00:00") - XCTAssertEqual(date.formatted(style.locale(Locale.localeAsIfCurrent(name: esES, overrides: .init(force12Hour: true)))), "4:00:00 p. m.") - XCTAssertEqual(date.formatted(style.locale(Locale.localeAsIfCurrent(name: esES, overrides: .init(force24Hour: true)))), "16:00:00") - } - -#if !os(watchOS) // 99504292 - func testNSICUDateFormatterCache() throws { - guard Locale.autoupdatingCurrent.language.isEquivalent(to: Locale.Language(identifier: "en_US")) else { - throw XCTSkip("This test can only be run with the system set to the en_US language") - } - - let fixedTimeZone = TimeZone(identifier: TimeZone.current.identifier)! - let fixedCalendar = Calendar(identifier: Calendar.current.identifier) - - let dateStyle = Date.FormatStyle.DateStyle.complete - let timeStyle = Date.FormatStyle.TimeStyle.standard - - let style = Date.FormatStyle(date: dateStyle, time: timeStyle) - let styleUsingFixedTimeZone = Date.FormatStyle(date: dateStyle, time: timeStyle, timeZone: fixedTimeZone) - let styleUsingFixedCalendar = Date.FormatStyle(date: dateStyle, time: timeStyle, calendar: fixedCalendar) - - XCTAssertTrue(ICUDateFormatter.cachedFormatter(for: style) === ICUDateFormatter.cachedFormatter(for: styleUsingFixedTimeZone)) - XCTAssertTrue(ICUDateFormatter.cachedFormatter(for: style) === ICUDateFormatter.cachedFormatter(for: styleUsingFixedCalendar)) - } -#endif - -// Only Foundation framework supports the DateStyle override -#if FOUNDATION_FRAMEWORK - func testFormattingWithPrefsOverride() { - let date = Date(timeIntervalSince1970: 0) - let enUS = "en_US" - - func test(dateStyle: Date.FormatStyle.DateStyle, timeStyle: Date.FormatStyle.TimeStyle, dateFormatOverride: [Date.FormatStyle.DateStyle: String], expected: String, file: StaticString = #filePath, line: UInt = #line) { - let locale = Locale.localeAsIfCurrent(name: enUS, overrides: .init(dateFormats: dateFormatOverride)) - let style = Date.FormatStyle(date: dateStyle, time: timeStyle, locale: locale, calendar: Calendar(identifier: .gregorian), timeZone: TimeZone(identifier: "PST")!, capitalizationContext: .standalone) - let formatted = style.format(date) - XCTAssertEqual(formatted, expected, file: file, line: line) - - guard let parsed = try? Date(formatted, strategy: style) else { - XCTFail("Parsing failed", file: file, line: line) - return - } - let parsedStr = style.format(parsed) - XCTAssertEqual(parsedStr, expected, "round trip formatting failed", file: file, line: line) - } - - let dateFormatOverride: [Date.FormatStyle.DateStyle: String] = [ - .abbreviated: "'' yyyy-MMM-dd", - .numeric: "'' yyyy-MMM-dd", - .long: "'' yyyy-MMM-dd", - .complete: "'' yyyy-MMM-dd" - ] - -#if FOUNDATION_FRAMEWORK - let expectTimeString = "4:00:00\u{202F}PM" - let expectedShortTimeString = "4:00\u{202F}PM" -#else - let expectTimeString = "4:00:00 PM" - let expectedShortTimeString = "4:00 PM" -#endif - - test(dateStyle: .omitted, timeStyle: .omitted, dateFormatOverride: dateFormatOverride, expected: "12/31/1969, \(expectedShortTimeString)") // Ignoring override since there's no match for the specific style - test(dateStyle: .abbreviated, timeStyle: .omitted, dateFormatOverride: dateFormatOverride, expected: " 1969-Dec-31") - test(dateStyle: .numeric, timeStyle: .omitted, dateFormatOverride: dateFormatOverride, expected: " 1969-Dec-31") - test(dateStyle: .long, timeStyle: .omitted, dateFormatOverride: dateFormatOverride, expected: " 1969-Dec-31") - test(dateStyle: .complete, timeStyle: .omitted, dateFormatOverride: dateFormatOverride, expected: " 1969-Dec-31") - - test(dateStyle: .omitted, timeStyle: .standard, dateFormatOverride: dateFormatOverride, expected: expectTimeString) - test(dateStyle: .abbreviated, timeStyle: .complete, dateFormatOverride: dateFormatOverride, expected: " 1969-Dec-31 at \(expectTimeString) PST") - test(dateStyle: .numeric, timeStyle: .complete, dateFormatOverride: dateFormatOverride, expected: " 1969-Dec-31, \(expectTimeString) PST") - test(dateStyle: .long, timeStyle: .complete, dateFormatOverride: dateFormatOverride, expected: " 1969-Dec-31 at \(expectTimeString) PST") - test(dateStyle: .complete, timeStyle: .complete, dateFormatOverride: dateFormatOverride, expected: " 1969-Dec-31 at \(expectTimeString) PST") - - } -#endif - - func testFormattingWithPrefsOverride_firstweekday() { - let date = Date(timeIntervalSince1970: 0) - let locale = Locale.localeAsIfCurrent(name: "en_US", overrides: .init(firstWeekday: [.gregorian : 5])) - let style = Date.FormatStyle(date: .complete, time: .omitted, locale: locale, calendar: Calendar(identifier: .gregorian), timeZone: TimeZone(identifier: "PST")!, capitalizationContext: .standalone).week() - XCTAssertEqual(style.format(date), "Wednesday, December 31, 1969 (week: 53)") // First day is Thursday, so `date`, which is Wednesday, falls into the 53th week of the previous year. - } - -#if FOUNDATION_FRAMEWORK - func testEncodingDecodingWithPrefsOverride() { - let date = Date(timeIntervalSince1970: 0) - let dateFormatOverride: [Date.FormatStyle.DateStyle: String] = [ - .complete: "'' yyyy-MMM-dd" - ] - - let localeWithOverride = Locale.localeAsIfCurrent(name: "en_US", overrides: .init(dateFormats: dateFormatOverride)) - let style = Date.FormatStyle(date: .complete, time: .omitted, locale: localeWithOverride, calendar: Calendar(identifier: .gregorian), timeZone: TimeZone(identifier: "PST")!, capitalizationContext: .standalone) - XCTAssertEqual(style.format(date), " 1969-Dec-31") - - guard let encoded = try? JSONEncoder().encode(style) else { - XCTFail("Encoding Date.FormatStyle failed") - return - } - - guard var decoded = try? JSONDecoder().decode(Date.FormatStyle.self, from: encoded) else { - XCTFail("Decoding failed") - return - } - - XCTAssertEqual(decoded._dateStyle, .complete) - - decoded.locale = localeWithOverride - XCTAssertEqual(decoded.format(date), " 1969-Dec-31") - } -#endif - - func testConversationalDayPeriodsOverride() { - let middleOfNight = try! Date("2001-01-01T03:50:00Z", strategy: .iso8601) - let earlyMorning = try! Date("2001-01-01T06:50:00Z", strategy: .iso8601) - let morning = try! Date("2001-01-01T09:50:00Z", strategy: .iso8601) - let noon = try! Date("2001-01-01T12:50:00Z", strategy: .iso8601) - let afternoon = try! Date("2001-01-01T15:50:00Z", strategy: .iso8601) - let evening = try! Date("2001-01-01T21:50:00Z", strategy: .iso8601) - - var locale: Locale - var format: Date.FormatStyle - func verifyWithFormat(_ date: Date, expected: String, file: StaticString = #filePath, line: UInt = #line) { - let fmt = format.locale(locale) - let formatted = fmt.format(date) - XCTAssertEqual(formatted, expected, file: file, line: line) - } - - do { - locale = Locale(identifier: "zh_TW") - format = .init(timeZone: .gmt).hour() - verifyWithFormat(middleOfNight, expected: "凌晨3時") - verifyWithFormat(earlyMorning, expected: "清晨6時") - verifyWithFormat(morning, expected: "上åˆ9時") - verifyWithFormat(noon, expected: "中åˆ12時") - verifyWithFormat(afternoon, expected: "下åˆ3時") - verifyWithFormat(evening, expected: "晚上9時") - } - - do { - locale = Locale(identifier: "zh_TW") - format = .init(timeZone: .gmt).hour(.defaultDigits(amPM: .abbreviated)) - verifyWithFormat(middleOfNight, expected: "凌晨3時") - verifyWithFormat(earlyMorning, expected: "清晨6時") - verifyWithFormat(morning, expected: "上åˆ9時") - verifyWithFormat(noon, expected: "中åˆ12時") - verifyWithFormat(afternoon, expected: "下åˆ3時") - verifyWithFormat(evening, expected: "晚上9時") - } - - do { - locale = Locale(identifier: "zh_TW") - format = .init(timeZone: .gmt).hour(.twoDigits(amPM: .abbreviated)) - verifyWithFormat(middleOfNight, expected: "凌晨03時") - verifyWithFormat(earlyMorning, expected: "清晨06時") - verifyWithFormat(morning, expected: "上åˆ09時") - verifyWithFormat(noon, expected: "中åˆ12時") - verifyWithFormat(afternoon, expected: "下åˆ03時") - verifyWithFormat(evening, expected: "晚上09時") - } - - do { - locale = Locale(identifier: "zh_TW") - format = .init(timeZone: .gmt).hour().minute() - verifyWithFormat(middleOfNight, expected: "凌晨3:50") - verifyWithFormat(earlyMorning, expected: "清晨6:50") - verifyWithFormat(morning, expected: "上åˆ9:50") - verifyWithFormat(noon, expected: "中åˆ12:50") - verifyWithFormat(afternoon, expected: "下åˆ3:50") - verifyWithFormat(evening, expected: "晚上9:50") - } - - do { - locale = Locale(identifier: "zh_TW") - format = .init(timeZone: .gmt).hour(.defaultDigits(amPM: .wide)).minute() - verifyWithFormat(middleOfNight, expected: "凌晨3:50") - verifyWithFormat(earlyMorning, expected: "清晨6:50") - verifyWithFormat(morning, expected: "上åˆ9:50") - verifyWithFormat(noon, expected: "中åˆ12:50") - verifyWithFormat(afternoon, expected: "下åˆ3:50") - verifyWithFormat(evening, expected: "晚上9:50") - } - - do { - locale = Locale(identifier: "zh_TW") - format = .init(timeZone: .gmt).hour(.twoDigits(amPM: .wide)).minute() - verifyWithFormat(middleOfNight, expected: "凌晨03:50") - verifyWithFormat(earlyMorning, expected: "清晨06:50") - verifyWithFormat(morning, expected: "上åˆ09:50") - verifyWithFormat(noon, expected: "中åˆ12:50") - verifyWithFormat(afternoon, expected: "下åˆ03:50") - verifyWithFormat(evening, expected: "晚上09:50") - } - - do { - locale = Locale(identifier: "zh_TW") - format = .init(timeZone: .gmt).hour().minute().second() - verifyWithFormat(middleOfNight, expected: "凌晨3:50:00") - verifyWithFormat(earlyMorning, expected: "清晨6:50:00") - verifyWithFormat(morning, expected: "上åˆ9:50:00") - verifyWithFormat(noon, expected: "中åˆ12:50:00") - verifyWithFormat(afternoon, expected: "下åˆ3:50:00") - verifyWithFormat(evening, expected: "晚上9:50:00") - } - - do { - locale = Locale(identifier: "zh_TW") - format = .init(timeZone: .gmt).hour(.defaultDigits(amPM: .wide)).minute().second() - verifyWithFormat(middleOfNight, expected: "凌晨3:50:00") - verifyWithFormat(earlyMorning, expected: "清晨6:50:00") - verifyWithFormat(morning, expected: "上åˆ9:50:00") - verifyWithFormat(noon, expected: "中åˆ12:50:00") - verifyWithFormat(afternoon, expected: "下åˆ3:50:00") - verifyWithFormat(evening, expected: "晚上9:50:00") - } - - do { - locale = Locale(identifier: "zh_TW") - format = .init(timeZone: .gmt).hour(.twoDigits(amPM: .wide)).minute().second() - verifyWithFormat(middleOfNight, expected: "凌晨03:50:00") - verifyWithFormat(earlyMorning, expected: "清晨06:50:00") - verifyWithFormat(morning, expected: "上åˆ09:50:00") - verifyWithFormat(noon, expected: "中åˆ12:50:00") - verifyWithFormat(afternoon, expected: "下åˆ03:50:00") - verifyWithFormat(evening, expected: "晚上09:50:00") - } - - // Test for not showing day period - do { - locale = Locale(identifier: "zh_TW") - format = .init(timeZone: .gmt).hour(.defaultDigits(amPM: .omitted)) - verifyWithFormat(middleOfNight, expected: "3時") - verifyWithFormat(earlyMorning, expected: "6時") - verifyWithFormat(morning, expected: "9時") - verifyWithFormat(noon, expected: "12時") - verifyWithFormat(afternoon, expected: "3時") - verifyWithFormat(evening, expected: "9時") - } - - do { - locale = Locale(identifier: "zh_TW@hours=h24") // using 24-hour time - format = .init(timeZone: .gmt).hour() - verifyWithFormat(middleOfNight, expected: "3時") - verifyWithFormat(earlyMorning, expected: "6時") - verifyWithFormat(morning, expected: "9時") - verifyWithFormat(noon, expected: "12時") - verifyWithFormat(afternoon, expected: "15時") - verifyWithFormat(evening, expected: "21時") - } - - do { - var custom24HourLocale = Locale.Components(identifier: "zh_TW") - custom24HourLocale.hourCycle = .zeroToTwentyThree // using 24-hour time - locale = Locale(components: custom24HourLocale) - format = .init(timeZone: .gmt).hour() - verifyWithFormat(middleOfNight, expected: "3時") - verifyWithFormat(earlyMorning, expected: "6時") - verifyWithFormat(morning, expected: "9時") - verifyWithFormat(noon, expected: "12時") - verifyWithFormat(afternoon, expected: "15時") - verifyWithFormat(evening, expected: "21時") - } - - do { - locale = Locale.localeAsIfCurrent(name: "zh_TW", overrides: .init(force24Hour: true)) - format = .init(timeZone: .gmt).hour() - verifyWithFormat(middleOfNight, expected: "3時") - verifyWithFormat(earlyMorning, expected: "6時") - verifyWithFormat(morning, expected: "9時") - verifyWithFormat(noon, expected: "12時") - verifyWithFormat(afternoon, expected: "15時") - verifyWithFormat(evening, expected: "21時") - } - - // Tests for when region matches the special case but language doesn't - do { - locale = Locale(identifier: "en_TW") - format = .init(timeZone: .gmt).hour(.twoDigits(amPM: .wide)).minute().second() - verifyWithFormat(middleOfNight, expected: "03:50:00 AM") - verifyWithFormat(earlyMorning, expected: "06:50:00 AM") - verifyWithFormat(morning, expected: "09:50:00 AM") - verifyWithFormat(noon, expected: "12:50:00 PM") - verifyWithFormat(afternoon, expected: "03:50:00 PM") - verifyWithFormat(evening, expected: "09:50:00 PM") - } - } - - func testRemovingFields() { - var format: Date.FormatStyle = .init(calendar: .init(identifier: .gregorian), timeZone: .gmt).locale(Locale(identifier: "en_US")) - func verifyWithFormat(_ date: Date, expected: String, file: StaticString = #filePath, line: UInt = #line) { - let formatted = format.format(date) - XCTAssertEqual(formatted, expected, file: file, line: line) - } - - let date = Date(timeIntervalSince1970: 0) - - verifyWithFormat(date, expected: "1/1/1970, 12:00 AM") - format = format.day(.omitted) - verifyWithFormat(date, expected: "1/1970, 12:00 AM") - format = format.day(.defaultDigits) - verifyWithFormat(date, expected: "1/1/1970, 12:00 AM") - format = format.minute() - verifyWithFormat(date, expected: "1/1/1970, 12:00 AM") - format = format.minute(.omitted) - verifyWithFormat(date, expected: "1/1/1970, 12 AM") - format = format.day(.omitted) - verifyWithFormat(date, expected: "1/1970, 12 AM") - - format = .init(calendar: .init(identifier: .gregorian), timeZone: .gmt).locale(Locale(identifier: "en_US")) - format = format.day() - format = format.day(.omitted) - verifyWithFormat(date, expected: "") - } -} - -extension Sequence where Element == (String, AttributeScopes.FoundationAttributes.DateFieldAttribute.Field?) { - var attributedString: AttributedString { - self.map { pair in - return pair.1 == nil ? AttributedString(pair.0) : AttributedString(pair.0, attributes: .init().dateField(pair.1!)) - }.reduce(AttributedString(), +) - } -} - -final class DateAttributedFormatStyleTests : XCTestCase { - var enUSLocale = Locale(identifier: "en_US") - var gmtTimeZone = TimeZone(secondsFromGMT: 0)! - - typealias Segment = (String, AttributeScopes.FoundationAttributes.DateFieldAttribute.Field?) - func testAttributedFormatStyle() throws { - let baseStyle = Date.FormatStyle(locale: enUSLocale, timeZone: gmtTimeZone) - // dateFormatter.date(from: "2021-04-12 15:04:32")! - let date = Date(timeIntervalSinceReferenceDate: 639932672.0) - - let expectations: [Date.FormatStyle : [Segment]] = [ - baseStyle.month().day().hour().minute(): [("Apr", .month), - (" ", nil), - ("12", .day), - (" at ", nil), - ("3", .hour), - (":", nil), - ("04", .minute), - (" ", nil), - ("PM", .amPM)], - ] - - for (style, expectation) in expectations { - let formatted = style.attributedStyle.format(date) - XCTAssertEqual(formatted, expectation.attributedString) - } - } - func testIndividualFields() throws { - let baseStyle = Date.FormatStyle(locale: enUSLocale, timeZone: gmtTimeZone) - // dateFormatter.date(from: "2021-04-12 15:04:32")! - let date = Date(timeIntervalSinceReferenceDate: 639932672.0) - let expectations: [Date.FormatStyle : [Segment]] = [ - baseStyle.era(): [ ("AD", .era) ], - baseStyle.year(.defaultDigits): [ ("2021", .year) ], - baseStyle.quarter(): [ ("Q2", .quarter) ], - baseStyle.month(.defaultDigits): [ ("4", .month) ], - baseStyle.week(): [ ("16", .weekOfYear) ], - baseStyle.week(.weekOfMonth): [ ("3", .weekOfMonth) ], - baseStyle.day(): [ ("12", .day) ], - baseStyle.dayOfYear(): [ ("102", .dayOfYear) ], - baseStyle.weekday(): [ ("Mon", .weekday) ], - baseStyle.hour(): [ ("3", .hour), (" ", nil), ("PM", .amPM) ], - baseStyle.minute(): [ ("4", .minute) ], - baseStyle.second(): [ ("32", .second) ], - baseStyle.timeZone(): [ ("GMT", .timeZone) ], - ] - - for (style, expectation) in expectations { - let formatted = style.attributedStyle.format(date) - XCTAssertEqual(formatted, expectation.attributedString) - } - } - - func testCodable() throws { - let encoder = JSONEncoder() - let decoder = JSONDecoder() - - let fields: [AttributeScopes.FoundationAttributes.DateFieldAttribute.Field] = [.era, .year, .relatedGregorianYear, .quarter, .month, .weekOfYear, .weekOfMonth, .weekday, .weekdayOrdinal, .day, .dayOfYear, .amPM, .hour, .minute, .second, .secondFraction, .timeZone] - for field in fields { - let encoded = try? encoder.encode(field) - XCTAssertNotNil(encoded) - - let decoded = try? decoder.decode(AttributeScopes.FoundationAttributes.DateFieldAttribute.Field.self, from: encoded!) - XCTAssertEqual(decoded, field) - } - } - - func testSettingLocale() throws { - // dateFormatter.date(from: "2021-04-12 15:04:32")! - let date = Date(timeIntervalSinceReferenceDate: 639932672.0) - let zhTW = Locale(identifier: "zh_TW") - - func test(_ attributedResult: AttributedString, _ expected: [Segment], file: StaticString = #filePath, line: UInt = #line) { - XCTAssertEqual(attributedResult, expected.attributedString, file: file, line: line) - } - - var format = Date.FormatStyle.dateTime - format.timeZone = .gmt - - test(date.formatted(format.weekday().locale(enUSLocale).attributedStyle), [("Mon", .weekday)]) - test(date.formatted(format.weekday().locale(zhTW).attributedStyle), [("週一", .weekday)]) - - test(date.formatted(format.weekday().attributedStyle.locale(enUSLocale)), [("Mon", .weekday)]) - test(date.formatted(format.weekday().attributedStyle.locale(zhTW)), [("週一", .weekday)]) - } - -#if FOUNDATION_FRAMEWORK - func testFormattingWithPrefsOverride() { - let date = Date(timeIntervalSince1970: 0) - let enUS = "en_US" - - func test(dateStyle: Date.FormatStyle.DateStyle, timeStyle: Date.FormatStyle.TimeStyle, dateFormatOverride: [Date.FormatStyle.DateStyle: String], expected: [Segment], file: StaticString = #filePath, line: UInt = #line) { - let locale = Locale.localeAsIfCurrent(name: enUS, overrides: .init(dateFormats: dateFormatOverride)) - let style = Date.FormatStyle(date: dateStyle, time: timeStyle, locale: locale, calendar: Calendar(identifier: .gregorian), timeZone: TimeZone(identifier: "PST")!, capitalizationContext: .standalone).attributed - XCTAssertEqual(style.format(date), expected.attributedString, file: file, line: line) - } - - let dateFormatOverride: [Date.FormatStyle.DateStyle: String] = [ - .abbreviated: "'' yyyy-MMM-dd", - .numeric: "'' yyyy-MMM-dd", - .long: "'' yyyy-MMM-dd", - .complete: "'' yyyy-MMM-dd" - ] - - test(dateStyle: .omitted, timeStyle: .omitted, dateFormatOverride: dateFormatOverride, expected: [ - ("12", .month), - ("/", nil), - ("31", .day), - ("/", nil), - ("1969", .year), - (", ", nil), - ("4", .hour), - (":", nil), - ("00", .minute), - (" ", nil), - ("PM", .amPM), - ]) // Ignoring override since there's no match for the specific style - - test(dateStyle: .abbreviated, timeStyle: .omitted, dateFormatOverride: dateFormatOverride, expected: [ - (" ", nil), - ("1969", .year), - ("-", nil), - ("Dec", .month), - ("-", nil), - ("31", .day), - ]) - - test(dateStyle: .numeric, timeStyle: .omitted, dateFormatOverride: dateFormatOverride, expected: [ - (" ", nil), - ("1969", .year), - ("-", nil), - ("Dec", .month), - ("-", nil), - ("31", .day), - ]) - - test(dateStyle: .long, timeStyle: .omitted, dateFormatOverride: dateFormatOverride, expected: [ - (" ", nil), - ("1969", .year), - ("-", nil), - ("Dec", .month), - ("-", nil), - ("31", .day), - ]) - - test(dateStyle: .complete, timeStyle: .omitted, dateFormatOverride: dateFormatOverride, expected: [ - (" ", nil), - ("1969", .year), - ("-", nil), - ("Dec", .month), - ("-", nil), - ("31", .day), - ]) - - test(dateStyle: .omitted, timeStyle: .complete, dateFormatOverride: dateFormatOverride, expected: [ - ("4", .hour), - (":", nil), - ("00", .minute), - (":", nil), - ("00", .second), - (" ", nil), - ("PM", .amPM), - (" ", nil), - ("PST", .timeZone), - ]) - - test(dateStyle: .abbreviated, timeStyle: .complete, dateFormatOverride: dateFormatOverride, expected: [ - (" ", nil), - ("1969", .year), - ("-", nil), - ("Dec", .month), - ("-", nil), - ("31", .day), - (" at ", nil), - ("4", .hour), - (":", nil), - ("00", .minute), - (":", nil), - ("00", .second), - (" ", nil), - ("PM", .amPM), - (" ", nil), - ("PST", .timeZone), - ]) - - test(dateStyle: .numeric, timeStyle: .complete, dateFormatOverride: dateFormatOverride, expected: [ - (" ", nil), - ("1969", .year), - ("-", nil), - ("Dec", .month), - ("-", nil), - ("31", .day), - (", ", nil), - ("4", .hour), - (":", nil), - ("00", .minute), - (":", nil), - ("00", .second), - (" ", nil), - ("PM", .amPM), - (" ", nil), - ("PST", .timeZone), - ]) - - test(dateStyle: .long, timeStyle: .complete, dateFormatOverride: dateFormatOverride, expected: [ - (" ", nil), - ("1969", .year), - ("-", nil), - ("Dec", .month), - ("-", nil), - ("31", .day), - (" at ", nil), - ("4", .hour), - (":", nil), - ("00", .minute), - (":", nil), - ("00", .second), - (" ", nil), - ("PM", .amPM), - (" ", nil), - ("PST", .timeZone), - ]) - - test(dateStyle: .complete, timeStyle: .complete, dateFormatOverride: dateFormatOverride, expected: [ - (" ", nil), - ("1969", .year), - ("-", nil), - ("Dec", .month), - ("-", nil), - ("31", .day), - (" at ", nil), - ("4", .hour), - (":", nil), - ("00", .minute), - (":", nil), - ("00", .second), - (" ", nil), - ("PM", .amPM), - (" ", nil), - ("PST", .timeZone), - ]) - } -#endif -} - -final class DateVerbatimFormatStyleTests : XCTestCase { - var utcTimeZone = TimeZone(identifier: "UTC")! - - func testFormats() throws { - // dateFormatter.date(from: "2021-01-23 14:51:20")! - let date = Date(timeIntervalSinceReferenceDate: 633106280.0) - - func verify(_ f: Date.FormatString, expected: String, file: StaticString = #filePath, line: UInt = #line) { - let s = date.formatted(Date.VerbatimFormatStyle.verbatim(f, timeZone: utcTimeZone, calendar: Calendar(identifier: .gregorian))) - XCTAssertEqual(s, expected, file: file, line: line) - } - verify("\(month: .wide)", expected: "M01") - verify("\(month: .narrow)", expected: "1") - - verify("\(weekday: .abbreviated)", expected: "Sat") - verify("\(weekday: .wide)", expected: "Sat") - verify("\(weekday: .narrow)", expected: "S") - - verify("\(standaloneMonth: .wide)", expected: "M01") - verify("\(standaloneQuarter: .abbreviated)", expected: "Q1") - - verify("\(hour: .defaultDigits(clock: .twentyFourHour, hourCycle: .zeroBased)) heures et \(minute: .twoDigits) minutes", expected: "14 heures et 51 minutes") - verify("\(hour: .defaultDigits(clock: .twelveHour, hourCycle: .zeroBased)) heures et \(minute: .twoDigits) minutes", expected: "2 heures et 51 minutes") - } - - func testParseable() throws { - // dateFormatter.date(from: "2021-01-23 14:51:20")! - let date = Date(timeIntervalSinceReferenceDate: 633106280.0) - func verify(_ f: Date.FormatString, expectedString: String, expectedDate: Date, file: StaticString = #filePath, line: UInt = #line) { - let style = Date.VerbatimFormatStyle.verbatim(f, timeZone: utcTimeZone, calendar: Calendar(identifier: .gregorian)) - let s = date.formatted(style) - XCTAssertEqual(s, expectedString) - - let d = try? Date(s, strategy: style.parseStrategy) - XCTAssertNotNil(d) - XCTAssertEqual(d, expectedDate) - } - - // dateFormatter.date(from: "2021-01-23 00:00:00")! - verify("\(year: .twoDigits)_\(month: .defaultDigits)_\(day: .defaultDigits)", expectedString: "21_1_23", expectedDate: Date(timeIntervalSinceReferenceDate: 633052800.0)) - // dateFormatter.date(from: "2021-01-23 02:00:00")! - verify("\(year: .defaultDigits)_\(month: .defaultDigits)_\(day: .defaultDigits) at \(hour: .defaultDigits(clock: .twelveHour, hourCycle: .zeroBased)) o'clock", expectedString: "2021_1_23 at 2 o'clock", expectedDate: Date(timeIntervalSinceReferenceDate: 633060000.0)) - // dateFormatter.date(from: "2021-01-23 14:00:00")! - verify("\(year: .defaultDigits)_\(month: .defaultDigits)_\(day: .defaultDigits) at \(hour: .defaultDigits(clock: .twentyFourHour, hourCycle: .zeroBased))", expectedString: "2021_1_23 at 14", expectedDate: Date(timeIntervalSinceReferenceDate: 633103200.0)) - } - - // Test parsing strings containing `abbreviated` names - func testNonLenientParsingAbbreviatedNames() throws { - - // dateFormatter.date(from: "1970-01-01 00:00:00")! - let date = Date(timeIntervalSinceReferenceDate: -978307200.0) - func verify(_ f: Date.FormatString, localeID: String, calendarID: Calendar.Identifier, expectedString: String, file: StaticString = #filePath, line: UInt = #line) { - let style = Date.VerbatimFormatStyle.verbatim(f, locale: Locale(identifier: localeID), timeZone: .gmt, calendar: Calendar(identifier: calendarID)) - - let s = date.formatted(style) - XCTAssertEqual(s, expectedString, file: file, line: line) - - var strategy = style.parseStrategy - strategy.isLenient = false - let parsed = try? Date(s, strategy: strategy) - XCTAssertEqual(parsed, date, file: file, line: line) - } - - // Era: formatting - verify("\(era: .abbreviated) \(month: .twoDigits) \(day: .twoDigits) \(year: .defaultDigits)", localeID: "en_GB", calendarID: .gregorian, expectedString: "AD 01 01 1970") - - // Quarter: formatting - verify("\(quarter: .abbreviated) \(month: .twoDigits) \(day: .twoDigits) \(year: .defaultDigits)", localeID: "en_GB", calendarID: .gregorian, expectedString: "Q1 01 01 1970") - - // Quarter: standalone - verify("\(quarter: .abbreviated)", localeID: "en_GB", calendarID: .gregorian, expectedString: "Q1") - - // Month: formatting - verify("\(month: .abbreviated) \(day: .twoDigits) \(year: .defaultDigits)", localeID: "en_GB", calendarID: .gregorian, expectedString: "Jan 01 1970") - - // Month: standalone - verify("\(month: .abbreviated)", localeID: "en_GB", calendarID: .gregorian, expectedString: "Jan") - - // Weekday: formatting - verify("\(weekday: .abbreviated) \(month: .twoDigits) \(day: .twoDigits) \(year: .defaultDigits)", localeID: "en_GB", calendarID: .gregorian, expectedString: "Thu 01 01 1970") - - // Weekday: standalone - verify("\(weekday: .abbreviated)", localeID: "en_GB", calendarID: .gregorian, expectedString: "Thu") - - // Day period: formatting -#if FIXED_ICU_74_DAYPERIOD - verify("\(hour: .twoDigits(clock: .twelveHour, hourCycle: .zeroBased)) \(dayPeriod: .standard(.abbreviated))", localeID: "en_GB", calendarID: .gregorian, expectedString: "00 AM") -#endif // FIXED_ICU_74_DAYPERIOD - } - - func test_95845290() throws { - let formatString: Date.FormatString = "\(weekday: .abbreviated) \(month: .abbreviated) \(day: .twoDigits) \(hour: .twoDigits(clock: .twentyFourHour, hourCycle: .zeroBased)):\(minute: .twoDigits):\(second: .twoDigits) \(timeZone: .iso8601(.short)) \(year: .defaultDigits)" - let enGB = Locale(identifier: "en_GB") - let verbatim = Date.VerbatimFormatStyle(format: formatString, locale: enGB, timeZone: .init(secondsFromGMT: .zero)!, calendar: Calendar(identifier: .gregorian)) - - do { - let date = try Date("Sat Jun 18 16:10:00 +0000 2022", strategy: verbatim.parseStrategy) - // dateFormatter.date(from: "2022-06-18 16:10:00")! - XCTAssertEqual(date, Date(timeIntervalSinceReferenceDate: 677261400.0)) - } - - do { - let date = try Date("Sat Jun 18 16:10:00 +0000 2022", strategy: .fixed(format: formatString, timeZone: .gmt, locale: enGB)) - // dateFormatter.date(from: "2022-06-18 16:10:00")! - XCTAssertEqual(date, Date(timeIntervalSinceReferenceDate: 677261400.0)) - } - } - - typealias Segment = (String, AttributeScopes.FoundationAttributes.DateFieldAttribute.Field?) - - func testAttributedString() throws { - // dateFormatter.date(from: "2021-01-23 14:51:20")! - let date = Date(timeIntervalSinceReferenceDate: 633106280.0) - func verify(_ f: Date.FormatString, expected: [Segment], file: StaticString = #filePath, line: UInt = #line) { - let s = date.formatted(Date.VerbatimFormatStyle.verbatim(f, locale:Locale(identifier: "en_US"), timeZone: utcTimeZone, calendar: Calendar(identifier: .gregorian)).attributedStyle) - XCTAssertEqual(s, expected.attributedString, file: file, line: line) - } - verify("\(year: .twoDigits)_\(month: .defaultDigits)_\(day: .defaultDigits)", expected: - [("21", .year), - ("_", nil), - ("1", .month), - ("_", nil), - ("23", .day)]) - verify("\(weekday: .wide) at \(hour: .defaultDigits(clock: .twentyFourHour, hourCycle: .zeroBased))😜\(minute: .twoDigits)ðŸ„ðŸ½â€â™‚ï¸\(second: .defaultDigits)", expected: - [("Saturday", .weekday), - (" at ", nil), - ("14", .hour), - ("😜", nil), - ("51", .minute), - ("ðŸ„ðŸ½â€â™‚ï¸", nil), - ("20", .second)]) - } - - func test_storedVar() { - _ = Date.FormatStyle.dateTime - _ = Date.ISO8601FormatStyle.iso8601 - } - - func testAllIndividualFields() { - // dateFormatter.date(from: "2021-01-23 14:51:20")! - let date = Date(timeIntervalSinceReferenceDate: 633106280.0) - - let gregorian = Calendar(identifier: .gregorian) - let enUS = Locale(identifier: "en_US") - - func _verify(_ f: Date.FormatString, expected: String, file: StaticString = #filePath, line: UInt = #line) { - let s = date.formatted(Date.VerbatimFormatStyle.verbatim(f, locale: enUS, timeZone: utcTimeZone, calendar: gregorian)) - XCTAssertEqual(s, expected, file: file, line: line) - } - - _verify("\(era: .abbreviated)", expected: "AD") - _verify("\(era: .wide)", expected: "Anno Domini") - _verify("\(era: .narrow)", expected: "A") - _verify("\(year: .defaultDigits)", expected: "2021") - _verify("\(year: .twoDigits)", expected: "21") - _verify("\(year: .padded(0))", expected: "2021") - _verify("\(year: .padded(1))", expected: "2021") - _verify("\(year: .padded(2))", expected: "21") - _verify("\(year: .padded(999))", expected: "0000002021") // We cap at 10 digits - _verify("\(year: .relatedGregorian(minimumLength: 0))", expected: "2021") - _verify("\(year: .relatedGregorian(minimumLength: 999))", expected: "0000002021") - _verify("\(year: .extended(minimumLength: 0))", expected: "2021") - _verify("\(year: .extended(minimumLength: 999))", expected: "0000002021") - _verify("\(quarter: .oneDigit)", expected: "1") - _verify("\(quarter: .twoDigits)", expected: "01") - _verify("\(quarter: .abbreviated)", expected: "Q1") - _verify("\(quarter: .wide)", expected: "1st quarter") - _verify("\(quarter: .narrow)", expected: "1") - _verify("\(month: .defaultDigits)", expected: "1") - _verify("\(month: .twoDigits)", expected: "01") - _verify("\(month: .abbreviated)", expected: "Jan") - _verify("\(month: .wide)", expected: "January") - _verify("\(month: .narrow)", expected: "J") - _verify("\(week: .defaultDigits)", expected: "4") - _verify("\(week: .twoDigits)", expected: "04") - _verify("\(week: .weekOfMonth)", expected: "4") - _verify("\(day: .defaultDigits)", expected: "23") - _verify("\(day: .twoDigits)", expected: "23") - _verify("\(day: .ordinalOfDayInMonth)", expected: "4") - _verify("\(day: .julianModified(minimumLength: 0))", expected: "2459238") - _verify("\(day: .julianModified(minimumLength: 999))", expected: "0002459238") - _verify("\(dayOfYear: .defaultDigits)", expected: "23") - _verify("\(dayOfYear: .twoDigits)", expected: "23") - _verify("\(dayOfYear: .threeDigits)", expected: "023") - _verify("\(weekday: .oneDigit)", expected: "7") - _verify("\(weekday: .twoDigits)", expected: "07") - _verify("\(weekday: .abbreviated)", expected: "Sat") - _verify("\(weekday: .wide)", expected: "Saturday") - _verify("\(weekday: .narrow)", expected: "S") - _verify("\(weekday: .short)", expected: "Sa") - _verify("\(hour: .defaultDigits(clock: .twelveHour, hourCycle: .zeroBased))", expected: "2") - _verify("\(hour: .defaultDigits(clock: .twelveHour, hourCycle: .oneBased))", expected: "2") - _verify("\(hour: .defaultDigits(clock: .twentyFourHour, hourCycle: .zeroBased))", expected: "14") - _verify("\(hour: .defaultDigits(clock: .twentyFourHour, hourCycle: .oneBased))", expected: "14") - - _verify("\(hour: .twoDigits(clock: .twelveHour, hourCycle: .zeroBased))", expected: "02") - _verify("\(hour: .twoDigits(clock: .twelveHour, hourCycle: .oneBased))", expected: "02") - _verify("\(hour: .twoDigits(clock: .twentyFourHour, hourCycle: .zeroBased))", expected: "14") - _verify("\(hour: .twoDigits(clock: .twentyFourHour, hourCycle: .oneBased))", expected: "14") - } -} - -final class MatchConsumerAndSearcherTests : XCTestCase { - - let enUS = Locale(identifier: "en_US") - let utcTimeZone = TimeZone(identifier: "UTC")! - let gregorian = Calendar(identifier: .gregorian) - - func _verifyUTF16String(_ string: String, matches format: Date.FormatString, in range: Range, expectedUpperBound: Int?, expectedDate: Date?, file: StaticString = #filePath, line: UInt = #line) { - let lower = string.index(string.startIndex, offsetBy: range.lowerBound) - let upper = string.index(string.startIndex, offsetBy: range.upperBound) - - _verifyString(string, matches: format, start: lower, in: lower.., expectedUpperBound: String.Index?, expectedDate: Date?, file: StaticString = #filePath, line: UInt = #line) { - let style = Date.VerbatimFormatStyle(format: format, locale: enUS, timeZone: utcTimeZone, calendar: gregorian) - - let m = try? style.consuming(string, startingAt: start, in: range) - let matchedUpper = m?.upperBound - let match = m?.output - - let upperBoundDescription = matchedUpper?.utf16Offset(in: string) - let expectedUpperBoundDescription = expectedUpperBound?.utf16Offset(in: string) - XCTAssertEqual(matchedUpper, expectedUpperBound, "matched upperBound: \(String(describing: upperBoundDescription)), expected: \(String(describing: expectedUpperBoundDescription))", file: file, line: line) - XCTAssertEqual(match, expectedDate, file: file, line: line) - } - - func testMatchFullRanges() { - func verify(_ string: String, matches format: Date.FormatString, expectedDate: TimeInterval?, file: StaticString = #filePath, line: UInt = #line) { - let targetDate: Date? = (expectedDate != nil) ? Date(timeIntervalSinceReferenceDate: expectedDate!) : nil - _verifyString(string, matches: format, start: string.startIndex, in: string.startIndex.., matches format: Date.FormatString, expectedDate: TimeInterval, file: StaticString = #filePath, line: UInt = #line) { - _verifyUTF16String(string, matches: format, in: range, expectedUpperBound: range.upperBound, expectedDate: Date(timeIntervalSinceReferenceDate: expectedDate), file: file, line: line) - } - - // Match only up to "2022-2-1" though "2022-2-12" is also a legitimate date - verify("2022-2-12", in: 0..<8, matches: "\(year: .defaultDigits)-\(month: .defaultDigits)-\(day: .defaultDigits)", expectedDate: 665366400.0) // "2022-02-01 00:00:00" - // Match only up to "202021" though "2020218" is also a legitimate date - verify("2020218", in: 0..<6, matches: "\(year: .padded(4))\(month: .defaultDigits)\(day: .defaultDigits)", expectedDate: 602208000.0) // "2020-02-01 00:00:00" - } - - func testDateFormatStyleMatchRoundtrip() { - // dateFormatter.date(from: "2021-01-23 14:51:20")! - let date = Date(timeIntervalSinceReferenceDate: 633106280.0) - func verify(_ formatStyle: Date.FormatStyle, file: StaticString = #filePath, line: UInt = #line) { - var format = formatStyle - format.calendar = gregorian - format.timeZone = utcTimeZone - let formattedDate = format.format(date) - let embeddedDates = [ - "\(formattedDate)", - "\(formattedDate)trailing_text", - "\(formattedDate) trailing text with space", - "\(formattedDate);\(formattedDate)", - ] - - for embeddedDate in embeddedDates { - let m = try? format.consuming(embeddedDate, startingAt: embeddedDate.startIndex, in: embeddedDate.startIndex..", file: file, line: line) - XCTAssertEqual(match, date, "cannot find match in: <\(embeddedDate)>", file: file, line: line) - } - - - let embeddedMiddleDates = [ - " \(formattedDate)" : 1, - "__\(formattedDate)trailing_text" : 2, - "🥹💩\(formattedDate) 🥹💩trailing text with space": 2, - ] - - for (embeddedDate, startOffset) in embeddedMiddleDates { - let start = embeddedDate.index(embeddedDate.startIndex, offsetBy: startOffset) - let m = try? format.consuming(embeddedDate, startingAt: start, in: embeddedDate.startIndex..", file: file, line: line) - XCTAssertEqual(match, date, "cannot find match in: <\(embeddedDate)>", file: file, line: line) - } - } - - verify(Date.FormatStyle(date: .complete, time: .standard)) - verify(Date.FormatStyle(date: .complete, time: .complete)) - verify(Date.FormatStyle(date: .complete, time: .complete, locale: Locale(identifier: "zh_TW"))) - verify(Date.FormatStyle(date: .omitted, time: .complete, locale: enUS).year().month(.abbreviated).day(.twoDigits)) - verify(Date.FormatStyle(date: .omitted, time: .complete).year().month(.wide).day(.twoDigits).locale(Locale(identifier: "zh_TW"))) - } - - func testMatchPartialRangesFromMiddle() { - func verify(_ string: String, matches format: Date.FormatString, expectedMatch: String, expectedDate: TimeInterval, file: StaticString = #filePath, line: UInt = #line) { - let occurrenceRange = string.range(of: expectedMatch)! - _verifyString(string, matches: format, start: occurrenceRange.lowerBound, in: string.startIndex.. Date { - try! Date.ISO8601FormatStyle(dateSeparator: .dash, dateTimeSeparator: .space, timeZoneSeparator: .omitted, timeZone: .gmt).locale(enUSLocale).parse(string) - } - - func testBasics() throws { - let style = Date.FormatStyle(date: .complete, time: .complete) - let date = date("2021-05-05 16:00:00Z") - - XCTAssertEqual(style.discreteInput(after: date + 1), (date + 2)) - XCTAssertEqual(style.discreteInput(before: date + 1), (date + 1).nextDown) - XCTAssertEqual(style.discreteInput(after: date + 0.5), (date + 1)) - XCTAssertEqual(style.discreteInput(before: date + 0.5), (date + 0).nextDown) - XCTAssertEqual(style.discreteInput(after: date + 0), (date + 1)) - XCTAssertEqual(style.discreteInput(before: date + 0), (date + 0).nextDown) - XCTAssertEqual(style.discreteInput(after: date + -0.5), (date + 0)) - XCTAssertEqual(style.discreteInput(before: date + -0.5), (date + -1).nextDown) - XCTAssertEqual(style.discreteInput(after: date + -1), (date + 0)) - XCTAssertEqual(style.discreteInput(before: date + -1), (date + -1).nextDown) - } - - func testEvaluation() { - func assertEvaluation(of style: Date.FormatStyle, - in range: ClosedRange, - includes expectedExcerpts: [String]..., - file: StaticString = #filePath, - line: UInt = #line) { - var style = style.locale(Locale(identifier: "en_US")) - style.calendar = calendar - style.timeZone = calendar.timeZone - - verify( - sequence: style.evaluate(from: range.lowerBound, to: range.upperBound) { prev, bound in - if style.format(prev) == style.format(bound) { - return bound + 0.00001 - } else { - return bound - } - }.lazy.map(\.output), - contains: expectedExcerpts, - "(lowerbound to upperbound)", - file: file, - line: line) - - verify( - sequence: style.evaluate(from: range.upperBound, to: range.lowerBound) { prev, bound in - if style.format(prev) == style.format(bound) { - return bound - 0.00001 - } else { - return bound - } - }.lazy.map(\.output), - contains: expectedExcerpts - .reversed() - .map { $0.reversed() }, - "(upperbound to lowerbound)", - file: file, - line: line) - } - - let now = date("2023-05-15 08:47:20Z") - - assertEvaluation( - of: .init(date: .complete, time: .complete).secondFraction(.fractional(2)), - in: (now - 0.1)...(now + 0.1), - includes: [ - "Monday, May 15, 2023 at 8:47:19.90 AM GMT", - "Monday, May 15, 2023 at 8:47:19.91 AM GMT", - "Monday, May 15, 2023 at 8:47:19.92 AM GMT", - "Monday, May 15, 2023 at 8:47:19.93 AM GMT", - "Monday, May 15, 2023 at 8:47:19.94 AM GMT", - "Monday, May 15, 2023 at 8:47:19.95 AM GMT", - "Monday, May 15, 2023 at 8:47:19.96 AM GMT", - "Monday, May 15, 2023 at 8:47:19.97 AM GMT", - "Monday, May 15, 2023 at 8:47:19.98 AM GMT", - "Monday, May 15, 2023 at 8:47:19.99 AM GMT", - "Monday, May 15, 2023 at 8:47:20.00 AM GMT", - "Monday, May 15, 2023 at 8:47:20.01 AM GMT", - "Monday, May 15, 2023 at 8:47:20.02 AM GMT", - "Monday, May 15, 2023 at 8:47:20.03 AM GMT", - "Monday, May 15, 2023 at 8:47:20.04 AM GMT", - "Monday, May 15, 2023 at 8:47:20.05 AM GMT", - "Monday, May 15, 2023 at 8:47:20.06 AM GMT", - "Monday, May 15, 2023 at 8:47:20.07 AM GMT", - "Monday, May 15, 2023 at 8:47:20.08 AM GMT", - "Monday, May 15, 2023 at 8:47:20.09 AM GMT", - "Monday, May 15, 2023 at 8:47:20.10 AM GMT", - ]) - - assertEvaluation( - of: .init(date: .complete, time: .complete), - in: (now - 3)...(now + 3), - includes: [ - "Monday, May 15, 2023 at 8:47:17 AM GMT", - "Monday, May 15, 2023 at 8:47:18 AM GMT", - "Monday, May 15, 2023 at 8:47:19 AM GMT", - "Monday, May 15, 2023 at 8:47:20 AM GMT", - "Monday, May 15, 2023 at 8:47:21 AM GMT", - "Monday, May 15, 2023 at 8:47:22 AM GMT", - "Monday, May 15, 2023 at 8:47:23 AM GMT", - ]) - - assertEvaluation( - of: .init().hour(.twoDigits(amPM: .abbreviated)).minute(), - in: (now - 180)...(now + 180), - includes: [ - "08:44 AM", - "08:45 AM", - "08:46 AM", - "08:47 AM", - "08:48 AM", - "08:49 AM", - "08:50 AM", - ]) - - assertEvaluation( - of: .init(date: .omitted, time: .omitted).year().month(), - in: (now - 8 * 31 * 24 * 3600)...(now + 8 * 31 * 24 * 3600), - includes: [ - "Sep 2022", - "Oct 2022", - "Nov 2022", - "Dec 2022", - "Jan 2023", - "Feb 2023", - "Mar 2023", - "Apr 2023", - "May 2023", - "Jun 2023", - "Jul 2023", - "Aug 2023", - "Sep 2023", - "Oct 2023", - "Nov 2023", - "Dec 2023", - "Jan 2024", - ]) - - assertEvaluation( - of: .init(date: .omitted, time: .omitted).year().month().week(), - in: (now - 8 * 31 * 24 * 3600)...(now - 4 * 31 * 24 * 3600), - includes: [ - "Sep 2022 (week: 37)", - "Sep 2022 (week: 38)", - "Sep 2022 (week: 39)", - "Sep 2022 (week: 40)", - "Oct 2022 (week: 40)", - "Oct 2022 (week: 41)", - "Oct 2022 (week: 42)", - "Oct 2022 (week: 43)", - "Oct 2022 (week: 44)", - "Oct 2022 (week: 45)", - "Nov 2022 (week: 45)", - "Nov 2022 (week: 46)", - "Nov 2022 (week: 47)", - "Nov 2022 (week: 48)", - "Nov 2022 (week: 49)", - "Dec 2022 (week: 49)", - "Dec 2022 (week: 50)", - "Dec 2022 (week: 51)", - "Dec 2022 (week: 52)", - "Dec 2022 (week: 53)", - "Jan 2023 (week: 1)", - "Jan 2023 (week: 2)", - ]) - - assertEvaluation( - of: .init(date: .omitted, time: .omitted).year().month().week().era(), - in: (now - 8 * 31 * 24 * 3600)...(now - 4 * 31 * 24 * 3600), - includes: [ - "Sep 2022 AD (week: 37)", - "Sep 2022 AD (week: 38)", - "Sep 2022 AD (week: 39)", - "Sep 2022 AD (week: 40)", - "Oct 2022 AD (week: 40)", - "Oct 2022 AD (week: 41)", - "Oct 2022 AD (week: 42)", - "Oct 2022 AD (week: 43)", - "Oct 2022 AD (week: 44)", - "Oct 2022 AD (week: 45)", - "Nov 2022 AD (week: 45)", - "Nov 2022 AD (week: 46)", - "Nov 2022 AD (week: 47)", - "Nov 2022 AD (week: 48)", - "Nov 2022 AD (week: 49)", - "Dec 2022 AD (week: 49)", - "Dec 2022 AD (week: 50)", - "Dec 2022 AD (week: 51)", - "Dec 2022 AD (week: 52)", - "Dec 2022 AD (week: 53)", - "Jan 2023 AD (week: 1)", - "Jan 2023 AD (week: 2)", - ]) - } - - func testRegressions() throws { - var style: Date.FormatStyle - - style = .init(date: .complete, time: .complete).secondFraction(.fractional(2)) - style.timeZone = .gmt - XCTAssertLessThan(try XCTUnwrap(style.discreteInput(before: Date(timeIntervalSinceReferenceDate: 15538915.899999967))), Date(timeIntervalSinceReferenceDate: 15538915.899999967)) - - style = .init(date: .complete, time: .complete).secondFraction(.fractional(2)) - style.timeZone = .gmt - XCTAssertNotNil(style.input(after: Date(timeIntervalSinceReferenceDate: 1205656112.7299998))) - } - - func testRandomSamples() throws { - var style: Date.FormatStyle - - style = .init(date: .complete, time: .complete).secondFraction(.fractional(3)) - style.timeZone = .gmt - try verifyDiscreteFormatStyleConformance(style, samples: 100) - - style = .init(date: .complete, time: .complete).secondFraction(.fractional(2)) - style.timeZone = .gmt - try verifyDiscreteFormatStyleConformance(style, samples: 100) - - style = .init(date: .complete, time: .complete) - style.timeZone = .gmt - try verifyDiscreteFormatStyleConformance(style, samples: 100) - - style = .init().hour(.twoDigits(amPM: .abbreviated)).minute() - style.timeZone = .gmt - try verifyDiscreteFormatStyleConformance(style, samples: 100) - - style = .init(date: .omitted, time: .omitted).year().month() - style.timeZone = .gmt - try verifyDiscreteFormatStyleConformance(style, samples: 100) - - style = .init(date: .omitted, time: .omitted).year().month().era() - style.timeZone = .gmt - try verifyDiscreteFormatStyleConformance(style, samples: 100) - } -} - -final class TestDateVerbatimStyleDiscreteConformance : XCTestCase { - let enUSLocale = Locale(identifier: "en_US") - var calendar = Calendar(identifier: .gregorian) - - override func setUp() { - calendar.timeZone = TimeZone(abbreviation: "GMT")! - } - - func date(_ string: String) -> Date { - try! Date.ISO8601FormatStyle(dateSeparator: .dash, dateTimeSeparator: .space, timeZoneSeparator: .omitted, timeZone: .gmt).locale(enUSLocale).parse(string) - } - - func testExamples() throws { - let style = Date.VerbatimFormatStyle( - format: "\(year: .extended())-\(month: .twoDigits)-\(day: .twoDigits) \(hour: .twoDigits(clock: .twentyFourHour, hourCycle: .oneBased)):\(minute: .twoDigits):\(second: .twoDigits)", - timeZone: Calendar.current.timeZone, calendar: .current) - let date = date("2021-05-05 16:00:00Z") - - XCTAssertEqual(style.discreteInput(after: date.addingTimeInterval(1)), date.addingTimeInterval(2)) - XCTAssertEqual(style.discreteInput(before: date.addingTimeInterval(1)), date.addingTimeInterval(1).nextDown) - XCTAssertEqual(style.discreteInput(after: date.addingTimeInterval(0.5)), date.addingTimeInterval(1)) - XCTAssertEqual(style.discreteInput(before: date.addingTimeInterval(0.5)), date.addingTimeInterval(0).nextDown) - XCTAssertEqual(style.discreteInput(after: date.addingTimeInterval(0)), date.addingTimeInterval(1)) - XCTAssertEqual(style.discreteInput(before: date.addingTimeInterval(0)), date.addingTimeInterval(0).nextDown) - XCTAssertEqual(style.discreteInput(after: date.addingTimeInterval(-0.5)), date.addingTimeInterval(0)) - XCTAssertEqual(style.discreteInput(before: date.addingTimeInterval(-0.5)), date.addingTimeInterval(-1).nextDown) - XCTAssertEqual(style.discreteInput(after: date.addingTimeInterval(-1)), date.addingTimeInterval(0)) - XCTAssertEqual(style.discreteInput(before: date.addingTimeInterval(-1)), date.addingTimeInterval(-1).nextDown) - } - - func testCounting() { - func assertEvaluation(of style: Date.VerbatimFormatStyle, - in range: ClosedRange, - includes expectedExcerpts: [String]..., - file: StaticString = #filePath, - line: UInt = #line) { - var style = style.locale(enUSLocale) - style.calendar = calendar - style.timeZone = calendar.timeZone - - verify( - sequence: style.evaluate(from: range.lowerBound, to: range.upperBound) { prev, bound in - if style.format(prev) == style.format(bound) { - return bound + 0.00001 - } else { - return bound - } - }.lazy.map(\.output), - contains: expectedExcerpts, - "(lowerbound to upperbound)", - file: file, - line: line) - - verify( - sequence: style.evaluate(from: range.upperBound, to: range.lowerBound) { prev, bound in - if style.format(prev) == style.format(bound) { - return bound - 0.00001 - } else { - return bound - } - }.lazy.map(\.output), - contains: expectedExcerpts - .reversed() - .map { $0.reversed() }, - "(upperbound to lowerbound)", - file: file, - line: line) - } - - let now = date("2023-05-15 08:47:20Z") - - assertEvaluation( - of: .init(format: "\(weekday: .wide), \(month: .wide) \(day: .defaultDigits), \(year: .extended()) at \(hour: .defaultDigits(clock: .twelveHour, hourCycle: .oneBased)):\(minute: .twoDigits):\(second: .twoDigits).\(secondFraction: .fractional(2)) \(dayPeriod: .standard(.abbreviated)) \(timeZone: .genericName(.short))", timeZone: calendar.timeZone, calendar: calendar), - in: now.addingTimeInterval(-0.1)...now.addingTimeInterval(0.1), - includes: [ - "Monday, May 15, 2023 at 8:47:19.90 AM GMT", - "Monday, May 15, 2023 at 8:47:19.91 AM GMT", - "Monday, May 15, 2023 at 8:47:19.92 AM GMT", - "Monday, May 15, 2023 at 8:47:19.93 AM GMT", - "Monday, May 15, 2023 at 8:47:19.94 AM GMT", - "Monday, May 15, 2023 at 8:47:19.95 AM GMT", - "Monday, May 15, 2023 at 8:47:19.96 AM GMT", - "Monday, May 15, 2023 at 8:47:19.97 AM GMT", - "Monday, May 15, 2023 at 8:47:19.98 AM GMT", - "Monday, May 15, 2023 at 8:47:19.99 AM GMT", - "Monday, May 15, 2023 at 8:47:20.00 AM GMT", - "Monday, May 15, 2023 at 8:47:20.01 AM GMT", - "Monday, May 15, 2023 at 8:47:20.02 AM GMT", - "Monday, May 15, 2023 at 8:47:20.03 AM GMT", - "Monday, May 15, 2023 at 8:47:20.04 AM GMT", - "Monday, May 15, 2023 at 8:47:20.05 AM GMT", - "Monday, May 15, 2023 at 8:47:20.06 AM GMT", - "Monday, May 15, 2023 at 8:47:20.07 AM GMT", - "Monday, May 15, 2023 at 8:47:20.08 AM GMT", - "Monday, May 15, 2023 at 8:47:20.09 AM GMT", - "Monday, May 15, 2023 at 8:47:20.10 AM GMT", - ]) - - assertEvaluation( - of: .init(format: "'\(weekday: .wide),' '\(month: .wide)'' ss\(day: .defaultDigits), \(year: .extended()) at \(hour: .defaultDigits(clock: .twelveHour, hourCycle: .oneBased)):\(minute: .twoDigits):\(second: .twoDigits) \(dayPeriod: .standard(.abbreviated)) \(timeZone: .genericName(.short))", timeZone: calendar.timeZone, calendar: calendar), - in: now.addingTimeInterval(-3)...now.addingTimeInterval(3), - includes: [ - "'Monday,' 'May'' ss15, 2023 at 8:47:17 AM GMT", - "'Monday,' 'May'' ss15, 2023 at 8:47:18 AM GMT", - "'Monday,' 'May'' ss15, 2023 at 8:47:19 AM GMT", - "'Monday,' 'May'' ss15, 2023 at 8:47:20 AM GMT", - "'Monday,' 'May'' ss15, 2023 at 8:47:21 AM GMT", - "'Monday,' 'May'' ss15, 2023 at 8:47:22 AM GMT", - "'Monday,' 'May'' ss15, 2023 at 8:47:23 AM GMT", - ]) - - assertEvaluation( - of: .init(format: "'\(hour: .twoDigits(clock: .twelveHour, hourCycle: .oneBased)):\(minute: .twoDigits) ss \(dayPeriod: .standard(.abbreviated))", timeZone: calendar.timeZone, calendar: calendar), - in: now.addingTimeInterval(-180)...now.addingTimeInterval(180), - includes: [ - "'08:44 ss AM", - "'08:45 ss AM", - "'08:46 ss AM", - "'08:47 ss AM", - "'08:48 ss AM", - "'08:49 ss AM", - "'08:50 ss AM", - ]) - - assertEvaluation( - of: .init(format: "\(month: .abbreviated)''''\(year: .extended())", timeZone: calendar.timeZone, calendar: calendar), - in: now.addingTimeInterval(-8 * 31 * 24 * 3600)...now.addingTimeInterval(8 * 31 * 24 * 3600), - includes: [ - "Sep''''2022", - "Oct''''2022", - "Nov''''2022", - "Dec''''2022", - "Jan''''2023", - "Feb''''2023", - "Mar''''2023", - "Apr''''2023", - "May''''2023", - "Jun''''2023", - "Jul''''2023", - "Aug''''2023", - "Sep''''2023", - "Oct''''2023", - "Nov''''2023", - "Dec''''2023", - "Jan''''2024", - ]) - - assertEvaluation( - of: .init(format: "\(month: .abbreviated) \(year: .extended())'ss'(week: \(week: .defaultDigits))", timeZone: calendar.timeZone, calendar: calendar), - in: now.addingTimeInterval(-8 * 31 * 24 * 3600)...now.addingTimeInterval(-4 * 31 * 24 * 3600), - includes: [ - "Sep 2022'ss'(week: 37)", - "Sep 2022'ss'(week: 38)", - "Sep 2022'ss'(week: 39)", - "Sep 2022'ss'(week: 40)", - "Oct 2022'ss'(week: 40)", - "Oct 2022'ss'(week: 41)", - "Oct 2022'ss'(week: 42)", - "Oct 2022'ss'(week: 43)", - "Oct 2022'ss'(week: 44)", - "Oct 2022'ss'(week: 45)", - "Nov 2022'ss'(week: 45)", - "Nov 2022'ss'(week: 46)", - "Nov 2022'ss'(week: 47)", - "Nov 2022'ss'(week: 48)", - "Nov 2022'ss'(week: 49)", - "Dec 2022'ss'(week: 49)", - "Dec 2022'ss'(week: 50)", - "Dec 2022'ss'(week: 51)", - "Dec 2022'ss'(week: 52)", - "Dec 2022'ss'(week: 53)", - "Jan 2023'ss'(week: 1)", - "Jan 2023'ss'(week: 2)", - ]) - - assertEvaluation( - of: .init(format: "\(month: .abbreviated)''ss''' \(year: .extended()) \(era: .abbreviated) (week: \(week: .defaultDigits))", timeZone: calendar.timeZone, calendar: calendar), - in: now.addingTimeInterval(-8 * 31 * 24 * 3600)...now.addingTimeInterval(-4 * 31 * 24 * 3600), - includes: [ - "Sep''ss''' 2022 AD (week: 37)", - "Sep''ss''' 2022 AD (week: 38)", - "Sep''ss''' 2022 AD (week: 39)", - "Sep''ss''' 2022 AD (week: 40)", - "Oct''ss''' 2022 AD (week: 40)", - "Oct''ss''' 2022 AD (week: 41)", - "Oct''ss''' 2022 AD (week: 42)", - "Oct''ss''' 2022 AD (week: 43)", - "Oct''ss''' 2022 AD (week: 44)", - "Oct''ss''' 2022 AD (week: 45)", - "Nov''ss''' 2022 AD (week: 45)", - "Nov''ss''' 2022 AD (week: 46)", - "Nov''ss''' 2022 AD (week: 47)", - "Nov''ss''' 2022 AD (week: 48)", - "Nov''ss''' 2022 AD (week: 49)", - "Dec''ss''' 2022 AD (week: 49)", - "Dec''ss''' 2022 AD (week: 50)", - "Dec''ss''' 2022 AD (week: 51)", - "Dec''ss''' 2022 AD (week: 52)", - "Dec''ss''' 2022 AD (week: 53)", - "Jan''ss''' 2023 AD (week: 1)", - "Jan''ss''' 2023 AD (week: 2)", - ]) - } -} diff --git a/Tests/FoundationInternationalizationTests/Formatting/DateIntervalFormatStyleTests.swift b/Tests/FoundationInternationalizationTests/Formatting/DateIntervalFormatStyleTests.swift deleted file mode 100644 index d00b4c57b..000000000 --- a/Tests/FoundationInternationalizationTests/Formatting/DateIntervalFormatStyleTests.swift +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// RUN: %target-run-simple-swift -// REQUIRES: executable_test -// REQUIRES: objc_intero - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(FoundationInternationalization) -@testable import FoundationEssentials -@testable import FoundationInternationalization -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#endif - -final class DateIntervalFormatStyleTests: XCTestCase { - - let minute: TimeInterval = 60 - let hour: TimeInterval = 60 * 60 - let day: TimeInterval = 60 * 60 * 24 - let enUSLocale = Locale(identifier: "en_US") - let calendar = Calendar(identifier: .gregorian) - let timeZone = TimeZone(abbreviation: "GMT")! - - let date = Date(timeIntervalSinceReferenceDate: 0) - - let expectedSeparator = "\u{202f}" - - func testDefaultFormatStyle() throws { - var style = Date.IntervalFormatStyle() - style.timeZone = timeZone - // Make sure the default style does produce some output - XCTAssertGreaterThan(style.format(date ..< date + hour).count, 0) - } - - func testBasicFormatStyle() throws { - let style = Date.IntervalFormatStyle(locale: enUSLocale, calendar: calendar, timeZone: timeZone) - XCTAssertEqual(style.format(date.. (Date.IntervalFormatStyle)) { - - let style = customStyle(Date.IntervalFormatStyle(locale: enUSLocale, calendar: calendar, timeZone: timeZone)) - for (i, (locale, expected, expectedAfternoon)) in tests.enumerated() { - let localizedStyle = style.locale(locale) - XCTAssertEqual(localizedStyle.format(range), expected, file: file, line: line + UInt(i)) - XCTAssertEqual(localizedStyle.format(afternoon), expectedAfternoon, file: file, line: line + UInt(i)) - } - } - verify((default12, "12:00 – 1:00 AM", "1:00 – 3:00 PM"), - (default12force24, "00:00 – 01:00", "13:00 – 15:00")) { style in - style.hour().minute() - } - - verify((default24, "00:00 – 01:00", "13:00 – 15:00"), - (default24force12, "12:00 – 1:00 AM", "1:00 – 3:00 PM")) { style in - style.hour().minute() - } - -#if FIXED_96909465 - // ICU does not yet support two-digit hour configuration - verify((default12, "12:00 – 1:00 AM", "01:00 – 03:00 PM"), - (default12force24, "00:00 – 01:00", "13:00 – 15:00"), - (default24, "00:00 – 01:00", "13:00 – 15:00"), - (default24force12, "12:00 – 1:00 AM", "01:00 – 03:00 PM")) { style in - style.hour(.twoDigits(amPM: .abbreviated)).minute() - } -#endif - - verify((default12, "12:00 – 1:00", "1:00 – 3:00"), - (default12force24, "00:00 – 01:00", "13:00 – 15:00")) { style in - style.hour(.twoDigits(amPM: .omitted)).minute() - } - - verify((default24, "00:00 – 01:00", "13:00 – 15:00")) { style in - style.hour(.twoDigits(amPM: .omitted)).minute() - } - -#if FIXED_97447020 - verify() { style in - style.hour(.twoDigits(amPM: .omitted)).minute() - } -#endif - - verify((default12, "Jan 1, 12:00 – 1:00 AM", "Jan 1, 1:00 – 3:00 PM"), - (default12force24, "Jan 1, 00:00 – 01:00", "Jan 1, 13:00 – 15:00"), - (default24, "1 Jan, 00:00 – 01:00", "1 Jan, 13:00 – 15:00"), - (default24force12, "1 Jan, 12:00 – 1:00 AM", "1 Jan, 1:00 – 3:00 PM")) { style in - style.month().day().hour().minute() - } - } -#endif // FIXED_ICU_74_DAYPERIOD - - func testAutoupdatingCurrentChangesFormatResults() { - let locale = Locale.autoupdatingCurrent - let range = Date.now..<(Date.now + 3600) - - // Get a formatted result from es-ES - var prefs = LocalePreferences() - prefs.languages = ["es-ES"] - prefs.locale = "es_ES" - LocaleCache.cache.resetCurrent(to: prefs) - let formattedSpanish = range.formatted(.interval.locale(locale)) - - // Get a formatted result from en-US - prefs.languages = ["en-US"] - prefs.locale = "en_US" - LocaleCache.cache.resetCurrent(to: prefs) - let formattedEnglish = range.formatted(.interval.locale(locale)) - - // Reset to current preferences before any possibility of failing this test - LocaleCache.cache.reset() - - // No matter what 'current' was before this test was run, formattedSpanish and formattedEnglish should be different. - XCTAssertNotEqual(formattedSpanish, formattedEnglish) - } -} diff --git a/Tests/FoundationInternationalizationTests/Formatting/DateRelativeFormatStyleTests.swift b/Tests/FoundationInternationalizationTests/Formatting/DateRelativeFormatStyleTests.swift deleted file mode 100644 index 2c3e82f14..000000000 --- a/Tests/FoundationInternationalizationTests/Formatting/DateRelativeFormatStyleTests.swift +++ /dev/null @@ -1,976 +0,0 @@ -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// RUN: %target-run-simple-swift -// REQUIRES: executable_test -// REQUIRES: objc_intero - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(FoundationInternationalization) -@testable import FoundationEssentials -@testable import FoundationInternationalization -#endif - -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#endif - -final class DateRelativeFormatStyleTests: XCTestCase { - - let oneHour: TimeInterval = 60 * 60 - let oneDay: TimeInterval = 60 * 60 * 24 - let enUSLocale = Locale(identifier: "en_US") - var calendar = Calendar(identifier: .gregorian) - - - override func setUp() { - calendar.timeZone = TimeZone(abbreviation: "GMT")! - } - - func testDefaultStyle() throws { - let style = Date.RelativeFormatStyle(locale: enUSLocale, calendar: calendar) - XCTAssertEqual(style.format(Date()), "in 0 seconds") - XCTAssertEqual(style.format(Date(timeIntervalSinceNow: oneHour)), "in 1 hour") - XCTAssertEqual(style.format(Date(timeIntervalSinceNow: oneHour * 2)), "in 2 hours") - XCTAssertEqual(style.format(Date(timeIntervalSinceNow: oneDay)), "in 1 day") - XCTAssertEqual(style.format(Date(timeIntervalSinceNow: oneDay * 2)), "in 2 days") - - XCTAssertEqual(style.format(Date(timeIntervalSinceNow: -oneHour)), "1 hour ago") - XCTAssertEqual(style.format(Date(timeIntervalSinceNow: -oneHour * 2)), "2 hours ago") - - XCTAssertEqual(style.format(Date(timeIntervalSinceNow: -oneHour * 1.5)), "2 hours ago") - XCTAssertEqual(style.format(Date(timeIntervalSinceNow: oneHour * 1.5)), "in 2 hours") - } - - func testDateRelativeFormatConvenience() throws { - let now = Date() - let tomorrow = Date(timeInterval: oneDay + oneHour * 2, since: now) - let future = Date(timeInterval: oneDay * 14 + oneHour * 3, since: now) - let past = Date(timeInterval: -(oneDay * 14 + oneHour * 2), since: now) - - XCTAssertEqual(past.formatted(.relative(presentation: .named)), Date.RelativeFormatStyle(presentation: .named, unitsStyle: .wide).format(past)) - XCTAssertEqual(tomorrow.formatted(.relative(presentation: .numeric)), Date.RelativeFormatStyle(presentation: .numeric, unitsStyle: .wide).format(tomorrow)) - XCTAssertEqual(tomorrow.formatted(Date.RelativeFormatStyle(presentation: .named)), Date.RelativeFormatStyle(presentation: .named).format(tomorrow)) - - XCTAssertEqual(past.formatted(Date.RelativeFormatStyle(unitsStyle: .spellOut, capitalizationContext: .beginningOfSentence)), Date.RelativeFormatStyle(unitsStyle: .spellOut, capitalizationContext: .beginningOfSentence).format(past)) - XCTAssertEqual(future.formatted(.relative(presentation: .numeric, unitsStyle: .abbreviated)), Date.RelativeFormatStyle(unitsStyle: .abbreviated).format(future)) - } - - func testNamedStyleRounding() throws { - let named = Date.RelativeFormatStyle(presentation: .named, locale: enUSLocale, calendar: calendar) - - func _verifyStyle(_ dateValue: TimeInterval, relativeTo: TimeInterval, expected: String, file: StaticString = #filePath, line: UInt = #line) { - let date = Date(timeIntervalSinceReferenceDate: dateValue) - let refDate = Date(timeIntervalSinceReferenceDate: relativeTo) - let formatted = named._format(date, refDate: refDate) - XCTAssertEqual(formatted, expected, file: file, line: line) - } - - // Within a day - - // "2021-06-10 12:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(645019200.0, relativeTo: 645019200.0, expected: "now") - // "2021-06-10 11:59:30" -> "2021-06-10 12:00:00" - _verifyStyle(645019170.0, relativeTo: 645019200.0, expected: "30 seconds ago") - // "2021-06-10 11:59:00" -> "2021-06-10 12:00:00" - _verifyStyle(645019140.0, relativeTo: 645019200.0, expected: "1 minute ago") - // "2021-06-10 11:50:00" -> "2021-06-10 12:00:00" - _verifyStyle(645018600.0, relativeTo: 645019200.0, expected: "10 minutes ago") - // "2021-06-10 11:49:30" -> "2021-06-10 12:00:00" - _verifyStyle(645018570.0, relativeTo: 645019200.0, expected: "11 minutes ago") // 10 minutes and 30 seconds ago; rounded to 11 minutes - - // "2021-06-10 11:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(645015600.0, relativeTo: 645019200.0, expected: "1 hour ago") - // "2021-06-10 10:40:00" -> "2021-06-10 12:00:00" - _verifyStyle(645014400.0, relativeTo: 645019200.0, expected: "1 hour ago") - // "2021-06-10 10:30:00" -> "2021-06-10 12:00:00" - _verifyStyle(645013800.0, relativeTo: 645019200.0, expected: "2 hours ago") // exact 1.5 hours ago; rounded to 2 hours - - // "2021-06-10 13:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(645022800.0, relativeTo: 645019200.0, expected: "in 1 hour") - // "2021-06-10 13:20:00" -> "2021-06-10 12:00:00" - _verifyStyle(645024000.0, relativeTo: 645019200.0, expected: "in 1 hour") - // "2021-06-10 13:30:00" -> "2021-06-10 12:00:00" - _verifyStyle(645024600.0, relativeTo: 645019200.0, expected: "in 2 hours") - // "2021-06-10 13:50:00" -> "2021-06-10 12:00:00" - _verifyStyle(645025800.0, relativeTo: 645019200.0, expected: "in 2 hours") - - // More than one days - - // "2019-01-10 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(568771200.0, relativeTo: 645019200.0, expected: "2 years ago") - // "2019-12-31 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(599529599.0, relativeTo: 645019200.0, expected: "2 years ago") - - // "2020-01-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(599529600.0, relativeTo: 645019200.0, expected: "last year") - // "2020-06-10 12:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(613483200.0, relativeTo: 645019200.0, expected: "last year") // exact one year - // "2020-12-06 12:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(628948800.0, relativeTo: 645019200.0, expected: "6 months ago") // last year, but less than 12 months apart, so formatted with month - - // "2021-01-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(631152000.0, relativeTo: 645019200.0, expected: "5 months ago") - // "2021-02-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(633830400.0, relativeTo: 645019200.0, expected: "4 months ago") - // "2021-03-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(636249600.0, relativeTo: 645019200.0, expected: "3 months ago") - // "2021-04-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(638928000.0, relativeTo: 645019200.0, expected: "2 months ago") - // "2021-04-10 12:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(639748800.0, relativeTo: 645019200.0, expected: "2 months ago") - // "2021-04-30 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(641519999.0, relativeTo: 645019200.0, expected: "2 months ago") - // "2021-05-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(641520000.0, relativeTo: 645019200.0, expected: "last month") // first moment of the previous month - // "2021-05-30 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(644111999.0, relativeTo: 645019200.0, expected: "last week") // first moment of the previous week, different month - - // "2021-06-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(644198400.0, relativeTo: 645019200.0, expected: "last week") // first moment of the previous week, same month - // "2021-06-05 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(644630399.0, relativeTo: 645019200.0, expected: "5 days ago") // last moment of the previous week, but less than 7 days apart, so formatted with day - // "2021-06-06 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(644630400.0, relativeTo: 645019200.0, expected: "4 days ago") // first moment of this week - // "2021-06-08 10:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(644839200.0, relativeTo: 645019200.0, expected: "2 days ago") // the day before yesterday, but more than 48 hours apart - // "2021-06-08 13:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(644850000.0, relativeTo: 645019200.0, expected: "2 days ago") // the day before yesterday, but less than 48 hours apart - // "2021-06-09 11:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(644929200.0, relativeTo: 645019200.0, expected: "yesterday") // yesterday, but more than 24 hours apart - // "2021-06-09 13:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(644936400.0, relativeTo: 645019200.0, expected: "23 hours ago") // yesterday, but less than 24 hours apart - // "2021-06-11 07:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(645087600.0, relativeTo: 645019200.0, expected: "in 19 hours") // tomorrow, but less than 24 hours apart - // "2021-06-11 23:00:59" -> "2021-06-10 12:00:00" - _verifyStyle(645145259.0, relativeTo: 645019200.0, expected: "tomorrow") // tomorrow, but more than 24 hours apart - // "2021-06-12 11:00:59" -> "2021-06-10 12:00:00" - _verifyStyle(645188459.0, relativeTo: 645019200.0, expected: "in 2 days") // the day after tomorrow, but less than 48 hours apart - // "2021-06-12 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(645235199.0, relativeTo: 645019200.0, expected: "in 2 days") // the day after tomorrow, but more than 48 hours apart - // "2021-06-13 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(645235200.0, relativeTo: 645019200.0, expected: "in 3 days") // the first moment of the next week, but less than 7 days apart, so formatted with day - // "2021-06-19 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(645839999.0, relativeTo: 645019200.0, expected: "next week") // the last moment of the next week - // "2021-06-20 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(645840000.0, relativeTo: 645019200.0, expected: "in 2 weeks") - // "2021-06-26 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(646444799.0, relativeTo: 645019200.0, expected: "in 2 weeks") - // "2021-06-30 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(646790399.0, relativeTo: 645019200.0, expected: "in 3 weeks") // last moment of in the same month - // "2021-07-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(646790400.0, relativeTo: 645019200.0, expected: "in 3 weeks") // first moment of the next month, but than 4 weeks apart, so it's formatted with week - // "2021-07-31 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(649468799.0, relativeTo: 645019200.0, expected: "next month") // last moment of the next month - // "2021-08-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(649468800.0, relativeTo: 645019200.0, expected: "in 2 months") - // "2021-08-31 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(652147199.0, relativeTo: 645019200.0, expected: "in 2 months") - // "2022-01-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(662688000.0, relativeTo: 645019200.0, expected: "in 7 months") // next year, but less than 12 months apart, so formatted with month - // "2022-06-10 12:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(676555200.0, relativeTo: 645019200.0, expected: "next year") // exact one year - // "2022-12-31 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(694223999.0, relativeTo: 645019200.0, expected: "next year") - // "2023-01-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(694224000.0, relativeTo: 645019200.0, expected: "in 2 years") - // "2023-12-31 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(725759999.0, relativeTo: 645019200.0, expected: "in 2 years") - } - - func testNumericStyleRounding() throws { - let numeric = Date.RelativeFormatStyle(presentation: .numeric, locale: enUSLocale, calendar: calendar) - - func _verifyStyle(_ dateValue: TimeInterval, relativeTo: TimeInterval, expected: String, file: StaticString = #filePath, line: UInt = #line) { - let date = Date(timeIntervalSinceReferenceDate: dateValue) - let refDate = Date(timeIntervalSinceReferenceDate: relativeTo) - let formatted = numeric._format(date, refDate: refDate) - XCTAssertEqual(formatted, expected, file: file, line: line) - } - - // Within a day - - // "2021-06-10 12:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(645019200.0, relativeTo: 645019200.0, expected: "in 0 seconds") - // "2021-06-10 11:59:30" -> "2021-06-10 12:00:00" - _verifyStyle(645019170.0, relativeTo: 645019200.0, expected: "30 seconds ago") - // "2021-06-10 11:59:00" -> "2021-06-10 12:00:00" - _verifyStyle(645019140.0, relativeTo: 645019200.0, expected: "1 minute ago") - // "2021-06-10 11:50:00" -> "2021-06-10 12:00:00" - _verifyStyle(645018600.0, relativeTo: 645019200.0, expected: "10 minutes ago") - // "2021-06-10 11:49:30" -> "2021-06-10 12:00:00" - _verifyStyle(645018570.0, relativeTo: 645019200.0, expected: "11 minutes ago") // 10 minutes and 30 seconds ago; rounded to 11 minutes - // "2021-06-10 11:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(645015600.0, relativeTo: 645019200.0, expected: "1 hour ago") - // "2021-06-10 10:40:00" -> "2021-06-10 12:00:00" - _verifyStyle(645014400.0, relativeTo: 645019200.0, expected: "1 hour ago") - // "2021-06-10 10:30:00" -> "2021-06-10 12:00:00" - _verifyStyle(645013800.0, relativeTo: 645019200.0, expected: "2 hours ago") // exact 1.5 hours ago; rounded to 2 hours - // "2021-06-10 13:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(645022800.0, relativeTo: 645019200.0, expected: "in 1 hour") - // "2021-06-10 13:20:00" -> "2021-06-10 12:00:00" - _verifyStyle(645024000.0, relativeTo: 645019200.0, expected: "in 1 hour") - // "2021-06-10 13:30:00" -> "2021-06-10 12:00:00" - _verifyStyle(645024600.0, relativeTo: 645019200.0, expected: "in 2 hours") - // "2021-06-10 13:50:00" -> "2021-06-10 12:00:00" - _verifyStyle(645025800.0, relativeTo: 645019200.0, expected: "in 2 hours") - - // More than one day - - // "2019-01-10 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(568771200.0, relativeTo: 645019200.0, expected: "2 years ago") - // "2019-12-31 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(599529599.0, relativeTo: 645019200.0, expected: "2 years ago") - // "2020-01-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(599529600.0, relativeTo: 645019200.0, expected: "1 year ago") - // "2020-06-10 12:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(613483200.0, relativeTo: 645019200.0, expected: "1 year ago") // exact one year - // "2020-12-06 12:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(628948800.0, relativeTo: 645019200.0, expected: "6 months ago") // last year, but less than 12 months apart, so formatted with month - // "2021-01-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(631152000.0, relativeTo: 645019200.0, expected: "5 months ago") - // "2021-02-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(633830400.0, relativeTo: 645019200.0, expected: "4 months ago") - // "2021-03-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(636249600.0, relativeTo: 645019200.0, expected: "3 months ago") - // "2021-04-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(638928000.0, relativeTo: 645019200.0, expected: "2 months ago") - // "2021-04-10 12:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(639748800.0, relativeTo: 645019200.0, expected: "2 months ago") - // "2021-04-30 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(641519999.0, relativeTo: 645019200.0, expected: "2 months ago") - // "2021-05-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(641520000.0, relativeTo: 645019200.0, expected: "1 month ago") // first moment of the previous month - // "2021-05-30 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(644111999.0, relativeTo: 645019200.0, expected: "1 week ago") // first moment of the previous week, different month - // "2021-06-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(644198400.0, relativeTo: 645019200.0, expected: "1 week ago") // first moment of the previous week, same month - // "2021-06-05 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(644630399.0, relativeTo: 645019200.0, expected: "5 days ago") // last moment of the previous week, but less than 7 days apart, so formatted with day - // "2021-06-06 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(644630400.0, relativeTo: 645019200.0, expected: "4 days ago") // first moment of this week - // "2021-06-08 10:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(644839200.0, relativeTo: 645019200.0, expected: "2 days ago") // the day before yesterday, but more than 48 hours apart - // "2021-06-08 13:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(644850000.0, relativeTo: 645019200.0, expected: "2 days ago") // the day before yesterday, but less than 48 hours apart - // "2021-06-09 11:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(644929200.0, relativeTo: 645019200.0, expected: "1 day ago") // yesterday, but more than 24 hours apart - // "2021-06-09 13:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(644936400.0, relativeTo: 645019200.0, expected: "23 hours ago") // yesterday, but less than 24 hours apart - // "2021-06-11 07:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(645087600.0, relativeTo: 645019200.0, expected: "in 19 hours") // tomorrow, but less than 24 hours apart - // "2021-06-11 23:00:59" -> "2021-06-10 12:00:00" - _verifyStyle(645145259.0, relativeTo: 645019200.0, expected: "in 1 day") // tomorrow, but more than 24 hours apart - // "2021-06-12 11:00:59" -> "2021-06-10 12:00:00" - _verifyStyle(645188459.0, relativeTo: 645019200.0, expected: "in 2 days") // the day after tomorrow, but less than 48 hours apart - // "2021-06-12 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(645235199.0, relativeTo: 645019200.0, expected: "in 2 days") // the day after tomorrow, but more than 48 hours apart - // "2021-06-13 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(645235200.0, relativeTo: 645019200.0, expected: "in 3 days") // the first moment of the next week, but less than 7 days apart, so formatted with day - // "2021-06-19 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(645839999.0, relativeTo: 645019200.0, expected: "in 1 week") // the last moment of the next week - // "2021-06-20 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(645840000.0, relativeTo: 645019200.0, expected: "in 2 weeks") - // "2021-06-26 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(646444799.0, relativeTo: 645019200.0, expected: "in 2 weeks") - // "2021-06-30 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(646790399.0, relativeTo: 645019200.0, expected: "in 3 weeks") // last moment of in the same month - // "2021-07-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(646790400.0, relativeTo: 645019200.0, expected: "in 3 weeks") // first moment of the next month, but than 4 weeks apart, so it's formatted with week - // "2021-07-31 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(649468799.0, relativeTo: 645019200.0, expected: "in 1 month") // last moment of the next month - // "2021-08-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(649468800.0, relativeTo: 645019200.0, expected: "in 2 months") - // "2021-08-31 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(652147199.0, relativeTo: 645019200.0, expected: "in 2 months") - // "2022-01-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(662688000.0, relativeTo: 645019200.0, expected: "in 7 months") // next year, but less than 12 months apart, so formatted with month - // "2022-06-10 12:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(676555200.0, relativeTo: 645019200.0, expected: "in 1 year") // exact one year - // "2022-12-31 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(694223999.0, relativeTo: 645019200.0, expected: "in 1 year") - // "2023-01-01 00:00:00" -> "2021-06-10 12:00:00" - _verifyStyle(694224000.0, relativeTo: 645019200.0, expected: "in 2 years") - // "2023-12-31 23:59:59" -> "2021-06-10 12:00:00" - _verifyStyle(725759999.0, relativeTo: 645019200.0, expected: "in 2 years") - - } - - func testAutoupdatingCurrentChangesFormatResults() { - let locale = Locale.autoupdatingCurrent - let date = Date.now + 3600 - - // Get a formatted result from es-ES - var prefs = LocalePreferences() - prefs.languages = ["es-ES"] - prefs.locale = "es_ES" - LocaleCache.cache.resetCurrent(to: prefs) - let formattedSpanish = date.formatted(.relative(presentation: .named).locale(locale)) - - // Get a formatted result from en-US - prefs.languages = ["en-US"] - prefs.locale = "en_US" - LocaleCache.cache.resetCurrent(to: prefs) - let formattedEnglish = date.formatted(.relative(presentation: .named).locale(locale)) - - // Reset to current preferences before any possibility of failing this test - LocaleCache.cache.reset() - - // No matter what 'current' was before this test was run, formattedSpanish and formattedEnglish should be different. - XCTAssertNotEqual(formattedSpanish, formattedEnglish) - } - - func testAllowedFieldsNamed() throws { - var named = Date.RelativeFormatStyle(presentation: .named, locale: enUSLocale, calendar: calendar) - - func _verifyStyle(_ dateStr: String, relativeTo: String, expected: String, file: StaticString = #filePath, line: UInt = #line) { - let date = try! Date.ISO8601FormatStyle().parse(dateStr) - let refDate = try! Date.ISO8601FormatStyle().parse(relativeTo) - let formatted = named._format(date, refDate: refDate) - XCTAssertEqual(formatted, expected, file: file, line: line) - } - - named.allowedFields = [.year] - _verifyStyle("2021-06-10T12:00:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "this year") - _verifyStyle("2020-12-06T12:00:00Z", relativeTo: "2021-01-10T12:00:00Z", expected: "last year") - named.allowedFields = [.year, .hour] - _verifyStyle("2021-06-11T12:00:00Z", relativeTo: "2021-06-01T12:00:00Z", expected: "in 240 hours") - _verifyStyle("2020-12-06T12:00:00Z", relativeTo: "2021-01-10T12:00:00Z", expected: "840 hours ago") - _verifyStyle("2020-01-10T12:00:00Z", relativeTo: "2021-01-10T12:00:00Z", expected: "last year") - named.allowedFields = [.minute] - _verifyStyle("2021-06-10T11:59:31Z", relativeTo: "2021-06-10T12:00:00Z", expected: "this minute") - _verifyStyle("2021-06-10T11:59:30Z", relativeTo: "2021-06-10T12:00:00Z", expected: "1 minute ago") - _verifyStyle("2021-06-10T11:59:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "1 minute ago") - named.allowedFields = [.hour] - _verifyStyle("2021-06-10T11:50:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "this hour") - named.allowedFields = [.hour, .minute] - _verifyStyle("2021-06-10T11:49:30Z", relativeTo: "2021-06-10T12:00:00Z", expected: "11 minutes ago") - named.allowedFields = [.day] - _verifyStyle("2021-06-08T13:00:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "2 days ago") - _verifyStyle("2021-06-09T11:00:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "yesterday") - - _verifyStyle("2021-06-09T13:00:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "yesterday") - _verifyStyle("2021-06-11T07:00:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "tomorrow") - } - - func testAllowedFieldsNumeric() throws { - var named = Date.RelativeFormatStyle(presentation: .numeric, locale: enUSLocale, calendar: calendar) - - func _verifyStyle(_ dateStr: String, relativeTo: String, expected: String, file: StaticString = #filePath, line: UInt = #line) { - let date = try! Date.ISO8601FormatStyle().parse(dateStr) - let refDate = try! Date.ISO8601FormatStyle().parse(relativeTo) - let formatted = named._format(date, refDate: refDate) - XCTAssertEqual(formatted, expected, file: file, line: line) - } - - named.allowedFields = [.year] - _verifyStyle("2021-06-10T12:00:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "in 0 years") - _verifyStyle("2020-12-06T12:00:00Z", relativeTo: "2021-01-10T12:00:00Z", expected: "1 year ago") - named.allowedFields = [.minute] - _verifyStyle("2021-06-10T11:59:31Z", relativeTo: "2021-06-10T12:00:00Z", expected: "in 0 minutes") - _verifyStyle("2021-06-10T11:59:30Z", relativeTo: "2021-06-10T12:00:00Z", expected: "1 minute ago") - _verifyStyle("2021-06-10T11:59:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "1 minute ago") - named.allowedFields = [.hour] - _verifyStyle("2021-06-10T11:50:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "in 0 hours") - named.allowedFields = [.hour, .minute] - _verifyStyle("2021-06-10T11:49:30Z", relativeTo: "2021-06-10T12:00:00Z", expected: "11 minutes ago") - named.allowedFields = [.day] - _verifyStyle("2021-06-08T13:00:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "2 days ago") - _verifyStyle("2021-06-09T11:00:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "1 day ago") - - _verifyStyle("2021-06-09T13:00:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "1 day ago") - _verifyStyle("2021-06-11T07:00:00Z", relativeTo: "2021-06-10T12:00:00Z", expected: "in 1 day") - } -} - -// MARK: DiscreteFormatStyle conformance test - -final class TestDateAnchoredRelativeDiscreteConformance : XCTestCase { - let enUSLocale = Locale(identifier: "en_US") - var calendar = Calendar(identifier: .gregorian) - - override func setUp() { - calendar.timeZone = TimeZone(abbreviation: "GMT")! - } - - func date(_ string: String) -> Date { - try! Date.ISO8601FormatStyle(dateSeparator: .dash, dateTimeSeparator: .space, timeZoneSeparator: .omitted, timeZone: .gmt).locale(enUSLocale).parse(string) - } - - func testExamples() throws { - var now = Date.now - var style = Date.AnchoredRelativeFormatStyle(anchor: now) - .locale(enUSLocale) - - XCTAssertEqual(style.discreteInput(after: now.addingTimeInterval(1)), now.addingTimeInterval(1.5)) - XCTAssertEqual(style.discreteInput(before: now.addingTimeInterval(1)), now.addingTimeInterval(0.5).nextDown) - XCTAssertEqual(style.discreteInput(after: now.addingTimeInterval(0.5)), now.addingTimeInterval(1.5)) - XCTAssertEqual(style.discreteInput(before: now.addingTimeInterval(0.5)), now.addingTimeInterval(0.5).nextDown) - XCTAssertEqual(style.discreteInput(after: now.addingTimeInterval(0)), now.addingTimeInterval(0.5)) - XCTAssertEqual(style.discreteInput(before: now.addingTimeInterval(0)), now.addingTimeInterval(-0.5)) - XCTAssertEqual(style.discreteInput(after: now.addingTimeInterval(-0.5)), now.addingTimeInterval(-0.5).nextUp) - XCTAssertEqual(style.discreteInput(before: now.addingTimeInterval(-0.5)), now.addingTimeInterval(-1.5)) - XCTAssertEqual(style.discreteInput(after: now.addingTimeInterval(-1)), now.addingTimeInterval(-0.5).nextUp) - XCTAssertEqual(style.discreteInput(before: now.addingTimeInterval(-1)), now.addingTimeInterval(-1.5)) - - now = date("2021-06-10 12:00:00Z") - style.anchor = now - - - XCTAssertEqual(style.discreteInput(before: date("2021-06-10 11:58:30Z").addingTimeInterval(0.5).nextUp), date("2021-06-10 11:58:30Z").addingTimeInterval(0.5)) - XCTAssertEqual(style.discreteInput(after: date("2021-06-10 11:58:30Z").addingTimeInterval(0.5)), date("2021-06-10 11:58:30Z").addingTimeInterval(0.5).nextUp) - XCTAssertEqual(style.format(date("2021-06-10 11:58:30Z").addingTimeInterval(0.5).nextUp), "in 1 minute") - XCTAssertEqual(style.format(date("2021-06-10 11:58:30Z").addingTimeInterval(0.5)), "in 2 minutes") - - XCTAssertEqual(style.discreteInput(before: date("2021-06-10 11:57:30Z").addingTimeInterval(0.5).nextUp), date("2021-06-10 11:57:30Z").addingTimeInterval(0.5)) - XCTAssertEqual(style.discreteInput(after: date("2021-06-10 11:57:30Z").addingTimeInterval(0.5)), date("2021-06-10 11:57:30Z").addingTimeInterval(0.5).nextUp) - XCTAssertEqual(style.format(date("2021-06-10 11:57:30Z").addingTimeInterval(0.5).nextUp), "in 2 minutes") - XCTAssertEqual(style.format(date("2021-06-10 11:57:30Z").addingTimeInterval(0.5)), "in 3 minutes") - - XCTAssertEqual(style.discreteInput(before: date("2021-06-10 11:56:30Z").addingTimeInterval(0.5).nextUp), date("2021-06-10 11:56:30Z").addingTimeInterval(0.5)) - XCTAssertEqual(style.discreteInput(after: date("2021-06-10 11:56:30Z").addingTimeInterval(0.5)), date("2021-06-10 11:56:30Z").addingTimeInterval(0.5).nextUp) - XCTAssertEqual(style.format(date("2021-06-10 11:56:30Z").addingTimeInterval(0.5).nextUp), "in 3 minutes") - XCTAssertEqual(style.format(date("2021-06-10 11:56:30Z").addingTimeInterval(0.5)), "in 4 minutes") - - - - XCTAssertEqual(style.discreteInput(before: date("2021-06-10 12:01:30Z").addingTimeInterval(-0.5)), date("2021-06-10 12:01:30Z").addingTimeInterval(-0.5).nextDown) - XCTAssertEqual(style.discreteInput(after: date("2021-06-10 12:01:30Z").addingTimeInterval(-0.5).nextDown), date("2021-06-10 12:01:30Z").addingTimeInterval(-0.5)) - XCTAssertEqual(style.format(date("2021-06-10 12:01:30Z").addingTimeInterval(-0.5).nextDown), "1 minute ago") - XCTAssertEqual(style.format(date("2021-06-10 12:01:30Z").addingTimeInterval(-0.5)), "2 minutes ago") - - XCTAssertEqual(style.discreteInput(before: date("2021-06-10 12:02:30Z").addingTimeInterval(-0.5)), date("2021-06-10 12:02:30Z").addingTimeInterval(-0.5).nextDown) - XCTAssertEqual(style.discreteInput(after: date("2021-06-10 12:02:30Z").addingTimeInterval(-0.5).nextDown), date("2021-06-10 12:02:30Z").addingTimeInterval(-0.5)) - XCTAssertEqual(style.format(date("2021-06-10 12:02:30Z").addingTimeInterval(-0.5).nextDown), "2 minutes ago") - XCTAssertEqual(style.format(date("2021-06-10 12:02:30Z").addingTimeInterval(-0.5)), "3 minutes ago") - - XCTAssertEqual(style.discreteInput(before: date("2021-06-10 12:03:30Z").addingTimeInterval(-0.5)), date("2021-06-10 12:03:30Z").addingTimeInterval(-0.5).nextDown) - XCTAssertEqual(style.discreteInput(after: date("2021-06-10 12:03:30Z").addingTimeInterval(-0.5).nextDown), date("2021-06-10 12:03:30Z").addingTimeInterval(-0.5)) - XCTAssertEqual(style.format(date("2021-06-10 12:03:30Z").addingTimeInterval(-0.5).nextDown), "3 minutes ago") - XCTAssertEqual(style.format(date("2021-06-10 12:03:30Z").addingTimeInterval(-0.5)), "4 minutes ago") - } - - func testCounting() { - func assertEvaluation(of style: Date.AnchoredRelativeFormatStyle, - in range: ClosedRange, - includes expectedExcerpts: [String]..., - file: StaticString = #filePath, - line: UInt = #line) { - var style = style - .locale(enUSLocale) - style.calendar = calendar - - verify( - sequence: style.evaluate(from: range.lowerBound, to: range.upperBound).lazy.map(\.output), - contains: expectedExcerpts, - "(lowerbound to upperbound)", - file: file, - line: line) - - verify( - sequence: style.evaluate(from: range.upperBound, to: range.lowerBound).lazy.map(\.output), - contains: expectedExcerpts - .reversed() - .map { $0.reversed() }, - "(upperbound to lowerbound)", - file: file, - line: line) - } - - var now = date("2021-06-10 12:00:00Z") - - assertEvaluation( - of: .init(anchor: now, presentation: .numeric, unitsStyle: .abbreviated), - in: now.addingTimeInterval(-3)...now.addingTimeInterval(3), - includes: [ - "in 3 sec.", - "in 2 sec.", - "in 1 sec.", - "in 0 sec.", - "1 sec. ago", - "2 sec. ago", - "3 sec. ago", - ]) - - assertEvaluation( - of: .init(anchor: now, allowedFields: [.minute], presentation: .numeric, unitsStyle: .abbreviated), - in: now.addingTimeInterval(-180)...now.addingTimeInterval(180), - includes: [ - "in 3 min.", - "in 2 min.", - "in 1 min.", - "in 0 min.", - "1 min. ago", - "2 min. ago", - "3 min. ago", - ]) - - assertEvaluation( - of: .init(anchor: now, allowedFields: [.minute, .second], presentation: .numeric, unitsStyle: .abbreviated), - in: now.addingTimeInterval(-120)...now.addingTimeInterval(120), - includes: [ - "in 2 min.", - "in 1 min.", - "in 59 sec.", - "in 58 sec.", - "in 57 sec.", - "in 56 sec.", - "in 55 sec.", - ], - [ - "in 2 sec.", - "in 1 sec.", - "in 0 sec.", - "1 sec. ago", - "2 sec. ago", - ], - [ - "55 sec. ago", - "56 sec. ago", - "57 sec. ago", - "58 sec. ago", - "59 sec. ago", - "1 min. ago", - "2 min. ago", - ]) - - assertEvaluation( - of: .init(anchor: now, allowedFields: [.month], presentation: .numeric, unitsStyle: .abbreviated), - in: now.addingTimeInterval(-8 * 31 * 24 * 3600)...now.addingTimeInterval(8 * 31 * 24 * 3600), - includes: [ - "in 8 mo.", - "in 7 mo.", - "in 6 mo.", - "in 5 mo.", - "in 4 mo.", - "in 3 mo.", - "in 2 mo.", - "in 1 mo.", - "in 0 mo.", - "1 mo. ago", - "2 mo. ago", - "3 mo. ago", - "4 mo. ago", - "5 mo. ago", - "6 mo. ago", - "7 mo. ago", - "8 mo. ago", - ]) - - now = date("2023-05-15 08:47:20Z") - - assertEvaluation( - of: .init(anchor: now, allowedFields: [.month, .week], presentation: .numeric, unitsStyle: .abbreviated), - in: now.addingTimeInterval(-8 * 31 * 24 * 3600)...now.addingTimeInterval(8 * 31 * 24 * 3600), - includes: [ - "in 8 mo.", - "in 7 mo.", - "in 6 mo.", - "in 5 mo.", - "in 4 mo.", - "in 3 mo.", - "in 2 mo.", - "in 1 mo.", - "in 4 wk.", - "in 3 wk.", - "in 2 wk.", - "in 1 wk.", - "in 0 wk.", - "1 wk. ago", - "2 wk. ago", - "3 wk. ago", - "1 mo. ago", - "2 mo. ago", - "3 mo. ago", - "4 mo. ago", - "5 mo. ago", - "6 mo. ago", - "7 mo. ago", - "8 mo. ago", - ]) - - assertEvaluation( - of: .init(anchor: now, allowedFields: [.month, .week, .day, .hour], presentation: .numeric, unitsStyle: .abbreviated), - in: now.addingTimeInterval(-8 * 31 * 24 * 3600)...now.addingTimeInterval(8 * 31 * 24 * 3600), - includes: [ - "in 8 mo.", - "in 7 mo.", - "in 6 mo.", - "in 5 mo.", - "in 4 mo.", - "in 3 mo.", - "in 2 mo.", - "in 1 mo.", - "in 4 wk.", - "in 3 wk.", - "in 2 wk.", - "in 1 wk.", - "in 6 days", - "in 5 days", - "in 4 days", - "in 3 days", - "in 2 days", - "in 1 day", - "in 23 hr.", - "in 22 hr.", - "in 21 hr.", - "in 20 hr.", - "in 19 hr.", - "in 18 hr.", - "in 17 hr.", - "in 16 hr.", - "in 15 hr.", - "in 14 hr.", - "in 13 hr.", - "in 12 hr.", - "in 11 hr.", - "in 10 hr.", - "in 9 hr.", - "in 8 hr.", - "in 7 hr.", - "in 6 hr.", - "in 5 hr.", - "in 4 hr.", - "in 3 hr.", - "in 2 hr.", - "in 1 hr.", - "in 0 hr.", - "1 hr. ago", - "2 hr. ago", - "3 hr. ago", - "4 hr. ago", - "5 hr. ago", - "6 hr. ago", - "7 hr. ago", - "8 hr. ago", - "9 hr. ago", - "10 hr. ago", - "11 hr. ago", - "12 hr. ago", - "13 hr. ago", - "14 hr. ago", - "15 hr. ago", - "16 hr. ago", - "17 hr. ago", - "18 hr. ago", - "19 hr. ago", - "20 hr. ago", - "21 hr. ago", - "22 hr. ago", - "23 hr. ago", - "1 day ago", - "2 days ago", - "3 days ago", - "4 days ago", - "5 days ago", - "6 days ago", - "1 wk. ago", - "2 wk. ago", - "3 wk. ago", - "1 mo. ago", - "2 mo. ago", - "3 mo. ago", - "4 mo. ago", - "5 mo. ago", - "6 mo. ago", - "7 mo. ago", - "8 mo. ago", - ]) - - now = date("2019-06-03 09:41:00Z") - - assertEvaluation( - of: .init(anchor: now, allowedFields: [.year, .month, .day, .hour, .minute], presentation: .named, unitsStyle: .wide), - in: now.addingTimeInterval(-2 * 24 * 3600)...now.addingTimeInterval(2 * 24 * 3600), - includes: [ - "in 2 days", - "tomorrow", - "in 23 hours", - "in 22 hours", - "in 21 hours", - "in 20 hours", - "in 19 hours", - "in 18 hours", - "in 17 hours", - "in 16 hours", - "in 15 hours", - "in 14 hours", - "in 13 hours", - "in 12 hours", - "in 11 hours", - "in 10 hours", - "in 9 hours", - "in 8 hours", - "in 7 hours", - "in 6 hours", - "in 5 hours", - "in 4 hours", - "in 3 hours", - "in 2 hours", - "in 1 hour", - "in 59 minutes", - "in 58 minutes", - "in 57 minutes", - "in 56 minutes", - "in 55 minutes", - "in 54 minutes", - "in 53 minutes", - "in 52 minutes", - "in 51 minutes", - "in 50 minutes", - "in 49 minutes", - "in 48 minutes", - "in 47 minutes", - "in 46 minutes", - "in 45 minutes", - "in 44 minutes", - "in 43 minutes", - "in 42 minutes", - "in 41 minutes", - "in 40 minutes", - "in 39 minutes", - "in 38 minutes", - "in 37 minutes", - "in 36 minutes", - "in 35 minutes", - "in 34 minutes", - "in 33 minutes", - "in 32 minutes", - "in 31 minutes", - "in 30 minutes", - "in 29 minutes", - "in 28 minutes", - "in 27 minutes", - "in 26 minutes", - "in 25 minutes", - "in 24 minutes", - "in 23 minutes", - "in 22 minutes", - "in 21 minutes", - "in 20 minutes", - "in 19 minutes", - "in 18 minutes", - "in 17 minutes", - "in 16 minutes", - "in 15 minutes", - "in 14 minutes", - "in 13 minutes", - "in 12 minutes", - "in 11 minutes", - "in 10 minutes", - "in 9 minutes", - "in 8 minutes", - "in 7 minutes", - "in 6 minutes", - "in 5 minutes", - "in 4 minutes", - "in 3 minutes", - "in 2 minutes", - "in 1 minute", - "this minute", - "1 minute ago", - "2 minutes ago", - "3 minutes ago", - "4 minutes ago", - "5 minutes ago", - "6 minutes ago", - "7 minutes ago", - "8 minutes ago", - "9 minutes ago", - "10 minutes ago", - "11 minutes ago", - "12 minutes ago", - "13 minutes ago", - "14 minutes ago", - "15 minutes ago", - "16 minutes ago", - "17 minutes ago", - "18 minutes ago", - "19 minutes ago", - "20 minutes ago", - "21 minutes ago", - "22 minutes ago", - "23 minutes ago", - "24 minutes ago", - "25 minutes ago", - "26 minutes ago", - "27 minutes ago", - "28 minutes ago", - "29 minutes ago", - "30 minutes ago", - "31 minutes ago", - "32 minutes ago", - "33 minutes ago", - "34 minutes ago", - "35 minutes ago", - "36 minutes ago", - "37 minutes ago", - "38 minutes ago", - "39 minutes ago", - "40 minutes ago", - "41 minutes ago", - "42 minutes ago", - "43 minutes ago", - "44 minutes ago", - "45 minutes ago", - "46 minutes ago", - "47 minutes ago", - "48 minutes ago", - "49 minutes ago", - "50 minutes ago", - "51 minutes ago", - "52 minutes ago", - "53 minutes ago", - "54 minutes ago", - "55 minutes ago", - "56 minutes ago", - "57 minutes ago", - "58 minutes ago", - "59 minutes ago", - "1 hour ago", - "2 hours ago", - "3 hours ago", - "4 hours ago", - "5 hours ago", - "6 hours ago", - "7 hours ago", - "8 hours ago", - "9 hours ago", - "10 hours ago", - "11 hours ago", - "12 hours ago", - "13 hours ago", - "14 hours ago", - "15 hours ago", - "16 hours ago", - "17 hours ago", - "18 hours ago", - "19 hours ago", - "20 hours ago", - "21 hours ago", - "22 hours ago", - "23 hours ago", - "yesterday", - "2 days ago", - ]) - } - - func testRegressions() throws { - var style: Date.AnchoredRelativeFormatStyle - var now: Date - - now = Date(timeIntervalSinceReferenceDate: 724685580.417914) - style = .init(anchor: now, allowedFields: [.minute], presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - XCTAssertGreaterThan(try XCTUnwrap(style.discreteInput(after: Date(timeIntervalSinceReferenceDate: 12176601839.415668))), Date(timeIntervalSinceReferenceDate: 12176601839.415668)) - - - now = Date(timeIntervalSinceReferenceDate: 724686086.706003) - style = .init(anchor: now, allowedFields: [.minute], presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - XCTAssertLessThan(try XCTUnwrap(style.discreteInput(before: Date(timeIntervalSinceReferenceDate: -24141834543.08099))), Date(timeIntervalSinceReferenceDate: -24141834543.08099)) - - now = Date(timeIntervalSinceReferenceDate: 724688507.315708) - style = .init(anchor: now, allowedFields: [.minute, .second], presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - XCTAssertGreaterThan(try XCTUnwrap(style.discreteInput(after: Date(timeIntervalSinceReferenceDate: 6013270816.926929))), Date(timeIntervalSinceReferenceDate: 6013270816.926929)) - - now = Date(timeIntervalSinceReferenceDate: 724689590.234374) - style = .init(anchor: now, allowedFields: [.month, .week], presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - print(style.format(Date(timeIntervalSinceReferenceDate: 722325435.4645464))) - XCTAssertGreaterThan(try XCTUnwrap(style.discreteInput(after: Date(timeIntervalSinceReferenceDate: 722325435.4645464))), Date(timeIntervalSinceReferenceDate: 722325435.4645464)) - - now = Date(timeIntervalSinceReferenceDate: 724701229.591328) - style = .init(anchor: now, presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - /// style.discreteInput(before: Date(timeIntervalSinceReferenceDate: -7256167.2374657225)) returned Date(timeIntervalSinceReferenceDate: -31622400.5), but - /// Date(timeIntervalSinceReferenceDate: -31622400.49), which is a valid input, because style.input(after: Date(timeIntervalSinceReferenceDate: -31622400.5)) = Date(timeIntervalSinceReferenceDate: -31622400.49), - /// already produces a different formatted output 'in 24 yr' compared to style.format(Date(timeIntervalSinceReferenceDate: -7256167.2374657225)), which is 'in 23 yr' - XCTAssertGreaterThanOrEqual(try XCTUnwrap(style.discreteInput(before: Date(timeIntervalSinceReferenceDate: -7256167.2374657225))), Date(timeIntervalSinceReferenceDate: -31622400.49)) - - - now = Date(timeIntervalSinceReferenceDate: 724707086.436074) - style = .init(anchor: now, presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - /// style.discreteInput(after: Date(timeIntervalSinceReferenceDate: -728.7911686889214)) returned Date(timeIntervalSinceReferenceDate: 0.9360740142747098), but - /// Date(timeIntervalSinceReferenceDate: 0.9260740142747098), which is a valid input, because style.input(before: Date(timeIntervalSinceReferenceDate: 0.9360740142747098)) = Date(timeIntervalSinceReferenceDate: 0.9260740142747098), - /// already produces a different formatted output 'in 22 yr' compared to style.format(Date(timeIntervalSinceReferenceDate: -728.7911686889214)), which is 'in 23 yr' - XCTAssertLessThanOrEqual(try XCTUnwrap(style.discreteInput(after: Date(timeIntervalSinceReferenceDate: -728.7911686889214))), Date(timeIntervalSinceReferenceDate: 0.9260740142747098)) - - - now = Date(timeIntervalSinceReferenceDate: 724707983.332096) - style = .init(anchor: now, allowedFields: [.year, .month, .day, .hour, .minute], presentation: .named, unitsStyle: .wide) - style.calendar = self.calendar - XCTAssertGreaterThan(try XCTUnwrap(style.discreteInput(after: Date(timeIntervalSinceReferenceDate: 722086631.228182))), Date(timeIntervalSinceReferenceDate: 722086631.228182)) - - now = Date(timeIntervalSinceReferenceDate: 725887340.112405) - style = .init(anchor: now, allowedFields: [.month, .week, .day, .hour], presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - /// style.discreteInput(before: Date(timeIntervalSinceReferenceDate: 728224511.9413433)) returned Date(timeIntervalSinceReferenceDate: 727487999.6124048), but - /// Date(timeIntervalSinceReferenceDate: 727487999.6224048), which is a valid input, because style.input(after: Date(timeIntervalSinceReferenceDate: 727487999.6124048)) = Date(timeIntervalSinceReferenceDate: 727487999.6224048), - /// already produces a different formatted output '3 wk ago' compared to style.format(Date(timeIntervalSinceReferenceDate: 728224511.9413433)), which is '1 mo ago' - XCTAssertGreaterThanOrEqual(try XCTUnwrap(style.discreteInput(before: Date(timeIntervalSinceReferenceDate: 728224511.9413433))), Date(timeIntervalSinceReferenceDate: 727487999.6224048)) - - now = Date(timeIntervalSinceReferenceDate: 725895690.016681) - style = .init(anchor: now, presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - /// style.discreteInput(before: Date(timeIntervalSinceReferenceDate: 726561180.513301)) returned Date(timeIntervalSinceReferenceDate: 726364799.5166808), but - /// Date(timeIntervalSinceReferenceDate: 726364799.5266808), which is a valid input, because style.input(after: Date(timeIntervalSinceReferenceDate: 726364799.5166808)) = Date(timeIntervalSinceReferenceDate: 726364799.5266808), - /// already produces a different formatted output '6 days ago' compared to style.format(Date(timeIntervalSinceReferenceDate: 726561180.513301)), which is '1 wk ago' - XCTAssertGreaterThanOrEqual(try XCTUnwrap(style.discreteInput(before: Date(timeIntervalSinceReferenceDate: 726561180.513301))), Date(timeIntervalSinceReferenceDate: 726364799.5266808)) - - now = Date(timeIntervalSinceReferenceDate: 725903036.660503) - style = .init(anchor: now, presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - /// style.discreteInput(after: Date(timeIntervalSinceReferenceDate: 725318223.6599436)) returned Date(timeIntervalSinceReferenceDate: 725414400.1605031), but - /// Date(timeIntervalSinceReferenceDate: 725398549.919868), which is a valid input, because style.input(before: Date(timeIntervalSinceReferenceDate: 725414400.1605031)) = Date(timeIntervalSinceReferenceDate: 725414400.1505032), - /// already produces a different formatted output 'in 6 days' compared to style.format(Date(timeIntervalSinceReferenceDate: 725318223.6599436)), which is 'in 1 wk' - XCTAssertLessThanOrEqual(try XCTUnwrap(style.discreteInput(after: Date(timeIntervalSinceReferenceDate: 725318223.6599436))), Date(timeIntervalSinceReferenceDate: 725398549.919868)) - } - -#if FIXME_RANDOMIZED_SAMPLES_123465054 - func testRandomSamples() throws { - var style: Date.AnchoredRelativeFormatStyle - let now = Date.now - - lazy var message = "now = Date(timeIntervalSinceReferenceDate: \(now.timeIntervalSinceReferenceDate))" - - style = .init(anchor: now, presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - try verifyDiscreteFormatStyleConformance(style, samples: 100, message) - - style = .init(anchor: now, allowedFields: [.minute], presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - try verifyDiscreteFormatStyleConformance(style, samples: 100, message) - - style = .init(anchor: now, allowedFields: [.minute, .second], presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - try verifyDiscreteFormatStyleConformance(style, samples: 100, message) - - style = .init(anchor: now, allowedFields: [.month], presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - try verifyDiscreteFormatStyleConformance(style, samples: 100, message) - - style = .init(anchor: now, allowedFields: [.month, .week], presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - try verifyDiscreteFormatStyleConformance(style, samples: 100, message) - - style = .init(anchor: now, allowedFields: [.month, .week, .day, .hour], presentation: .numeric, unitsStyle: .abbreviated) - style.calendar = self.calendar - try verifyDiscreteFormatStyleConformance(style, samples: 100, message) - - style = .init(anchor: now, allowedFields: [.year, .month, .day, .hour, .minute], presentation: .named, unitsStyle: .wide) - style.calendar = self.calendar - try verifyDiscreteFormatStyleConformance(style, samples: 100, message) - } -#endif -} diff --git a/Tests/FoundationInternationalizationTests/Formatting/DiscreteFormatStyleTestUtilities.swift b/Tests/FoundationInternationalizationTests/Formatting/DiscreteFormatStyleTestUtilities.swift deleted file mode 100644 index c6b9a88e4..000000000 --- a/Tests/FoundationInternationalizationTests/Formatting/DiscreteFormatStyleTestUtilities.swift +++ /dev/null @@ -1,422 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#if canImport(TestSupport) -import TestSupport -#endif - -#if canImport(FoundationEssentials) -@testable import FoundationEssentials -#endif - -#if canImport(FoundationInternationalization) -@testable import FoundationInternationalization -#endif - -extension DiscreteFormatStyle where FormatInput : Comparable { - /// Produces a sequence that generates all outputs of a discrete format style from a given start to a given end. - func evaluate(from initialInput: FormatInput, to end: FormatInput, _ advance: @escaping (FormatInput, FormatInput) -> FormatInput? = { prev, next in next }) -> LazySequence> { - DiscreteFormatStyleSequence(style: self, input: initialInput, end: end, advance: advance, isLower: <).lazy - } -} - -extension DiscreteFormatStyle { - /// Produces a sequence that generates all outputs of a discrete format style from a given start to a given end. - func evaluate(from initialInput: FormatInput, to end: FormatInput, _ advance: @escaping (FormatInput, FormatInput) -> FormatInput? = { prev, next in next }, isLower: @escaping (FormatInput, FormatInput) -> Bool) -> LazySequence> { - DiscreteFormatStyleSequence(style: self, input: initialInput, end: end, advance: advance, isLower: isLower).lazy - } -} - -/// A sequence that generates all outputs of a discrete format style from a given start to a given end. -struct DiscreteFormatStyleSequence : Sequence, IteratorProtocol { - private let style: Style - private var input: Style.FormatInput - private let end: Style.FormatInput - private let isIncreasing: Bool - private let advance: (Style.FormatInput, Style.FormatInput) -> Style.FormatInput? - private var abort: Bool = false - private let isLower: (Style.FormatInput, Style.FormatInput) -> Bool - - init(style: Style, input: Style.FormatInput, end: Style.FormatInput, advance: @escaping (Style.FormatInput, Style.FormatInput) -> Style.FormatInput?, isLower: @escaping (Style.FormatInput, Style.FormatInput) -> Bool) { - self.style = style - self.input = input - self.end = end - self.isIncreasing = isLower(input, end) - self.advance = advance - self.isLower = isLower - } - - func makeIterator() -> DiscreteFormatStyleSequence