Merge pull request #926 from rxwei/master
diff --git a/CoreFoundation/Base.subproj/CFRuntime.c b/CoreFoundation/Base.subproj/CFRuntime.c
index 2672704..8a01c0f 100644
--- a/CoreFoundation/Base.subproj/CFRuntime.c
+++ b/CoreFoundation/Base.subproj/CFRuntime.c
@@ -999,9 +999,9 @@
#ifndef __CFSwiftGetBaseClass
#if TARGET_OS_LINUX
-#define __CFSwiftGetBaseClass _TF10Foundation21__CFSwiftGetBaseClassFT_PMPs9AnyObject_
+#define __CFSwiftGetBaseClass _T010Foundation21__CFSwiftGetBaseClasss9AnyObject_pXpyF
#elif TARGET_OS_MAC
-#define __CFSwiftGetBaseClass _TF15SwiftFoundation21__CFSwiftGetBaseClassFT_PMPs9AnyObject_
+#define __CFSwiftGetBaseClass _T015SwiftFoundation21__CFSwiftGetBaseClasss9AnyObject_pXpyF
#endif
#endif
extern uintptr_t __CFSwiftGetBaseClass();
@@ -1108,9 +1108,9 @@
#if DEPLOYMENT_RUNTIME_SWIFT
#ifndef __CFInitializeSwift
#if TARGET_OS_LINUX
-#define __CFInitializeSwift _TF10Foundation19__CFInitializeSwiftFT_T_
+#define __CFInitializeSwift _T010Foundation19__CFInitializeSwiftyyF
#elif TARGET_OS_MAC
-#define __CFInitializeSwift _TF15SwiftFoundation19__CFInitializeSwiftFT_T_
+#define __CFInitializeSwift _T015SwiftFoundation014__CFInitializeA0yyF
#endif
#endif
extern void __CFInitializeSwift();
diff --git a/Foundation/NSError.swift b/Foundation/NSError.swift
index c83403e..5c675de 100644
--- a/Foundation/NSError.swift
+++ b/Foundation/NSError.swift
@@ -377,8 +377,8 @@
}
public extension __BridgedNSError where Self: RawRepresentable, Self.RawValue: SignedInteger {
- public final var _domain: String { return Self._nsErrorDomain }
- public final var _code: Int { return Int(rawValue.toIntMax()) }
+ public var _domain: String { return Self._nsErrorDomain }
+ public var _code: Int { return Int(rawValue.toIntMax()) }
public init?(rawValue: RawValue) {
self = unsafeBitCast(rawValue, to: Self.self)
@@ -392,7 +392,7 @@
self.init(rawValue: RawValue(IntMax(_bridgedNSError.code)))
}
- public final var hashValue: Int { return _code }
+ public var hashValue: Int { return _code }
}
// Allow two bridged NSError types to be compared.
@@ -403,8 +403,8 @@
}
public extension __BridgedNSError where Self: RawRepresentable, Self.RawValue: UnsignedInteger {
- public final var _domain: String { return Self._nsErrorDomain }
- public final var _code: Int {
+ public var _domain: String { return Self._nsErrorDomain }
+ public var _code: Int {
return Int(bitPattern: UInt(rawValue.toUIntMax()))
}
@@ -420,7 +420,7 @@
self.init(rawValue: RawValue(UIntMax(UInt(_bridgedNSError.code))))
}
- public final var hashValue: Int { return _code }
+ public var hashValue: Int { return _code }
}
/// Describes a raw representable type that is bridged to a particular
diff --git a/Foundation/NSJSONSerialization.swift b/Foundation/NSJSONSerialization.swift
index 8e08b85..36120e3 100644
--- a/Foundation/NSJSONSerialization.swift
+++ b/Foundation/NSJSONSerialization.swift
@@ -716,22 +716,25 @@
defer { intEndPointer.deallocate(capacity: 1) }
let doubleEndPointer = UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>.allocate(capacity: 1)
defer { doubleEndPointer.deallocate(capacity: 1) }
-
let intResult = strtol(startPointer, intEndPointer, 10)
let intDistance = startPointer.distance(to: intEndPointer[0]!)
let doubleResult = strtod(startPointer, doubleEndPointer)
let doubleDistance = startPointer.distance(to: doubleEndPointer[0]!)
-
+
guard intDistance > 0 || doubleDistance > 0 else {
return nil
}
-
+
if intDistance == doubleDistance {
return (intResult, intDistance)
}
guard doubleDistance > 0 else {
return nil
}
+
+ if doubleResult == doubleResult.rounded() {
+ return (Int(doubleResult), doubleDistance)
+ }
return (doubleResult, doubleDistance)
}
}
diff --git a/Foundation/NSOperation.swift b/Foundation/NSOperation.swift
index fcc9b38..988aef8 100644
--- a/Foundation/NSOperation.swift
+++ b/Foundation/NSOperation.swift
@@ -47,7 +47,6 @@
#endif
}
- /// - Note: Operations that are asynchronous from the execution of the operation queue itself are not supported since there is no KVO to trigger the finish.
open func start() {
main()
finish()
@@ -159,6 +158,24 @@
}
}
+/// The following two methods are added to provide support for Operations which
+/// are asynchronous from the execution of the operation queue itself. On Darwin,
+/// this is supported via KVO notifications. In the absence of KVO on non-Darwin
+/// platforms, these two methods (which are defined in NSObject on Darwin) are
+/// temporarily added here. They should be removed once a permanent solution is
+/// found.
+extension Operation {
+ public func willChangeValue(forKey key: String) {
+ // do nothing
+ }
+
+ public func didChangeValue(forKey key: String) {
+ if key == "isFinished" && isFinished {
+ finish()
+ }
+ }
+}
+
extension Operation {
public enum QueuePriority : Int {
case veryLow
diff --git a/Foundation/NSRegularExpression.swift b/Foundation/NSRegularExpression.swift
index 0d1a289..ec4a88e 100644
--- a/Foundation/NSRegularExpression.swift
+++ b/Foundation/NSRegularExpression.swift
@@ -75,7 +75,7 @@
/* An instance of NSRegularExpression is created from a regular expression pattern and a set of options. If the pattern is invalid, nil will be returned and an NSError will be returned by reference. The pattern syntax currently supported is that specified by ICU.
*/
- public init(pattern: String, options: Options) throws {
+ public init(pattern: String, options: Options = []) throws {
var error: Unmanaged<CFError>?
#if os(OSX) || os(iOS)
let opt = _CFRegularExpressionOptions(rawValue: options.rawValue)
@@ -277,12 +277,12 @@
var count = 0
var offset = 0
for result in results {
- var currentRnage = result.range
+ var currentRange = result.range
let replacement = replacementString(for: result, in: string._swiftObject, offset: offset, template: templ)
- currentRnage.location += offset
+ currentRange.location += offset
- string.replaceCharacters(in: currentRnage, with: replacement)
- offset += replacement.length - currentRnage.length
+ string.replaceCharacters(in: currentRange, with: replacement)
+ offset += replacement.length - currentRange.length
count += 1
}
return count
diff --git a/Foundation/NSString.swift b/Foundation/NSString.swift
index de75c17..7f2d181 100644
--- a/Foundation/NSString.swift
+++ b/Foundation/NSString.swift
@@ -1298,7 +1298,33 @@
}
public convenience init(contentsOf url: URL, usedEncoding enc: UnsafeMutablePointer<UInt>?) throws {
- NSUnimplemented()
+ let readResult = try NSData(contentsOf: url, options:[])
+
+ let bytePtr = readResult.bytes.bindMemory(to: UInt8.self, capacity:readResult.length)
+ if readResult.length >= 2 && bytePtr[0] == 254 && bytePtr[1] == 255 {
+ enc?.pointee = String.Encoding.utf16BigEndian.rawValue
+ }
+ else if readResult.length >= 2 && bytePtr[0] == 255 && bytePtr[1] == 254 {
+ enc?.pointee = String.Encoding.utf16LittleEndian.rawValue
+ }
+ else {
+ //Need to work on more conditions. This should be the default
+ enc?.pointee = String.Encoding.utf8.rawValue
+ }
+
+ guard let enc = enc, let cf = CFStringCreateWithBytes(kCFAllocatorDefault, bytePtr, readResult.length, CFStringConvertNSStringEncodingToEncoding(enc.pointee), true) else {
+ throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileReadInapplicableStringEncoding.rawValue, userInfo: [
+ "NSDebugDescription" : "Unable to create a string using the specified encoding."
+ ])
+ }
+ var str: String?
+ if String._conditionallyBridgeFromObjectiveC(cf._nsObject, result: &str) {
+ self.init(str!)
+ } else {
+ throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileReadInapplicableStringEncoding.rawValue, userInfo: [
+ "NSDebugDescription" : "Unable to bridge CFString to String."
+ ])
+ }
}
public convenience init(contentsOfFile path: String, usedEncoding enc: UnsafeMutablePointer<UInt>?) throws {
diff --git a/Foundation/Progress.swift b/Foundation/Progress.swift
index 3f16c2a..08c3e30 100644
--- a/Foundation/Progress.swift
+++ b/Foundation/Progress.swift
@@ -292,8 +292,8 @@
open var pausingHandler: (() -> Void)? {
didSet {
guard let handler = pausingHandler else { return }
- // If we're already cancelled, then invoke it - asynchronously
- if isCancelled {
+ // If we're already paused, then invoke it - asynchronously
+ if isPaused {
DispatchQueue.global().async {
handler()
}
diff --git a/TestFoundation/Resources/NSString-UTF16-BE-data.txt b/TestFoundation/Resources/NSString-UTF16-BE-data.txt
new file mode 100644
index 0000000..b28d473
--- /dev/null
+++ b/TestFoundation/Resources/NSString-UTF16-BE-data.txt
Binary files differ
diff --git a/TestFoundation/Resources/NSString-UTF16-LE-data.txt b/TestFoundation/Resources/NSString-UTF16-LE-data.txt
new file mode 100644
index 0000000..d9f85ab
--- /dev/null
+++ b/TestFoundation/Resources/NSString-UTF16-LE-data.txt
Binary files differ
diff --git a/TestFoundation/TestNSJSONSerialization.swift b/TestFoundation/TestNSJSONSerialization.swift
index 33eadcb..0e4e09f 100644
--- a/TestFoundation/TestNSJSONSerialization.swift
+++ b/TestFoundation/TestNSJSONSerialization.swift
@@ -468,7 +468,7 @@
XCTAssertEqual(result?[1] as? Int, -1)
XCTAssertEqual(result?[2] as? Double, 1.3)
XCTAssertEqual(result?[3] as? Double, -1.3)
- XCTAssertEqual(result?[4] as? Double, 1000)
+ XCTAssertEqual(result?[4] as? Int, 1000)
XCTAssertEqual(result?[5] as? Double, 0.001)
}
} catch {
@@ -871,6 +871,7 @@
("test_jsonObjectToOutputStreamInsufficientBuffer", test_jsonObjectToOutputStreamInsufficientBuffer),
("test_booleanJSONObject", test_booleanJSONObject),
("test_serialize_dictionaryWithDecimal", test_serialize_dictionaryWithDecimal),
+ ("test_serializeDecimalNumberJSONObject", test_serializeDecimalNumberJSONObject),
]
}
@@ -1214,6 +1215,22 @@
XCTAssertTrue(JSONSerialization.isValidJSONObject([true]))
}
+ func test_serializeDecimalNumberJSONObject() {
+ let decimalArray = "[12.1,10.0,0.0,0.0001,20,\(Int.max)]"
+ do {
+ let data = decimalArray.data(using: String.Encoding.utf8)
+ let result = try JSONSerialization.jsonObject(with: data!, options: []) as? [Any]
+ XCTAssertEqual(result?[0] as! Double, 12.1)
+ XCTAssertEqual(result?[1] as! Int, 10)
+ XCTAssertEqual(result?[2] as! Int, 0)
+ XCTAssertEqual(result?[3] as! Double, 0.0001)
+ XCTAssertEqual(result?[4] as! Int, 20)
+ XCTAssertEqual(result?[5] as! Int, Int.max)
+ } catch {
+ XCTFail("Failed during serialization")
+ }
+ }
+
fileprivate func createTestFile(_ path: String,_contents: Data) -> String? {
let tempDir = NSTemporaryDirectory() + "TestFoundation_Playground_" + NSUUID().uuidString + "/"
do {
diff --git a/TestFoundation/TestNSNotificationQueue.swift b/TestFoundation/TestNSNotificationQueue.swift
index 30a6645..2cea068 100644
--- a/TestFoundation/TestNSNotificationQueue.swift
+++ b/TestFoundation/TestNSNotificationQueue.swift
@@ -19,6 +19,9 @@
class TestNSNotificationQueue : XCTestCase {
static var allTests : [(String, (TestNSNotificationQueue) -> () throws -> Void)] {
return [
+/*
+FIXME SR-4280 timeouts in TestNSNotificationQueue tests
+
("test_defaultQueue", test_defaultQueue),
("test_postNowToDefaultQueueWithoutCoalescing", test_postNowToDefaultQueueWithoutCoalescing),
("test_postNowToDefaultQueueWithCoalescing", test_postNowToDefaultQueueWithCoalescing),
@@ -29,6 +32,7 @@
("test_postAsapToDefaultQueueWithCoalescingOnNameAndSender", test_postAsapToDefaultQueueWithCoalescingOnNameAndSender),
("test_postAsapToDefaultQueueWithCoalescingOnNameOrSender", test_postAsapToDefaultQueueWithCoalescingOnNameOrSender),
("test_postIdleToDefaultQueue", test_postIdleToDefaultQueue),
+*/
]
}
diff --git a/TestFoundation/TestNSOperationQueue.swift b/TestFoundation/TestNSOperationQueue.swift
index cc74b86..783115f 100644
--- a/TestFoundation/TestNSOperationQueue.swift
+++ b/TestFoundation/TestNSOperationQueue.swift
@@ -16,12 +16,14 @@
import SwiftFoundation
import SwiftXCTest
#endif
+import Dispatch
class TestNSOperationQueue : XCTestCase {
static var allTests: [(String, (TestNSOperationQueue) -> () throws -> Void)] {
return [
("test_OperationPriorities", test_OperationPriorities),
- ("test_OperationCount", test_OperationCount)
+ ("test_OperationCount", test_OperationCount),
+ ("test_AsyncOperation", test_AsyncOperation)
]
}
@@ -65,4 +67,76 @@
XCTAssertEqual(msgOperations[2], "Operation2 executed")
XCTAssertEqual(msgOperations[3], "Operation4 executed")
}
+
+ func test_AsyncOperation() {
+ let operation = AsyncOperation()
+ XCTAssertFalse(operation.isExecuting)
+ XCTAssertFalse(operation.isFinished)
+
+ operation.start()
+
+ while !operation.isFinished {
+ // do nothing
+ }
+
+ XCTAssertFalse(operation.isExecuting)
+ XCTAssertTrue(operation.isFinished)
+ }
+}
+
+class AsyncOperation: Operation {
+
+ private let queue = DispatchQueue(label: "async.operation.queue")
+ private let lock = NSLock()
+
+ private var _executing = false
+ private var _finished = false
+
+ override internal(set) var isExecuting: Bool {
+ get {
+ return _executing
+ }
+ set {
+ if _executing != newValue {
+ willChangeValue(forKey: "isExecuting")
+ _executing = newValue
+ didChangeValue(forKey: "isExecuting")
+ }
+ }
+ }
+
+ override internal(set) var isFinished: Bool {
+ get {
+ return _finished
+ }
+ set {
+ if _finished != newValue {
+ willChangeValue(forKey: "isFinished")
+ _finished = newValue
+ didChangeValue(forKey: "isFinished")
+ }
+ }
+ }
+
+ override var isAsynchronous: Bool {
+ return true
+ }
+
+ override func start() {
+ if isCancelled {
+ isFinished = true
+ return
+ }
+
+ isExecuting = true
+
+ queue.async {
+ sleep(1)
+ self.lock.lock()
+ self.isExecuting = false
+ self.isFinished = true
+ self.lock.unlock()
+ }
+ }
+
}
diff --git a/TestFoundation/TestNSRegularExpression.swift b/TestFoundation/TestNSRegularExpression.swift
index 5e5eb77..8b115cc 100644
--- a/TestFoundation/TestNSRegularExpression.swift
+++ b/TestFoundation/TestNSRegularExpression.swift
@@ -35,7 +35,7 @@
do {
let str = NSString(string: searchString)
var range = NSMakeRange(0, str.length)
- let regex = try NSRegularExpression(pattern: patternString, options: [])
+ let regex = try NSRegularExpression(pattern: patternString)
do {
let lookingRange = regex.rangeOfFirstMatch(in: searchString, options: .anchored, range: range)
let matchRange = regex.rangeOfFirstMatch(in: searchString, options: [], range: range)
diff --git a/TestFoundation/TestNSString.swift b/TestFoundation/TestNSString.swift
index 86e5daa..58a1c8a 100644
--- a/TestFoundation/TestNSString.swift
+++ b/TestFoundation/TestNSString.swift
@@ -66,6 +66,8 @@
("test_rangeOfCharacterFromSet", test_rangeOfCharacterFromSet ),
("test_CFStringCreateMutableCopy", test_CFStringCreateMutableCopy),
("test_FromContentsOfURL",test_FromContentsOfURL),
+ ("test_FromContentsOfURLUsedEncodingUTF16BE", test_FromContentsOfURLUsedEncodingUTF16BE),
+ ("test_FromContentsOfURLUsedEncodingUTF16LE", test_FromContentsOfURLUsedEncodingUTF16LE),
("test_FromContentOfFile",test_FromContentOfFile),
("test_swiftStringUTF16", test_swiftStringUTF16),
// This test takes forever on build servers; it has been seen up to 1852.084 seconds
@@ -300,6 +302,38 @@
}
}
+ func test_FromContentsOfURLUsedEncodingUTF16BE() {
+ guard let testFileURL = testBundle().url(forResource: "NSString-UTF16-BE-data", withExtension: "txt") else {
+ XCTFail("URL for NSString-UTF16-BE-data.txt is nil")
+ return
+ }
+
+ do {
+ var encoding: UInt = 0
+ let string = try NSString(contentsOf: testFileURL, usedEncoding: &encoding)
+ XCTAssertEqual(string, "NSString fromURL usedEncoding test with UTF16 BE file", "Wrong result when reading UTF16BE file")
+ XCTAssertEqual(encoding, String.Encoding.utf16BigEndian.rawValue, "Wrong encoding detected from UTF16BE file")
+ } catch {
+ XCTFail("Unable to init NSString from contentsOf:usedEncoding:")
+ }
+ }
+
+ func test_FromContentsOfURLUsedEncodingUTF16LE() {
+ guard let testFileURL = testBundle().url(forResource: "NSString-UTF16-LE-data", withExtension: "txt") else {
+ XCTFail("URL for NSString-UTF16-LE-data.txt is nil")
+ return
+ }
+
+ do {
+ var encoding: UInt = 0
+ let string = try NSString(contentsOf: testFileURL, usedEncoding: &encoding)
+ XCTAssertEqual(string, "NSString fromURL usedEncoding test with UTF16 LE file", "Wrong result when reading UTF16LE file")
+ XCTAssertEqual(encoding, String.Encoding.utf16LittleEndian.rawValue, "Wrong encoding detected from UTF16LE file")
+ } catch {
+ XCTFail("Unable to init NSString from contentOf:usedEncoding:")
+ }
+ }
+
func test_FromContentOfFile() {
let testFilePath = testBundle().path(forResource: "NSStringTestData", ofType: "txt")
XCTAssertNotNil(testFilePath)
diff --git a/build.py b/build.py
index 4f9d9e9..625b17c 100644
--- a/build.py
+++ b/build.py
@@ -16,7 +16,7 @@
swift_cflags = ['-DDEPLOYMENT_RUNTIME_SWIFT']
if Configuration.current.target.sdk == OSType.Linux:
foundation.CFLAGS = '-DDEPLOYMENT_TARGET_LINUX -D_GNU_SOURCE -DCF_CHARACTERSET_DATA_DIR="CoreFoundation/CharacterSets"'
- foundation.LDFLAGS = '${SWIFT_USE_LINKER} -Wl,@./CoreFoundation/linux.ld -lswiftGlibc `${PKG_CONFIG} icu-uc icu-i18n --libs` -Wl,-defsym,__CFConstantStringClassReference=_TMC10Foundation19_NSCFConstantString -Wl,-Bsymbolic '
+ foundation.LDFLAGS = '${SWIFT_USE_LINKER} -Wl,@./CoreFoundation/linux.ld -lswiftGlibc `${PKG_CONFIG} icu-uc icu-i18n --libs` -Wl,-defsym,__CFConstantStringClassReference=_T010Foundation19_NSCFConstantStringCN -Wl,-Bsymbolic '
Configuration.current.requires_pkg_config = True
elif Configuration.current.target.sdk == OSType.FreeBSD:
foundation.CFLAGS = '-DDEPLOYMENT_TARGET_FREEBSD -I/usr/local/include -I/usr/local/include/libxml2 -I/usr/local/include/curl '
@@ -26,7 +26,7 @@
foundation.LDFLAGS = '-licucore -twolevel_namespace -Wl,-alias_list,CoreFoundation/Base.subproj/DarwinSymbolAliases -sectcreate __UNICODE __csbitmaps CoreFoundation/CharacterSets/CFCharacterSetBitmaps.bitmap -sectcreate __UNICODE __properties CoreFoundation/CharacterSets/CFUniCharPropertyDatabase.data -sectcreate __UNICODE __data CoreFoundation/CharacterSets/CFUnicodeData-L.mapping -segprot __UNICODE r r '
elif Configuration.current.target.sdk == OSType.Win32 and Configuration.current.target.environ == EnvironmentType.Cygnus:
foundation.CFLAGS = '-DDEPLOYMENT_TARGET_LINUX -D_GNU_SOURCE -mcmodel=large '
- foundation.LDFLAGS = '${SWIFT_USE_LINKER} -lswiftGlibc `icu-config --ldflags` -Wl,-defsym,__CFConstantStringClassReference=_TMC10Foundation19_NSCFConstantString,--allow-multiple-definition '
+ foundation.LDFLAGS = '${SWIFT_USE_LINKER} -lswiftGlibc `icu-config --ldflags` -Wl,-defsym,__CFConstantStringClassReference=_T010Foundation19_NSCFConstantStringCN,--allow-multiple-definition '
swift_cflags += ['-DCYGWIN']
if Configuration.current.build_mode == Configuration.Debug:
@@ -460,6 +460,8 @@
'TestFoundation/Resources/NSURLTestData.plist',
'TestFoundation/Resources/Test.plist',
'TestFoundation/Resources/NSStringTestData.txt',
+ 'TestFoundation/Resources/NSString-UTF16-BE-data.txt',
+ 'TestFoundation/Resources/NSString-UTF16-LE-data.txt',
'TestFoundation/Resources/NSXMLDocumentTestData.xml',
'TestFoundation/Resources/PropertyList-1.0.dtd',
'TestFoundation/Resources/NSXMLDTDTestData.xml',