Skip to content

Commit 5f520d9

Browse files
committed
Merge remote-tracking branch 'origin/master' into swift-4.0-branch
2 parents f71275e + 3b1ebdb commit 5f520d9

25 files changed

+693
-110
lines changed

CoreFoundation/Base.subproj/CFRuntime.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,15 +1699,6 @@ const char *_NSPrintForDebugger(void *cf) {
16991699
}
17001700
}
17011701

1702-
// For CF functions with 'Get' semantics, the compiler currently assumes that the result is autoreleased and must be retained. It does so on all platforms by emitting a call to objc_retainAutoreleasedReturnValue. On Darwin, this is implemented by the ObjC runtime. On Linux, there is no runtime, and therefore we have to stub it out here ourselves. The compiler will eventually call swift_release to balance the retain below. This is a workaround until the compiler no longer emits this callout on Linux.
1703-
void * objc_retainAutoreleasedReturnValue(void *obj) {
1704-
if (obj) {
1705-
swift_retain(obj);
1706-
return obj;
1707-
}
1708-
else return NULL;
1709-
}
1710-
17111702
CFHashCode __CFHashDouble(double d) {
17121703
return _CFHashDouble(d);
17131704
}

Foundation/Data.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1514,7 +1514,6 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
15141514
@inline(__always)
15151515
public func subdata(in range: Range<Index>) -> Data {
15161516
_validateRange(range)
1517-
let length = count
15181517
if count == 0 {
15191518
return Data()
15201519
}

Foundation/ExtraStringAPIs.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ extension String.UTF16View.Index : Strideable {
1717
/// Construct from an integer offset.
1818
public init(_ offset: Int) {
1919
_precondition(offset >= 0, "Negative UTF16 index offset not allowed")
20-
self.init(_offset: offset)
20+
self.init(encodedOffset: offset)
2121
}
2222

2323
public func distance(to other: String.UTF16View.Index) -> Int {
24-
return _offset.distance(to: other._offset)
24+
return encodedOffset.distance(to: other.encodedOffset)
2525
}
2626

2727
public func advanced(by n: Int) -> String.UTF16View.Index {
28-
return String.UTF16View.Index(_offset.advanced(by: n))
28+
return String.UTF16View.Index(encodedOffset.advanced(by: n))
2929
}
3030
}
3131

Foundation/FileManager.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ open class FileManager : NSObject {
624624
}
625625
}
626626

