Merge remote-tracking branch 'origin/master' into swift-4.0-branch
diff --git a/Foundation/NSArray.swift b/Foundation/NSArray.swift
index 6f52df9..9c37357 100644
--- a/Foundation/NSArray.swift
+++ b/Foundation/NSArray.swift
@@ -446,9 +446,6 @@
self.enumerateObjects(at: IndexSet(integersIn: 0..<count), options: opts, using: block)
}
open func enumerateObjects(at s: IndexSet, options opts: NSEnumerationOptions = [], using block: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Swift.Void) {
- guard !opts.contains(.concurrent) else {
- NSUnimplemented()
- }
s._bridgeToObjectiveC().enumerate(options: opts) { (idx, stop) in
block(self.object(at: idx), idx, stop)
}
diff --git a/Foundation/NSConcreteValue.swift b/Foundation/NSConcreteValue.swift
index 6b01414..eccb14e 100644
--- a/Foundation/NSConcreteValue.swift
+++ b/Foundation/NSConcreteValue.swift
@@ -39,7 +39,7 @@
scanner.scanLocation = 1
- guard scanner.scanInteger(&count) && count > 0 else {
+ guard scanner.scanInt(&count) && count > 0 else {
print("NSConcreteValue.TypeInfo: array count is missing or zero")
return nil
}
diff --git a/Foundation/NSDictionary.swift b/Foundation/NSDictionary.swift
index 16ec60e..f331104 100644
--- a/Foundation/NSDictionary.swift
+++ b/Foundation/NSDictionary.swift
@@ -9,7 +9,7 @@
import CoreFoundation
-
+import Dispatch
open class NSDictionary : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSCoding {
private let _cfinfo = _CFInfo(typeID: CFDictionaryGetTypeID())
@@ -454,19 +454,37 @@
enumerateKeysAndObjects(options: [], using: block)
}
- open func enumerateKeysAndObjects(options opts: NSEnumerationOptions = [], using block: (Any, Any, UnsafeMutablePointer<ObjCBool>) -> Swift.Void) {
+ open func enumerateKeysAndObjects(options opts: NSEnumerationOptions = [], using block: (Any, Any, UnsafeMutablePointer<ObjCBool>) -> Void) {
let count = self.count
var keys = [Any]()
var objects = [Any]()
+ var sharedStop = ObjCBool(false)
+ let lock = NSLock()
+
getObjects(&objects, andKeys: &keys, count: count)
- var stop = ObjCBool(false)
- for idx in 0..<count {
- withUnsafeMutablePointer(to: &stop, { stop in
- block(keys[idx], objects[idx], stop)
- })
-
- if stop {
- break
+ let iteration: (Int) -> Void = withoutActuallyEscaping(block) { (closure: @escaping (Any, Any, UnsafeMutablePointer<ObjCBool>) -> Void) -> (Int) -> Void in
+ return { (idx) in
+ lock.lock()
+ var stop = sharedStop
+ lock.unlock()
+ if stop { return }
+
+ closure(keys[idx], objects[idx], &stop)
+
+ if stop {
+ lock.lock()
+ sharedStop = stop
+ lock.unlock()
+ return
+ }
+ }
+ }
+
+ if opts.contains(.concurrent) {
+ DispatchQueue.concurrentPerform(iterations: count, execute: iteration)
+ } else {
+ for idx in 0..<count {
+ iteration(idx)
}
}
}
diff --git a/Foundation/NSGeometry.swift b/Foundation/NSGeometry.swift
index 9ac69d2..454014a 100644
--- a/Foundation/NSGeometry.swift
+++ b/Foundation/NSGeometry.swift
@@ -71,7 +71,7 @@
return self.x.hashValue &+ self.y.hashValue
}
- var description: String? {
+ var description: String {
return NSStringFromPoint(self)
}
}
@@ -134,7 +134,7 @@
return self.width.hashValue &+ self.height.hashValue
}
- var description: String? {
+ var description: String {
return NSStringFromSize(self)
}
}
@@ -216,7 +216,7 @@
return self.origin.hash &+ self.size.hash
}
- var description: String? {
+ var description: String {
return NSStringFromRect(self)
}
}
@@ -316,8 +316,8 @@
return self.top.hashValue &+ self.left.hashValue &+ self.bottom.hashValue &+ self.right.hashValue
}
- var description: String? {
- return nil
+ var description: String {
+ return ""
}
}
diff --git a/Foundation/NSIndexSet.swift b/Foundation/NSIndexSet.swift
index 6c5490d..66f2bf5 100644
--- a/Foundation/NSIndexSet.swift
+++ b/Foundation/NSIndexSet.swift
@@ -7,6 +7,7 @@
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
+import Dispatch
/* Class for managing set of indexes. The set of valid indexes are 0 .. NSNotFound - 1; trying to use indexes outside this range is an error. NSIndexSet uses NSNotFound as a return value in cases where the queried index doesn't exist in the set; for instance, when you ask firstIndex and there are no indexes; or when you ask for indexGreaterThanIndex: on the last index, and so on.
@@ -388,36 +389,60 @@
let reverse = opts.contains(.reverse)
let passRanges = paramType == NSRange.self
let findIndex = returnType == Bool.self
- var stop = false
+ var sharedStop = false
+ let lock = NSLock()
let ranges = _ranges[startRangeIndex...endRangeIndex]
- let rangeSequence = (reverse ? AnySequence(ranges.reversed()) : AnySequence(ranges))
- outer: for curRange in rangeSequence {
- let intersection = NSIntersectionRange(curRange, range)
- if passRanges {
- if intersection.length > 0 {
- let _ = block(intersection as! P, &stop)
- }
- if stop {
- break outer
- }
- } else if intersection.length > 0 {
- let maxIndex = NSMaxRange(intersection) - 1
- let indexes = reverse ? stride(from: maxIndex, through: intersection.location, by: -1) : stride(from: intersection.location, through: maxIndex, by: 1)
- for idx in indexes {
- if findIndex {
- let found : Bool = block(idx as! P, &stop) as! Bool
- if found {
- result = idx
- stop = true
- }
- } else {
- let _ = block(idx as! P, &stop)
+ let rangeSequence = (reverse ? AnyCollection(ranges.reversed()) : AnyCollection(ranges))
+ let iteration = withoutActuallyEscaping(block) { (closure: @escaping (P, UnsafeMutablePointer<ObjCBool>) -> R) -> (Int) -> Void in
+ return { (rangeIdx) in
+ lock.lock()
+ var stop = sharedStop
+ lock.unlock()
+ if stop { return }
+
+ let idx = rangeSequence.index(rangeSequence.startIndex, offsetBy: IntMax(rangeIdx))
+ let curRange = rangeSequence[idx]
+ let intersection = NSIntersectionRange(curRange, range)
+ if passRanges {
+ if intersection.length > 0 {
+ let _ = closure(intersection as! P, &stop)
}
if stop {
- break outer
+ lock.lock()
+ sharedStop = stop
+ lock.unlock()
+ return
+ }
+ } else if intersection.length > 0 {
+ let maxIndex = NSMaxRange(intersection) - 1
+ let indexes = reverse ? stride(from: maxIndex, through: intersection.location, by: -1) : stride(from: intersection.location, through: maxIndex, by: 1)
+ for idx in indexes {
+ if findIndex {
+ let found : Bool = closure(idx as! P, &stop) as! Bool
+ if found {
+ result = idx
+ stop = true
+ }
+ } else {
+ let _ = closure(idx as! P, &stop)
+ }
+ if stop {
+ lock.lock()
+ sharedStop = stop
+ lock.unlock()
+ return
+ }
}
}
- } // else, continue
+ }
+ }
+
+ if opts.contains(.concurrent) {
+ DispatchQueue.concurrentPerform(iterations: Int(rangeSequence.count), execute: iteration)
+ } else {
+ for idx in 0..<Int(rangeSequence.count) {
+ iteration(idx)
+ }
}
return result
diff --git a/Foundation/NSKeyedArchiver.swift b/Foundation/NSKeyedArchiver.swift
index 40fc5a5..3790990 100644
--- a/Foundation/NSKeyedArchiver.swift
+++ b/Foundation/NSKeyedArchiver.swift
@@ -755,7 +755,7 @@
scanner.scanLocation = 1 // advance past ObJCType
var count : Int = 0
- guard scanner.scanInteger(&count) && count > 0 else {
+ guard scanner.scanInt(&count) && count > 0 else {
fatalError("NSKeyedArchiver.encodeValueOfObjCType: array count is missing or zero")
}
diff --git a/Foundation/NSKeyedUnarchiver.swift b/Foundation/NSKeyedUnarchiver.swift
index c8feeb5..47fc2f8 100644
--- a/Foundation/NSKeyedUnarchiver.swift
+++ b/Foundation/NSKeyedUnarchiver.swift
@@ -813,7 +813,7 @@
scanner.scanLocation = 1
var count : Int = 0
- guard scanner.scanInteger(&count) && count > 0 else {
+ guard scanner.scanInt(&count) && count > 0 else {
fatalError("NSKeyedUnarchiver.decodeValueOfObjCType: array count is missing or zero")
}
diff --git a/Foundation/NSRange.swift b/Foundation/NSRange.swift
index 5889644..699ebb1 100644
--- a/Foundation/NSRange.swift
+++ b/Foundation/NSRange.swift
@@ -7,11 +7,15 @@
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
+#if DEPLOYMENT_RUNTIME_SWIFT
+
import CoreFoundation
public struct _NSRange {
public var location: Int
public var length: Int
+
+
public init() {
location = 0
length = 0
@@ -21,100 +25,10 @@
self.location = location
self.length = length
}
+}
- internal init(_ range: CFRange) {
- location = range.location == kCFNotFound ? NSNotFound : range.location
- length = range.length
- }
-}
-
-extension CFRange {
- internal init(_ range: NSRange) {
- location = range.location == NSNotFound ? kCFNotFound : range.location
- length = range.length
- }
-}
-
public typealias NSRange = _NSRange
-
-extension NSRange {
- public init(_ x: Range<Int>) {
- location = x.lowerBound
- length = x.count
- }
- public func toRange() -> Range<Int>? {
- if location == NSNotFound { return nil }
- return location..<(location+length)
- }
-
- internal func toCountableRange() -> CountableRange<Int>? {
- if location == NSNotFound { return nil }
- return location..<(location+length)
- }
-}
-
-extension NSRange: NSSpecialValueCoding {
- init(bytes: UnsafeRawPointer) {
- self.location = bytes.load(as: Int.self)
- self.length = bytes.load(fromByteOffset: MemoryLayout<Int>.stride, as: Int.self)
- }
-
- init?(coder aDecoder: NSCoder) {
- guard aDecoder.allowsKeyedCoding else {
- preconditionFailure("Unkeyed coding is unsupported.")
- }
- if let location = aDecoder.decodeObject(of: NSNumber.self, forKey: "NS.rangeval.location") {
- self.location = location.intValue
- } else {
- self.location = 0
- }
- if let length = aDecoder.decodeObject(of: NSNumber.self, forKey: "NS.rangeval.length") {
- self.length = length.intValue
- } else {
- self.length = 0
- }
- }
-
- func encodeWithCoder(_ aCoder: NSCoder) {
- guard aCoder.allowsKeyedCoding else {
- preconditionFailure("Unkeyed coding is unsupported.")
- }
- aCoder.encode(NSNumber(value: self.location), forKey: "NS.rangeval.location")
- aCoder.encode(NSNumber(value: self.length), forKey: "NS.rangeval.length")
- }
-
- static func objCType() -> String {
-#if arch(i386) || arch(arm)
- return "{_NSRange=II}"
-#elseif arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
- return "{_NSRange=QQ}"
-#else
- NSUnimplemented()
-#endif
- }
-
- func getValue(_ value: UnsafeMutableRawPointer) {
- value.initializeMemory(as: NSRange.self, to: self)
- }
-
- func isEqual(_ aValue: Any) -> Bool {
- if let other = aValue as? NSRange {
- return other.location == self.location && other.length == self.length
- } else {
- return false
- }
- }
-
- var hash: Int {
- return self.location &+ self.length
- }
-
- var description: String? {
- return NSStringFromRange(self)
- }
-}
-
public typealias NSRangePointer = UnsafeMutablePointer<NSRange>
public func NSMakeRange(_ loc: Int, _ len: Int) -> NSRange {
@@ -185,7 +99,7 @@
// fail early if there are no decimal digits
return emptyRange
}
- guard let location = scanner.scanInteger() else {
+ guard let location = scanner.scanInt() else {
return emptyRange
}
let partialRange = NSMakeRange(location, 0)
@@ -198,12 +112,308 @@
// return early if there are no integer characters after the first int in the string
return partialRange
}
- guard let length = scanner.scanInteger() else {
+ guard let length = scanner.scanInt() else {
return partialRange
}
return NSMakeRange(location, length)
}
+
+#else
+@_exported import Foundation // Clang module
+#endif
+extension NSRange : Hashable {
+ public var hashValue: Int {
+ #if arch(i386) || arch(arm)
+ return Int(bitPattern: (UInt(bitPattern: location) | (UInt(bitPattern: length) << 16)))
+ #elseif arch(x86_64) || arch(arm64)
+ return Int(bitPattern: (UInt(bitPattern: location) | (UInt(bitPattern: length) << 32)))
+ #endif
+ }
+
+ public static func==(_ lhs: NSRange, _ rhs: NSRange) -> Bool {
+ return lhs.location == rhs.location && lhs.length == rhs.length
+ }
+}
+
+extension NSRange : CustomStringConvertible, CustomDebugStringConvertible {
+ public var description: String { return "{\(location), \(length)}" }
+ public var debugDescription: String {
+ guard location != NSNotFound else {
+ return "{NSNotFound, \(length)}"
+ }
+ return "{\(location), \(length)}"
+ }
+}
+
+extension NSRange {
+ public init?(_ string: String) {
+ var savedLocation = 0
+ if string.isEmpty {
+ // fail early if the string is empty
+ return nil
+ }
+ let scanner = Scanner(string: string)
+ let digitSet = CharacterSet.decimalDigits
+ let _ = scanner.scanUpToCharacters(from: digitSet, into: nil)
+ if scanner.isAtEnd {
+ // fail early if there are no decimal digits
+ return nil
+ }
+ var location = 0
+ savedLocation = scanner.scanLocation
+ guard scanner.scanInt(&location) else {
+ return nil
+ }
+ if scanner.isAtEnd {
+ // return early if there are no more characters after the first int in the string
+ return nil
+ }
+ if scanner.scanString(".", into: nil) {
+ scanner.scanLocation = savedLocation
+ var double = 0.0
+ guard scanner.scanDouble(&double) else {
+ return nil
+ }
+ guard let integral = Int(exactly: double) else {
+ return nil
+ }
+ location = integral
+ }
+
+ let _ = scanner.scanUpToCharacters(from: digitSet, into: nil)
+ if scanner.isAtEnd {
+ // return early if there are no integer characters after the first int in the string
+ return nil
+ }
+ var length = 0
+ savedLocation = scanner.scanLocation
+ guard scanner.scanInt(&length) else {
+ return nil
+ }
+
+ if !scanner.isAtEnd {
+ if scanner.scanString(".", into: nil) {
+ scanner.scanLocation = savedLocation
+ var double = 0.0
+ guard scanner.scanDouble(&double) else {
+ return nil
+ }
+ guard let integral = Int(exactly: double) else {
+ return nil
+ }
+ length = integral
+ }
+ }
+
+
+ self.location = location
+ self.length = length
+ }
+}
+
+extension NSRange {
+ public var lowerBound: Int { return location }
+
+ public var upperBound: Int { return location + length }
+
+ public func contains(_ index: Int) -> Bool { return (!(index < location) && (index - location) < length) }
+
+ public mutating func formUnion(_ other: NSRange) {
+ self = union(other)
+ }
+
+ public func union(_ other: NSRange) -> NSRange {
+ let max1 = location + length
+ let max2 = other.location + other.length
+ let maxend = (max1 < max2) ? max2 : max1
+ let minloc = location < other.location ? location : other.location
+ return NSRange(location: minloc, length: maxend - minloc)
+ }
+
+ public func intersection(_ other: NSRange) -> NSRange? {
+ let max1 = location + length
+ let max2 = other.location + other.length
+ let minend = (max1 < max2) ? max1 : max2
+ if other.location <= location && location < max2 {
+ return NSRange(location: location, length: minend - location)
+ } else if location <= other.location && other.location < max1 {
+ return NSRange(location: other.location, length: minend - other.location);
+ }
+ return nil
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Ranges
+//===----------------------------------------------------------------------===//
+
+extension NSRange {
+ public init<R: RangeExpression>(_ region: R)
+ where R.Bound: FixedWidthInteger, R.Bound.Stride : SignedInteger {
+ let r = region.relative(to: 0..<R.Bound.max)
+ location = numericCast(r.lowerBound)
+ length = numericCast(r.count)
+ }
+
+ public init<R: RangeExpression, S: StringProtocol>(_ region: R, in target: S)
+ where R.Bound == S.Index, S.Index == String.Index {
+ let r = region.relative(to: target)
+ self = NSRange(
+ location: r.lowerBound._utf16Index - target.startIndex._utf16Index,
+ length: r.upperBound._utf16Index - r.lowerBound._utf16Index
+ )
+ }
+
+ @available(swift, deprecated: 4, renamed: "Range.init(_:)")
+ public func toRange() -> Range<Int>? {
+ if location == NSNotFound { return nil }
+ return location..<(location+length)
+ }
+}
+
+extension Range where Bound: BinaryInteger {
+ public init?(_ range: NSRange) {
+ guard range.location != NSNotFound else { return nil }
+ self.init(uncheckedBounds: (numericCast(range.lowerBound), numericCast(range.upperBound)))
+ }
+}
+
+// This additional overload will mean Range.init(_:) defaults to Range<Int> when
+// no additional type context is provided:
+extension Range where Bound == Int {
+ public init?(_ range: NSRange) {
+ guard range.location != NSNotFound else { return nil }
+ self.init(uncheckedBounds: (range.lowerBound, range.upperBound))
+ }
+}
+
+extension Range where Bound == String.Index {
+ public init?(_ range: NSRange, in string: String) {
+ let u = string.utf16
+ guard range.location != NSNotFound,
+ let start = u.index(u.startIndex, offsetBy: range.location, limitedBy: u.endIndex),
+ let end = u.index(u.startIndex, offsetBy: range.location + range.length, limitedBy: u.endIndex),
+ let lowerBound = String.Index(start, within: string),
+ let upperBound = String.Index(end, within: string)
+ else { return nil }
+
+ self = lowerBound..<upperBound
+ }
+}
+
+extension NSRange : CustomReflectable {
+ public var customMirror: Mirror {
+ return Mirror(self, children: ["location": location, "length": length])
+ }
+}
+
+extension NSRange : CustomPlaygroundQuickLookable {
+ public var customPlaygroundQuickLook: PlaygroundQuickLook {
+ return .range(Int64(location), Int64(length))
+ }
+}
+
+extension NSRange : Codable {
+ public init(from decoder: Decoder) throws {
+ var container = try decoder.unkeyedContainer()
+ let location = try container.decode(Int.self)
+ let length = try container.decode(Int.self)
+ self.init(location: location, length: length)
+ }
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.unkeyedContainer()
+ try container.encode(self.location)
+ try container.encode(self.length)
+ }
+}
+
+#if DEPLOYMENT_RUNTIME_SWIFT
+
+
+extension NSRange {
+ internal init(_ range: CFRange) {
+ location = range.location == kCFNotFound ? NSNotFound : range.location
+ length = range.length
+ }
+}
+
+extension CFRange {
+ internal init(_ range: NSRange) {
+ location = range.location == NSNotFound ? kCFNotFound : range.location
+ length = range.length
+ }
+}
+
+extension NSRange {
+ public init(_ x: Range<Int>) {
+ location = x.lowerBound
+ length = x.count
+ }
+
+ internal func toCountableRange() -> CountableRange<Int>? {
+ if location == NSNotFound { return nil }
+ return location..<(location+length)
+ }
+}
+
+extension NSRange: NSSpecialValueCoding {
+ init(bytes: UnsafeRawPointer) {
+ self.location = bytes.load(as: Int.self)
+ self.length = bytes.load(fromByteOffset: MemoryLayout<Int>.stride, as: Int.self)
+ }
+
+ init?(coder aDecoder: NSCoder) {
+ guard aDecoder.allowsKeyedCoding else {
+ preconditionFailure("Unkeyed coding is unsupported.")
+ }
+ if let location = aDecoder.decodeObject(of: NSNumber.self, forKey: "NS.rangeval.location") {
+ self.location = location.intValue
+ } else {
+ self.location = 0
+ }
+ if let length = aDecoder.decodeObject(of: NSNumber.self, forKey: "NS.rangeval.length") {
+ self.length = length.intValue
+ } else {
+ self.length = 0
+ }
+ }
+
+ func encodeWithCoder(_ aCoder: NSCoder) {
+ guard aCoder.allowsKeyedCoding else {
+ preconditionFailure("Unkeyed coding is unsupported.")
+ }
+ aCoder.encode(NSNumber(value: self.location), forKey: "NS.rangeval.location")
+ aCoder.encode(NSNumber(value: self.length), forKey: "NS.rangeval.length")
+ }
+
+ static func objCType() -> String {
+#if arch(i386) || arch(arm)
+ return "{_NSRange=II}"
+#elseif arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
+ return "{_NSRange=QQ}"
+#else
+ NSUnimplemented()
+#endif
+ }
+
+ func getValue(_ value: UnsafeMutableRawPointer) {
+ value.initializeMemory(as: NSRange.self, to: self)
+ }
+
+ func isEqual(_ aValue: Any) -> Bool {
+ if let other = aValue as? NSRange {
+ return other.location == self.location && other.length == self.length
+ } else {
+ return false
+ }
+ }
+
+ var hash: Int { return hashValue }
+}
+
extension NSValue {
public convenience init(range: NSRange) {
self.init()
@@ -215,3 +425,5 @@
return specialValue._value as! NSRange
}
}
+#endif
+
diff --git a/Foundation/NSScanner.swift b/Foundation/NSScanner.swift
index 93b91ea..40da664 100644
--- a/Foundation/NSScanner.swift
+++ b/Foundation/NSScanner.swift
@@ -391,19 +391,19 @@
extension Scanner {
// On overflow, the below methods will return success and clamp
- public func scanInt(_ result: UnsafeMutablePointer<Int32>) -> Bool {
+ public func scanInt32(_ result: UnsafeMutablePointer<Int32>) -> Bool {
return _scanString.scan(_skipSet, locationToScanFrom: &_scanLocation) { (value: Int32) -> Void in
result.pointee = value
}
}
- public func scanInteger(_ result: UnsafeMutablePointer<Int>) -> Bool {
+ public func scanInt(_ result: UnsafeMutablePointer<Int>) -> Bool {
return _scanString.scan(_skipSet, locationToScanFrom: &_scanLocation) { (value: Int) -> Void in
result.pointee = value
}
}
- public func scanLongLong(_ result: UnsafeMutablePointer<Int64>) -> Bool {
+ public func scanInt64(_ result: UnsafeMutablePointer<Int64>) -> Bool {
return _scanString.scan(_skipSet, locationToScanFrom: &_scanLocation) { (value: Int64) -> Void in
result.pointee = value
}
@@ -427,13 +427,13 @@
}
}
- public func scanHexInt(_ result: UnsafeMutablePointer<UInt32>) -> Bool {
+ public func scanHexInt32(_ result: UnsafeMutablePointer<UInt32>) -> Bool {
return _scanString.scanHex(_skipSet, locationToScanFrom: &_scanLocation) { (value: UInt32) -> Void in
result.pointee = value
}
}
- public func scanHexLongLong(_ result: UnsafeMutablePointer<UInt64>) -> Bool {
+ public func scanHexInt64(_ result: UnsafeMutablePointer<UInt64>) -> Bool {
return _scanString.scanHex(_skipSet, locationToScanFrom: &_scanLocation) { (value: UInt64) -> Void in
result.pointee = value
}
@@ -469,9 +469,20 @@
/// - Experiment: This is a draft API currently under consideration for official import into Foundation as a suitable alternative
/// - Note: Since this API is under consideration it may be either removed or revised in the near future
extension Scanner {
- public func scanInt() -> Int32? {
+ public func scanInt32() -> Int32? {
var value: Int32 = 0
return withUnsafeMutablePointer(to: &value) { (ptr: UnsafeMutablePointer<Int32>) -> Int32? in
+ if scanInt32(ptr) {
+ return ptr.pointee
+ } else {
+ return nil
+ }
+ }
+ }
+
+ public func scanInt() -> Int? {
+ var value: Int = 0
+ return withUnsafeMutablePointer(to: &value) { (ptr: UnsafeMutablePointer<Int>) -> Int? in
if scanInt(ptr) {
return ptr.pointee
} else {
@@ -480,21 +491,10 @@
}
}
- public func scanInteger() -> Int? {
- var value: Int = 0
- return withUnsafeMutablePointer(to: &value) { (ptr: UnsafeMutablePointer<Int>) -> Int? in
- if scanInteger(ptr) {
- return ptr.pointee
- } else {
- return nil
- }
- }
- }
-
- public func scanLongLong() -> Int64? {
+ public func scanInt64() -> Int64? {
var value: Int64 = 0
return withUnsafeMutablePointer(to: &value) { (ptr: UnsafeMutablePointer<Int64>) -> Int64? in
- if scanLongLong(ptr) {
+ if scanInt64(ptr) {
return ptr.pointee
} else {
return nil
@@ -535,10 +535,10 @@
}
}
- public func scanHexInt() -> UInt32? {
+ public func scanHexInt32() -> UInt32? {
var value: UInt32 = 0
return withUnsafeMutablePointer(to: &value) { (ptr: UnsafeMutablePointer<UInt32>) -> UInt32? in
- if scanHexInt(ptr) {
+ if scanHexInt32(ptr) {
return ptr.pointee
} else {
return nil
@@ -546,10 +546,10 @@
}
}
- public func scanHexLongLong() -> UInt64? {
+ public func scanHexInt64() -> UInt64? {
var value: UInt64 = 0
return withUnsafeMutablePointer(to: &value) { (ptr: UnsafeMutablePointer<UInt64>) -> UInt64? in
- if scanHexLongLong(ptr) {
+ if scanHexInt64(ptr) {
return ptr.pointee
} else {
return nil
@@ -579,9 +579,17 @@
}
}
+ public func scanString(_ string:String, into ptr: UnsafeMutablePointer<String?>?) -> Bool {
+ if let str = scanString(string) {
+ ptr?.pointee = str
+ return true
+ }
+ return false
+ }
+
// These methods avoid calling the private API for _invertedSkipSet and manually re-construct them so that it is only usage of public API usage
// Future implementations on Darwin of these methods will likely be more optimized to take advantage of the cached values.
- public func scanString(string searchString: String) -> String? {
+ public func scanString(_ searchString: String) -> String? {
let str = self.string._bridgeToObjectiveC()
var stringLoc = scanLocation
let stringLen = str.length
@@ -644,6 +652,14 @@
return nil
}
+ public func scanUpToCharacters(from set: CharacterSet, into ptr: UnsafeMutablePointer<String?>?) -> Bool {
+ if let result = scanUpToCharactersFromSet(set) {
+ ptr?.pointee = result
+ return true
+ }
+ return false
+ }
+
public func scanUpToCharactersFromSet(_ set: CharacterSet) -> String? {
let str = self.string._bridgeToObjectiveC()
var stringLoc = scanLocation
diff --git a/Foundation/NSSpecialValue.swift b/Foundation/NSSpecialValue.swift
index 42bc6d9..6809db0 100644
--- a/Foundation/NSSpecialValue.swift
+++ b/Foundation/NSSpecialValue.swift
@@ -25,7 +25,7 @@
// So in order to implement equality and hash we have the hack below.
func isEqual(_ value: Any) -> Bool
var hash: Int { get }
- var description: String? { get }
+ var description: String { get }
}
internal class NSSpecialValue : NSValue {
@@ -126,11 +126,11 @@
}
override var description : String {
- if let description = _value.description {
- return description
- } else {
+ let desc = _value.description
+ if desc.isEmpty {
return super.description
}
+ return desc
}
override func isEqual(_ value: Any?) -> Bool {
diff --git a/Foundation/NSString.swift b/Foundation/NSString.swift
index a444c24..97212d5 100644
--- a/Foundation/NSString.swift
+++ b/Foundation/NSString.swift
@@ -639,18 +639,18 @@
}
public var intValue: Int32 {
- return Scanner(string: _swiftObject).scanInt() ?? 0
+ return Scanner(string: _swiftObject).scanInt32() ?? 0
}
public var integerValue: Int {
let scanner = Scanner(string: _swiftObject)
var value: Int = 0
- let _ = scanner.scanInteger(&value)
+ let _ = scanner.scanInt(&value)
return value
}
public var longLongValue: Int64 {
- return Scanner(string: _swiftObject).scanLongLong() ?? 0
+ return Scanner(string: _swiftObject).scanInt64() ?? 0
}
public var boolValue: Bool {
@@ -658,8 +658,8 @@
// skip initial whitespace if present
let _ = scanner.scanCharactersFromSet(.whitespaces)
// scan a single optional '+' or '-' character, followed by zeroes
- if scanner.scanString(string: "+") == nil {
- let _ = scanner.scanString(string: "-")
+ if scanner.scanString("+") == nil {
+ let _ = scanner.scanString("-")
}
// scan any following zeroes
let _ = scanner.scanCharactersFromSet(CharacterSet(charactersIn: "0"))
diff --git a/TestFoundation/TestNSScanner.swift b/TestFoundation/TestNSScanner.swift
index 4ed0ded..aec488d 100644
--- a/TestFoundation/TestNSScanner.swift
+++ b/TestFoundation/TestNSScanner.swift
@@ -33,7 +33,7 @@
func test_scanInteger() {
let scanner = Scanner(string: "123")
var value: Int = 0
- XCTAssert(scanner.scanInteger(&value), "An Integer should be found in the string `123`.")
+ XCTAssert(scanner.scanInt(&value), "An Integer should be found in the string `123`.")
XCTAssertEqual(value, 123, "Scanned Integer value of the string `123` should be `123`.")
XCTAssertTrue(scanner.isAtEnd)
}
@@ -48,7 +48,7 @@
func test_scanString() {
let scanner = Scanner(string: "apple sauce")
- guard let firstPart = scanner.scanString(string: "apple ") else {
+ guard let firstPart = scanner.scanString("apple ") else {
XCTFail()
return
}
@@ -56,7 +56,7 @@
XCTAssertEqual(firstPart, "apple ")
XCTAssertFalse(scanner.isAtEnd)
- let _ = scanner.scanString(string: "sauce")
+ let _ = scanner.scanString("sauce")
XCTAssertTrue(scanner.isAtEnd)
}
@@ -64,7 +64,7 @@
let scanner = Scanner(string: "xyz ")
scanner.charactersToBeSkipped = .whitespaces
- let _ = scanner.scanString(string: "xyz")
+ let _ = scanner.scanString("xyz")
XCTAssertTrue(scanner.isAtEnd)
}
}