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',