627-
open func createFile(atPath path: String, contents data: Data?, attributes attr: [String : Any]? = [:]) -> Bool {
627+
open func createFile(atPath path: String, contents data: Data?, attributes attr: [FileAttributeKey : Any]? = nil) -> Bool {
628628
do {
629629
try (data ?? Data()).write(to: URL(fileURLWithPath: path), options: .atomic)
630630
return true

Foundation/NSCharacterSet.swift

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,18 @@ open class NSCharacterSet : NSObject, NSCopying, NSMutableCopying, NSCoding {
5050
}
5151

5252
open override func isEqual(_ value: Any?) -> Bool {
53+
guard let runtimeClass = _CFRuntimeGetClassWithTypeID(CFCharacterSetGetTypeID()) else {
54+
fatalError("Could not obtain CFRuntimeClass of CFCharacterSet")
55+
}
56+
57+
guard let equalFunction = runtimeClass.pointee.equal else {
58+
fatalError("Could not obtain equal function from CFRuntimeClass of CFCharacterSet")
59+
}
60+
5361
switch value {
54-
case let other as CharacterSet:
55-
return CFEqual(_cfObject, other._cfObject)
56-
case let other as NSCharacterSet:
57-
return CFEqual(_cfObject, other._cfObject)
58-
default:
59-
return false
62+
case let other as CharacterSet: return equalFunction(self._cfObject, other._cfObject) == true
63+
case let other as NSCharacterSet: return equalFunction(self._cfObject, other._cfObject) == true
64+
default: return false
6065
}
6166
}
6267

Foundation/NSJSONSerialization.swift

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ extension JSONSerialization {
3131
public init(rawValue: UInt) { self.rawValue = rawValue }
3232

3333
public static let prettyPrinted = WritingOptions(rawValue: 1 << 0)
34+
public static let sortedKeys = WritingOptions(rawValue: 1 << 1)
3435
}
3536
}
3637

@@ -116,6 +117,7 @@ open class JSONSerialization : NSObject {
116117

117118
var writer = JSONWriter(
118119
pretty: opt.contains(.prettyPrinted),
120+
sortedKeys: opt.contains(.sortedKeys),
119121
writer: { (str: String?) in
120122
if let str = str {
121123
jsonStr.append(str)
@@ -289,6 +291,7 @@ private struct JSONWriter {
289291
private let maxIntLength = String(describing: Int.max).characters.count
290292
var indent = 0
291293
let pretty: Bool
294+
let sortedKeys: Bool
292295
let writer: (String?) -> Void
293296

294297
private lazy var _numberformatter: CFNumberFormatter = {
@@ -299,8 +302,9 @@ private struct JSONWriter {
299302
return formatter
300303
}()
301304

302-
init(pretty: Bool = false, writer: @escaping (String?) -> Void) {
305+
init(pretty: Bool = false, sortedKeys: Bool = false, writer: @escaping (String?) -> Void) {
303306
self.pretty = pretty
307+
self.sortedKeys = sortedKeys
304308
self.writer = writer
305309
}
306310

@@ -499,10 +503,10 @@ private struct JSONWriter {
499503
writer("\n")
500504
incAndWriteIndent()
501505
}
502-
506+
503507
var first = true
504-
505-
for (key, value) in dict {
508+
509+
func serializeDictionaryElement(key: AnyHashable, value: Any) throws {
506510
if first {
507511
first = false
508512
} else if pretty {
@@ -511,15 +515,37 @@ private struct JSONWriter {
511515
} else {
512516
writer(",")
513517
}
514-
515-
if key is String {
516-
try serializeString(key as! String)
518+
519+
if let key = key as? String {
520+
try serializeString(key)
517521
} else {
518522
throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "NSDictionary key must be NSString"])
519523
}
520524
pretty ? writer(": ") : writer(":")
521525
try serializeJSON(value)
522526
}
527+
528+
if sortedKeys {
529+
let elems = try dict.sorted(by: { a, b in
530+
guard let a = a.key as? String,
531+
let b = b.key as? String else {
532+
throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "NSDictionary key must be NSString"])
533+
}
534+
let options: NSString.CompareOptions = [.numeric, .caseInsensitive, .forcedOrdering]
535+
let range: Range<String.Index> = a.startIndex..<a.endIndex
536+
let locale = NSLocale.system
537+
538+
return a.compare(b, options: options, range: range, locale: locale) == .orderedAscending
539+
})
540+
for elem in elems {
541+
try serializeDictionaryElement(key: elem.key, value: elem.value)
542+
}
543+
} else {
544+
for (key, value) in dict {
545+
try serializeDictionaryElement(key: key, value: value)
546+
}
547+
}
548+
523549
if pretty {
524550
writer("\n")
525551
decAndWriteIndent()

Foundation/NSLocale.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ extension NSLocale {
8484
return CFLocaleCopyCurrent()._swiftObject
8585
}
8686

87-
open class func systemLocale() -> Locale {
87+
open class var system: Locale {
8888
return CFLocaleGetSystem()._swiftObject
8989
}
9090
}

Foundation/NSNotification.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ private class NSNotificationReceiver : NSObject {
9090
fileprivate var name: Notification.Name?
9191
fileprivate var block: ((Notification) -> Void)?
9292
fileprivate var sender: AnyObject?
93+
fileprivate var queue: OperationQueue?
9394
}
9495

9596
extension Sequence where Iterator.Element : NSNotificationReceiver {
@@ -159,7 +160,12 @@ open class NotificationCenter: NSObject {
159160
continue
160161
}
161162

162-
block(notification)
163+
if let queue = observer.queue, queue != OperationQueue.current {
164+
queue.addOperation { block(notification) }
165+
queue.waitUntilAllOperationsAreFinished()
166+
} else {
167+
block(notification)
168+
}
163169
}
164170
}
165171

@@ -183,17 +189,14 @@ open class NotificationCenter: NSObject {
183189
}
184190

185191
open func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, usingBlock block: @escaping (Notification) -> Void) -> NSObjectProtocol {
186-
if queue != nil {
187-
NSUnimplemented()
188-
}
189-
190192
let object = NSObject()
191193

192194
let newObserver = NSNotificationReceiver()
193195
newObserver.object = object
194196
newObserver.name = name
195197
newObserver.block = block
196198
newObserver.sender = _SwiftValue.store(obj)
199+
newObserver.queue = queue
197200

198201
_observersLock.synchronized({
199202
_observers.append(newObserver)

Foundation/NSPersonNameComponents.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,28 @@ open class NSPersonNameComponents : NSObject, NSCopying, NSSecureCoding {
6464
}
6565
return copy
6666
}
67+
68+
open override func isEqual(_ object: Any?) -> Bool {
69+
guard let object = object else { return false }
70+
71+
switch object {
72+
case let other as NSPersonNameComponents: return self.isEqual(other)
73+
case let other as PersonNameComponents: return self.isEqual(other._bridgeToObjectiveC())
74+
default: return false
75+
}
76+
}
77+
78+
private func isEqual(_ other: NSPersonNameComponents) -> Bool {
79+
if self === other { return true }
80+
81+
return (self.namePrefix == other.namePrefix
82+
&& self.givenName == other.givenName
83+
&& self.middleName == other.middleName
84+
&& self.familyName == other.familyName
85+
&& self.nameSuffix == other.nameSuffix
86+
&& self.nickname == other.nickname
87+
&& self.phoneticRepresentation == other.phoneticRepresentation)
88+
}
6789

6890
/* The below examples all assume the full name Dr. Johnathan Maple Appleseed Esq., nickname "Johnny" */
6991

Foundation/NSRange.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,8 @@ extension NSRange {
261261
where R.Bound == S.Index, S.Index == String.Index {
262262
let r = region.relative(to: target)
263263
self = NSRange(
264-
location: r.lowerBound._utf16Index - target.startIndex._utf16Index,
265-
length: r.upperBound._utf16Index - r.lowerBound._utf16Index
264+
location: r.lowerBound.encodedOffset - target.startIndex.encodedOffset,
265+
length: r.upperBound.encodedOffset - r.lowerBound.encodedOffset
266266
)
267267
}
268268

Foundation/NSStringAPI.swift

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ func _toNSArray<T, U : AnyObject>(_ a: [T], f: (T) -> U) -> NSArray {
3030

3131
func _toNSRange(_ r: Range<String.Index>) -> NSRange {
3232
return NSRange(
33-
location: r.lowerBound._utf16Index,
34-
length: r.upperBound._utf16Index - r.lowerBound._utf16Index)
33+
location: r.lowerBound.encodedOffset,
34+
length: r.upperBound.encodedOffset - r.lowerBound.encodedOffset)
3535
}
3636

3737
extension String {
@@ -47,10 +47,7 @@ extension String {
4747
/// Return an `Index` corresponding to the given offset in our UTF-16
4848
/// representation.
4949
func _index(_ utf16Index: Int) -> Index {
50-
return Index(
51-
_base: String.UnicodeScalarView.Index(_position: utf16Index),
52-
in: characters
53-
)
50+
return Index(encodedOffset: utf16Index)
5451
}
5552

5653
/// Return a `Range<Index>` corresponding to the given `NSRange` of
@@ -1076,7 +1073,7 @@ extension String {
10761073
public
10771074
func rangeOfComposedCharacterSequence(at anIndex: Index) -> Range<Index> {
10781075
return _range(
1079-
_ns.rangeOfComposedCharacterSequence(at: anIndex._utf16Index))
1076+
_ns.rangeOfComposedCharacterSequence(at: anIndex.encodedOffset))
10801077
}
10811078

10821079
// - (NSRange)rangeOfComposedCharacterSequencesForRange:(NSRange)range
@@ -1392,15 +1389,15 @@ extension String {
13921389
/// Returns a new string containing the characters of the
13931390
/// `String` from the one at a given index to the end.
13941391
public func substring(from index: Index) -> String {
1395-
return _ns.substring(from: index._utf16Index)
1392+
return _ns.substring(from: index.encodedOffset)
13961393
}
13971394

13981395
// - (NSString *)substringToIndex:(NSUInteger)anIndex
13991396

14001397
/// Returns a new string containing the characters of the
14011398
/// `String` up to, but not including, the one at a given index.
14021399
public func substring(to index: Index) -> String {
1403-
return _ns.substring(to: index._utf16Index)
1400+
return _ns.substring(to: index.encodedOffset)
14041401
}
14051402

14061403
// - (NSString *)substringWithRange:(NSRange)aRange

Foundation/NSURLSession/http/EasyHandle.swift

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ internal final class _EasyHandle {
5757
fileprivate var pauseState: _PauseState = []
5858
internal var fileLength: Int64 = 0
5959
internal var timeoutTimer: _TimeoutSource!
60+
#if os(Android)
61+
static fileprivate var _CAInfoFile: UnsafeMutablePointer<Int8>?
62+
#endif
6063

6164
init(delegate: _EasyHandleDelegate) {
6265
self.delegate = delegate
@@ -168,6 +171,20 @@ extension _EasyHandle {
168171
let protocols = (CFURLSessionProtocolHTTP | CFURLSessionProtocolHTTPS)
169172
try! CFURLSession_easy_setopt_long(rawHandle, CFURLSessionOptionPROTOCOLS, protocols).asError()
170173
try! CFURLSession_easy_setopt_long(rawHandle, CFURLSessionOptionREDIR_PROTOCOLS, protocols).asError()
174+
#if os(Android)
175+
// See https://curl.haxx.se/docs/sslcerts.html
176+
// For SSL to work you need "cacert.pem" to be accessable
177+
// at the path pointed to by the URLSessionCAInfo env var.
178+
// Downloadable here: https://curl.haxx.se/ca/cacert.pem
179+
if let caInfo = _EasyHandle._CAInfoFile {
180+
if String(cString: caInfo) == "UNSAFE_SSL_NOVERIFY" {
181+
try! CFURLSession_easy_setopt_int(rawHandle, CFURLSessionOptionSSL_VERIFYPEER, 0).asError()
182+
}
183+
else {
184+
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionCAINFO, caInfo).asError()
185+
}
186+
}
187+
#endif
171188
//TODO: Added in libcurl 7.45.0
172189
//TODO: Set default protocol for schemeless URLs
173190
//CURLOPT_DEFAULT_PROTOCOL available only in libcurl 7.45.0
@@ -268,7 +285,7 @@ fileprivate func printLibcurlDebug(handle: CFURLSessionEasyHandle, type: CInt, d
268285

269286
fileprivate func printLibcurlDebug(type: CFURLSessionInfo, data: String, task: URLSessionTask) {
270287
// libcurl sends is data with trailing CRLF which inserts lots of newlines into our output.
271-
print("[\(task.taskIdentifier)] \(type.debugHeader) \(data.mapControlToPictures)")
288+
NSLog("[\(task.taskIdentifier)] \(type.debugHeader) \(data.mapControlToPictures)")
272289
}
273290

274291
fileprivate extension String {
@@ -615,6 +632,19 @@ extension _EasyHandle._CurlStringList {
615632
}
616633
}
617634

635+
#if os(Android)
636+
extension URLSession {
637+
638+
public static func setCAInfoFile(_ _CAInfoFile: String) {
639+
free(_EasyHandle._CAInfoFile)
640+
_CAInfoFile.withCString {
641+
_EasyHandle._CAInfoFile = strdup($0)
642+
}
643+
}
644+
645+
}
646+
#endif
647+
618648
extension CFURLSessionEasyCode : Equatable {
619649
public static func ==(lhs: CFURLSessionEasyCode, rhs: CFURLSessionEasyCode) -> Bool {
620650
return lhs.value == rhs.value

Foundation/NSURLSession/http/HTTPURLProtocol.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,14 @@ extension _HTTPURLProtocol {
439439
extension _HTTPURLProtocol: _EasyHandleDelegate {
440440

441441
func didReceive(data: Data) -> _EasyHandle._Action {
442-
guard case .transferInProgress(let ts) = internalState else { fatalError("Received body data, but no transfer in progress.") }
443-
guard ts.isHeaderComplete else { fatalError("Received body data, but the header is not complete, yet.") }
442+
guard case .transferInProgress(var ts) = internalState else { fatalError("Received body data, but no transfer in progress.") }
443+
if !ts.isHeaderComplete {
444+
ts.response = HTTPURLResponse(url: ts.url, statusCode: 200, httpVersion: "HTTP/0.9", headerFields: [:])
445+
/* we received body data before CURL tells us that the headers are complete, that happens for HTTP/0.9 simple responses, see
446+
- https://www.w3.org/Protocols/HTTP/1.0/spec.html#Message-Types
447+
- https://github.com/curl/curl/issues/467
448+
*/
449+
}
444450
notifyDelegate(aboutReceivedData: data)
445451
internalState = .transferInProgress(ts.byAppending(bodyData: data))
446452
return .proceed

0 commit comments

Comments
 (0)