Merge pull request #1225 from dplanitzer/NSString-contents-of-file

diff --git a/Foundation/NSString.swift b/Foundation/NSString.swift
index 26c45b5..b27719a 100644
--- a/Foundation/NSString.swift
+++ b/Foundation/NSString.swift
@@ -1248,33 +1248,37 @@
     public convenience init(contentsOf url: URL, usedEncoding enc: UnsafeMutablePointer<UInt>?) throws {
         let readResult = try NSData(contentsOf: url, options:[])
 
-        var offset = 0
+        let encoding: UInt
+        let offset: Int
         let bytePtr = readResult.bytes.bindMemory(to: UInt8.self, capacity:readResult.length)
         if readResult.length >= 4 && bytePtr[0] == 0xFF && bytePtr[1] == 0xFE && bytePtr[2] == 0x00 && bytePtr[3] == 0x00 {
-            enc?.pointee = String.Encoding.utf32LittleEndian.rawValue
+            encoding = String.Encoding.utf32LittleEndian.rawValue
             offset = 4
         }
         else if readResult.length >= 2 && bytePtr[0] == 0xFE && bytePtr[1] == 0xFF {
-            enc?.pointee = String.Encoding.utf16BigEndian.rawValue
+            encoding = String.Encoding.utf16BigEndian.rawValue
             offset = 2
         }
         else if readResult.length >= 2 && bytePtr[0] == 0xFF && bytePtr[1] == 0xFE {
-            enc?.pointee = String.Encoding.utf16LittleEndian.rawValue
+            encoding = String.Encoding.utf16LittleEndian.rawValue
             offset = 2
         }
         else if readResult.length >= 4 && bytePtr[0] == 0x00 && bytePtr[1] == 0x00 && bytePtr[2] == 0xFE && bytePtr[3] == 0xFF {
-            enc?.pointee = String.Encoding.utf32BigEndian.rawValue
+            encoding = String.Encoding.utf32BigEndian.rawValue
             offset = 4
         }
         else {
             //Need to work on more conditions. This should be the default
-            enc?.pointee = String.Encoding.utf8.rawValue
+            encoding = String.Encoding.utf8.rawValue
+            offset = 0
         }
 
+        enc?.pointee = encoding
+
         // Since the encoding being passed includes the byte order the BOM wont be checked or skipped, so pass offset to
         // manually skip the BOM header.
-        guard let enc = enc, let cf = CFStringCreateWithBytes(kCFAllocatorDefault, bytePtr + offset, readResult.length - offset,
-                                                              CFStringConvertNSStringEncodingToEncoding(enc.pointee), true) else {
+        guard let cf = CFStringCreateWithBytes(kCFAllocatorDefault, bytePtr + offset, readResult.length - offset,
+                                               CFStringConvertNSStringEncodingToEncoding(encoding), true) else {
             throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileReadInapplicableStringEncoding.rawValue, userInfo: [
                 "NSDebugDescription" : "Unable to create a string using the specified encoding."
                 ])
@@ -1286,11 +1290,11 @@
             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 {
-        NSUnimplemented()    
+        try self.init(contentsOf: URL(fileURLWithPath: path), usedEncoding: enc)
     }
 }
 
diff --git a/TestFoundation/TestNSString.swift b/TestFoundation/TestNSString.swift
index 70e9398..e75bd4f 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_FromContentOfFileUsedEncodingIgnored", test_FromContentOfFileUsedEncodingIgnored),
+            ("test_FromContentOfFileUsedEncodingUTF8", test_FromContentOfFileUsedEncodingUTF8),
             ("test_FromContentsOfURLUsedEncodingUTF16BE", test_FromContentsOfURLUsedEncodingUTF16BE),
             ("test_FromContentsOfURLUsedEncodingUTF16LE", test_FromContentsOfURLUsedEncodingUTF16LE),
             ("test_FromContentsOfURLUsedEncodingUTF32BE", test_FromContentsOfURLUsedEncodingUTF32BE),
@@ -303,6 +305,32 @@
         }
     }
 
+    func test_FromContentOfFileUsedEncodingIgnored() {
+        let testFilePath = testBundle().path(forResource: "NSStringTestData", ofType: "txt")
+        XCTAssertNotNil(testFilePath)
+        
+        do {
+            let str = try NSString(contentsOfFile: testFilePath!, usedEncoding: nil)
+            XCTAssertEqual(str, "swift-corelibs-foundation")
+        } catch {
+            XCTFail("Unable to init NSString from contentsOfFile:encoding:")
+        }
+    }
+    
+    func test_FromContentOfFileUsedEncodingUTF8() {
+        let testFilePath = testBundle().path(forResource: "NSStringTestData", ofType: "txt")
+        XCTAssertNotNil(testFilePath)
+        
+        do {
+            var encoding: UInt = 0
+            let str = try NSString(contentsOfFile: testFilePath!, usedEncoding: &encoding)
+            XCTAssertEqual(str, "swift-corelibs-foundation")
+            XCTAssertEqual(encoding, String.Encoding.utf8.rawValue, "Wrong encoding detected from UTF8 file")
+        } catch {
+            XCTFail("Unable to init NSString from contentsOfFile:encoding:")
+        }
+    }
+
     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")