//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// @_exported import Foundation // Clang module private func _utfRangeToNSRange(_ inRange : Range) -> NSRange { return NSMakeRange(Int(inRange.lowerBound.value), Int(inRange.upperBound.value - inRange.lowerBound.value)) } internal final class _SwiftNSCharacterSet : _SwiftNativeNSCharacterSet, _SwiftNativeFoundationType { internal typealias ImmutableType = NSCharacterSet internal typealias MutableType = NSMutableCharacterSet var __wrapped : _MutableUnmanagedWrapper init(immutableObject: AnyObject) { // Take ownership. __wrapped = .Immutable(Unmanaged.passRetained(_unsafeReferenceCast(immutableObject, to: ImmutableType.self))) } init(mutableObject: AnyObject) { // Take ownership. __wrapped = .Mutable(Unmanaged.passRetained(_unsafeReferenceCast(mutableObject, to: MutableType.self))) } internal required init(unmanagedImmutableObject: Unmanaged) { // Take ownership. __wrapped = .Immutable(unmanagedImmutableObject) super.init() } internal required init(unmanagedMutableObject: Unmanaged) { // Take ownership. __wrapped = .Mutable(unmanagedMutableObject) super.init() } deinit { releaseWrappedObject() } @objc(copyWithZone:) func copy(with zone: NSZone? = nil) -> Any { return _mapUnmanaged { $0.copy(with: zone) } } @objc(mutableCopyWithZone:) func mutableCopy(with zone: NSZone? = nil) -> Any { return _mapUnmanaged { $0.mutableCopy(with: zone) } } @objc public var classForCoder: AnyClass { return NSCharacterSet.self } } /** A `CharacterSet` represents a set of Unicode-compliant characters. Foundation types use `CharacterSet` to group characters together for searching operations, so that they can find any of a particular set of characters during a search. This type provides "copy-on-write" behavior, and is also bridged to the Objective-C `NSCharacterSet` class. */ public struct CharacterSet : ReferenceConvertible, Equatable, Hashable, SetAlgebra, _MutablePairBoxing { public typealias ReferenceType = NSCharacterSet internal typealias SwiftNSWrapping = _SwiftNSCharacterSet internal typealias ImmutableType = SwiftNSWrapping.ImmutableType internal typealias MutableType = SwiftNSWrapping.MutableType internal var _wrapped : _SwiftNSCharacterSet // MARK: Init methods private init(_bridged characterSet: NSCharacterSet) { // We must copy the input because it might be mutable; just like storing a value type in ObjC _wrapped = _SwiftNSCharacterSet(immutableObject: characterSet.copy() as AnyObject) } /// Initialize an empty instance. public init() { _wrapped = _SwiftNSCharacterSet(immutableObject: NSCharacterSet()) } /// Initialize with a range of integers. /// /// It is the caller's responsibility to ensure that the values represent valid `UnicodeScalar` values, if that is what is desired. public init(charactersIn range: Range) { _wrapped = _SwiftNSCharacterSet(immutableObject: NSCharacterSet(range: _utfRangeToNSRange(range))) } /// Initialize with a closed range of integers. /// /// It is the caller's responsibility to ensure that the values represent valid `UnicodeScalar` values, if that is what is desired. public init(charactersIn range: ClosedRange) { let halfOpenRange = range.lowerBound.. Bool { return _mapUnmanaged { $0.hasMemberInPlane(plane) } } // MARK: Mutable functions /// Insert a range of integer values in the `CharacterSet`. /// /// It is the caller's responsibility to ensure that the values represent valid `UnicodeScalar` values, if that is what is desired. public mutating func insert(charactersIn range: Range) { let nsRange = _utfRangeToNSRange(range) _applyUnmanagedMutation { $0.addCharacters(in: nsRange) } } /// Insert a closed range of integer values in the `CharacterSet`. /// /// It is the caller's responsibility to ensure that the values represent valid `UnicodeScalar` values, if that is what is desired. public mutating func insert(charactersIn range: ClosedRange) { let halfOpenRange = range.lowerBound..) { let nsRange = _utfRangeToNSRange(range) _applyUnmanagedMutation { $0.removeCharacters(in: nsRange) } } /// Remove a closed range of integer values from the `CharacterSet`. public mutating func remove(charactersIn range: ClosedRange) { let halfOpenRange = range.lowerBound.. (inserted: Bool, memberAfterInsert: UnicodeScalar) { let nsRange = NSMakeRange(Int(character.value), 1) _applyUnmanagedMutation { $0.addCharacters(in: nsRange) } // TODO: This should probably return the truth, but figuring it out requires two calls into NSCharacterSet return (true, character) } /// Insert a `UnicodeScalar` representation of a character into the `CharacterSet`. /// /// `UnicodeScalar` values are available on `Swift.String.UnicodeScalarView`. @discardableResult public mutating func update(with character: UnicodeScalar) -> UnicodeScalar? { let nsRange = NSMakeRange(Int(character.value), 1) _applyUnmanagedMutation { $0.addCharacters(in: nsRange) } // TODO: This should probably return the truth, but figuring it out requires two calls into NSCharacterSet return character } /// Remove a `UnicodeScalar` representation of a character from the `CharacterSet`. /// /// `UnicodeScalar` values are available on `Swift.String.UnicodeScalarView`. @discardableResult public mutating func remove(_ character: UnicodeScalar) -> UnicodeScalar? { // TODO: Add method to NSCharacterSet to do this in one call let result : UnicodeScalar? = contains(character) ? character : nil let r = NSMakeRange(Int(character.value), 1) _applyUnmanagedMutation { $0.removeCharacters(in: r) } return result } /// Test for membership of a particular `UnicodeScalar` in the `CharacterSet`. public func contains(_ member: UnicodeScalar) -> Bool { return _mapUnmanaged { $0.longCharacterIsMember(member.value) } } /// Returns a union of the `CharacterSet` with another `CharacterSet`. public func union(_ other: CharacterSet) -> CharacterSet { // The underlying collection does not have a method to return new CharacterSets with changes applied, so we will copy and apply here var result = self result.formUnion(other) return result } /// Sets the value to a union of the `CharacterSet` with another `CharacterSet`. public mutating func formUnion(_ other: CharacterSet) { _applyUnmanagedMutation { $0.formUnion(with: other) } } /// Returns an intersection of the `CharacterSet` with another `CharacterSet`. public func intersection(_ other: CharacterSet) -> CharacterSet { // The underlying collection does not have a method to return new CharacterSets with changes applied, so we will copy and apply here var result = self result.formIntersection(other) return result } /// Sets the value to the intersection of the `CharacterSet` with another `CharacterSet`. public mutating func formIntersection(_ other: CharacterSet) { _applyUnmanagedMutation { $0.formIntersection(with: other) } } /// Returns the exclusive or of the `CharacterSet` with another `CharacterSet`. public func symmetricDifference(_ other: CharacterSet) -> CharacterSet { return union(other).subtracting(intersection(other)) } /// Sets the value to the exclusive or of the `CharacterSet` with another `CharacterSet`. public mutating func formSymmetricDifference(_ other: CharacterSet) { self = symmetricDifference(other) } /// Returns true if `self` is a superset of `other`. public func isSuperset(of other: CharacterSet) -> Bool { return _mapUnmanaged { $0.isSuperset(of: other) } } /// Returns true if the two `CharacterSet`s are equal. public static func ==(lhs : CharacterSet, rhs: CharacterSet) -> Bool { return lhs._wrapped.isEqual(rhs as NSCharacterSet) } } // MARK: Objective-C Bridging extension CharacterSet : _ObjectiveCBridgeable { public static func _getObjectiveCType() -> Any.Type { return NSCharacterSet.self } @_semantics("convertToObjectiveC") public func _bridgeToObjectiveC() -> NSCharacterSet { return unsafeBitCast(_wrapped, to: NSCharacterSet.self) } public static func _forceBridgeFromObjectiveC(_ input: NSCharacterSet, result: inout CharacterSet?) { result = CharacterSet(_bridged: input) } public static func _conditionallyBridgeFromObjectiveC(_ input: NSCharacterSet, result: inout CharacterSet?) -> Bool { result = CharacterSet(_bridged: input) return true } public static func _unconditionallyBridgeFromObjectiveC(_ source: NSCharacterSet?) -> CharacterSet { return CharacterSet(_bridged: source!) } } extension _SwiftNSCharacterSet { // Stubs // ----- // Immutable var bitmapRepresentation: Data { return _mapUnmanaged { $0.bitmapRepresentation } } var inverted : CharacterSet { return _mapUnmanaged { $0.inverted } } func hasMember(inPlane plane: UInt8) -> Bool { return _mapUnmanaged {$0.hasMemberInPlane(plane) } } func characterIsMember(_ member: unichar) -> Bool { return _mapUnmanaged { $0.characterIsMember(member) } } func longCharacterIsMember(_ member: UTF32Char) -> Bool { return _mapUnmanaged { $0.longCharacterIsMember(member) } } func isSuperset(of other: CharacterSet) -> Bool { return _mapUnmanaged { $0.isSuperset(of: other) } } }