Skip to content

Commit 6ec4054

Browse files
mohitathwaniparkera
authored andcommitted
Added basic implementation for NSString contentsOfURL:usedEncoding: (#893)
* Added basic implementation for NSString contentsOfURL:usedEncoding: In NSString, for contentsOfURL:usedEncoding: checking the BOM of the received data and determinig whether encoding to be used should be UTF 16 BE Fixed guard statement to handle nil case Fixed indentation in test case Updated build.py file to include test input file Fixed Indentation in build.py * Ensuring file size is atleasy 2 bytes and added test case for UTF 16 LE
1 parent 9d603e2 commit 6ec4054

File tree

5 files changed

+63
-1
lines changed

5 files changed

+63
-1
lines changed

Foundation/NSString.swift

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1298,7 +1298,33 @@ extension NSString {
12981298
}
12991299

13001300
public convenience init(contentsOf url: URL, usedEncoding enc: UnsafeMutablePointer<UInt>?) throws {
1301-
NSUnimplemented()
1301+
let readResult = try NSData(contentsOf: url, options:[])
1302+
1303+
let bytePtr = readResult.bytes.bindMemory(to: UInt8.self, capacity:readResult.length)
1304+
if readResult.length >= 2 && bytePtr[0] == 254 && bytePtr[1] == 255 {
1305+
enc?.pointee = String.Encoding.utf16BigEndian.rawValue
1306+
}
1307+
else if readResult.length >= 2 && bytePtr[0] == 255 && bytePtr[1] == 254 {
1308+
enc?.pointee = String.Encoding.utf16LittleEndian.rawValue
1309+
}
1310+
else {
1311+
//Need to work on more conditions. This should be the default
1312+
enc?.pointee = String.Encoding.utf8.rawValue
1313+
}
1314+
1315+
guard let enc = enc, let cf = CFStringCreateWithBytes(kCFAllocatorDefault, bytePtr, readResult.length, CFStringConvertNSStringEncodingToEncoding(enc.pointee), true) else {
1316+
throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileReadInapplicableStringEncoding.rawValue, userInfo: [
1317+
"NSDebugDescription" : "Unable to create a string using the specified encoding."
1318+
])
1319+
}
1320+
var str: String?
1321+
if String._conditionallyBridgeFromObjectiveC(cf._nsObject, result: &str) {
1322+
self.init(str!)
1323+
} else {
1324+
throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileReadInapplicableStringEncoding.rawValue, userInfo: [
1325+
"NSDebugDescription" : "Unable to bridge CFString to String."
1326+
])
1327+
}
13021328
}
13031329

13041330
public convenience init(contentsOfFile path: String, usedEncoding enc: UnsafeMutablePointer<UInt>?) throws {
108 Bytes
Binary file not shown.
108 Bytes
Binary file not shown.

TestFoundation/TestNSString.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ class TestNSString : XCTestCase {
6666
("test_rangeOfCharacterFromSet", test_rangeOfCharacterFromSet ),
6767
("test_CFStringCreateMutableCopy", test_CFStringCreateMutableCopy),
6868
("test_FromContentsOfURL",test_FromContentsOfURL),
69+
("test_FromContentsOfURLUsedEncodingUTF16BE", test_FromContentsOfURLUsedEncodingUTF16BE),
70+
("test_FromContentsOfURLUsedEncodingUTF16LE", test_FromContentsOfURLUsedEncodingUTF16LE),
6971
("test_FromContentOfFile",test_FromContentOfFile),
7072
("test_swiftStringUTF16", test_swiftStringUTF16),
7173
// This test takes forever on build servers; it has been seen up to 1852.084 seconds
@@ -300,6 +302,38 @@ class TestNSString : XCTestCase {
300302
}
301303
}
302304

305+
func test_FromContentsOfURLUsedEncodingUTF16BE() {
306+
guard let testFileURL = testBundle().url(forResource: "NSString-UTF16-BE-data", withExtension: "txt") else {
307+
XCTFail("URL for NSString-UTF16-BE-data.txt is nil")
308+
return
309+
}
310+
311+
do {
312+
var encoding: UInt = 0
313+
let string = try NSString(contentsOf: testFileURL, usedEncoding: &encoding)
314+
XCTAssertEqual(string, "NSString fromURL usedEncoding test with UTF16 BE file", "Wrong result when reading UTF16BE file")
315+
XCTAssertEqual(encoding, String.Encoding.utf16BigEndian.rawValue, "Wrong encoding detected from UTF16BE file")
316+
} catch {
317+
XCTFail("Unable to init NSString from contentsOf:usedEncoding:")
318+
}
319+
}
320+
321+
func test_FromContentsOfURLUsedEncodingUTF16LE() {
322+
guard let testFileURL = testBundle().url(forResource: "NSString-UTF16-LE-data", withExtension: "txt") else {
323+
XCTFail("URL for NSString-UTF16-LE-data.txt is nil")
324+
return
325+
}
326+
327+
do {
328+
var encoding: UInt = 0
329+
let string = try NSString(contentsOf: testFileURL, usedEncoding: &encoding)
330+
XCTAssertEqual(string, "NSString fromURL usedEncoding test with UTF16 LE file", "Wrong result when reading UTF16LE file")
331+
XCTAssertEqual(encoding, String.Encoding.utf16LittleEndian.rawValue, "Wrong encoding detected from UTF16LE file")
332+
} catch {
333+
XCTFail("Unable to init NSString from contentOf:usedEncoding:")
334+
}
335+
}
336+
303337
func test_FromContentOfFile() {
304338
let testFilePath = testBundle().path(forResource: "NSStringTestData", ofType: "txt")
305339
XCTAssertNotNil(testFilePath)

build.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,8 @@
460460
'TestFoundation/Resources/NSURLTestData.plist',
461461
'TestFoundation/Resources/Test.plist',
462462
'TestFoundation/Resources/NSStringTestData.txt',
463+
'TestFoundation/Resources/NSString-UTF16-BE-data.txt',
464+
'TestFoundation/Resources/NSString-UTF16-LE-data.txt',
463465
'TestFoundation/Resources/NSXMLDocumentTestData.xml',
464466
'TestFoundation/Resources/PropertyList-1.0.dtd',
465467
'TestFoundation/Resources/NSXMLDTDTestData.xml',

0 commit comments

Comments
 (0)