mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
133 lines
4.5 KiB
Swift
133 lines
4.5 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
@_exported import Foundation // Clang module
|
|
|
|
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 && rhs.length == rhs.length
|
|
}
|
|
}
|
|
|
|
extension NSRange : CustomStringConvertible, CustomDebugStringConvertible {
|
|
public var description: String { return "{\(location), \(length)}" }
|
|
public var debugDescription: String { return "{\(location), \(length)}" }
|
|
}
|
|
|
|
extension NSRange {
|
|
public init?(_ string: String) {
|
|
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
|
|
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
|
|
}
|
|
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
|
|
guard scanner.scanInt(&length) else {
|
|
return nil
|
|
}
|
|
|
|
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(_ x: Range<Int>) {
|
|
location = x.lowerBound
|
|
length = x.count
|
|
}
|
|
|
|
// FIXME(ABI)#75 (Conditional Conformance): this API should be an extension on Range.
|
|
// Can't express it now because the compiler does not support conditional
|
|
// extensions with type equality constraints.
|
|
public func toRange() -> Range<Int>? {
|
|
if location == NSNotFound { return nil }
|
|
return location..<(location+length)
|
|
}
|
|
}
|
|
|
|
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))
|
|
}
|
|
}
|