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")