blob: 9d76f93a24a22307d44f1890380b87cf4e7c8cb2 [file] [log] [blame]
// 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
//
/**************** Immutable Ordered Set ****************/
open class NSOrderedSet : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, ExpressibleByArrayLiteral {
internal var _storage: Set<NSObject>
internal var _orderedStorage: [NSObject]
open override func copy() -> Any {
return copy(with: nil)
}
open func copy(with zone: NSZone? = nil) -> Any {
NSUnimplemented()
}
open override func mutableCopy() -> Any {
return mutableCopy(with: nil)
}
open func mutableCopy(with zone: NSZone? = nil) -> Any {
NSUnimplemented()
}
public static var supportsSecureCoding: Bool {
return true
}
open override func isEqual(_ object: Any?) -> Bool {
guard let orderedSet = object as? NSOrderedSet else { return false }
return isEqual(to: orderedSet)
}
open func encode(with aCoder: NSCoder) {
guard aCoder.allowsKeyedCoding else {
preconditionFailure("Unkeyed coding is unsupported.")
}
for idx in 0..<self.count {
aCoder.encode(_SwiftValue.store(self.object(at: idx)), forKey:"NS.object.\(idx)")
}
}
public required convenience init?(coder aDecoder: NSCoder) {
guard aDecoder.allowsKeyedCoding else {
preconditionFailure("Unkeyed coding is unsupported.")
}
var idx = 0
var objects : [AnyObject] = []
while aDecoder.containsValue(forKey: ("NS.object.\(idx)")) {
guard let object = aDecoder.decodeObject(forKey: "NS.object.\(idx)") else {
return nil
}
objects.append(object as! NSObject)
idx += 1
}
self.init(array: objects)
}
open var count: Int {
return _storage.count
}
open func object(at idx: Int) -> Any {
return _SwiftValue.fetch(nonOptional: _orderedStorage[idx])
}
open func index(of object: Any) -> Int {
return _orderedStorage.index(of: _SwiftValue.store(object)) ?? NSNotFound
}
public convenience override init() {
self.init(objects: [], count: 0)
}
public init(objects: UnsafePointer<AnyObject>!, count cnt: Int) {
_storage = Set<NSObject>()
_orderedStorage = [NSObject]()
super.init()
_insertObjects(objects, count: cnt)
}
required public convenience init(arrayLiteral elements: Any...) {
self.init(array: elements)
}
public convenience init(objects elements: Any...) {
self.init(array: elements)
}
open subscript (idx: Int) -> Any {
return object(at: idx)
}
fileprivate func _insertObject(_ object: Any) {
let value = _SwiftValue.store(object)
guard !contains(value) else {
return
}
_storage.insert(value)
_orderedStorage.append(value)
}
fileprivate func _insertObjects(_ objects: UnsafePointer<AnyObject>!, count cnt: Int) {
let buffer = UnsafeBufferPointer(start: objects, count: cnt)
for obj in buffer {
_insertObject(obj)
}
}
internal var allObjects: [Any] {
if type(of: self) === NSOrderedSet.self || type(of: self) === NSMutableOrderedSet.self {
return _orderedStorage.map { _SwiftValue.fetch(nonOptional: $0) }
} else {
return (0..<count).map { idx in
return self[idx]
}
}
}
}
extension NSOrderedSet : Sequence {
/// Return a *generator* over the elements of this *sequence*.
///
/// - Complexity: O(1).
public typealias Iterator = NSEnumerator.Iterator
public func makeIterator() -> Iterator {
return self.objectEnumerator().makeIterator()
}
}
extension NSOrderedSet {
public func getObjects(_ objects: inout [AnyObject], range: NSRange) {
for idx in range.location..<(range.location + range.length) {
objects.append(_orderedStorage[idx])
}
}
open func objects(at indexes: IndexSet) -> [Any] {
var entries = [Any]()
for idx in indexes {
guard idx < count && idx >= 0 else {
fatalError("\(self): Index out of bounds")
}
entries.append(object(at: idx))
}
return entries
}
public var firstObject: Any? {
if let value = _orderedStorage.first {
return _SwiftValue.fetch(nonOptional: value)
} else {
return nil
}
}
public var lastObject: Any? {
if let value = _orderedStorage.last {
return _SwiftValue.fetch(nonOptional: value)
} else {
return nil
}
}
open func isEqual(to other: NSOrderedSet) -> Bool {
if count != other.count {
return false
}
for idx in 0..<count {
if let value1 = object(at: idx) as? AnyHashable,
let value2 = other.object(at: idx) as? AnyHashable {
if value1 != value2 {
return false
}
}
}
return true
}
open func contains(_ object: Any) -> Bool {
return _storage.contains(_SwiftValue.store(object))
}
open func intersects(_ other: NSOrderedSet) -> Bool {
if count < other.count {
return contains { obj in other.contains(obj) }
} else {
return other.contains { obj in contains(obj) }
}
}
open func intersectsSet(_ set: Set<AnyHashable>) -> Bool {
if count < set.count {
return contains { obj in set.contains(obj) }
} else {
return set.contains { obj in contains(obj) }
}
}
open func isSubset(of other: NSOrderedSet) -> Bool {
for item in self {
if !other.contains(item) {
return false
}
}
return true
}
open func isSubset(of set: Set<AnyHashable>) -> Bool {
for item in self {
if !set.contains(item as! AnyHashable) {
return false
}
}
return true
}
public func objectEnumerator() -> NSEnumerator {
guard type(of: self) === NSOrderedSet.self || type(of: self) === NSMutableOrderedSet.self else {
NSRequiresConcreteImplementation()
}
return NSGeneratorEnumerator(_orderedStorage.map { _SwiftValue.fetch(nonOptional: $0) }.makeIterator())
}
public func reverseObjectEnumerator() -> NSEnumerator {
guard type(of: self) === NSOrderedSet.self || type(of: self) === NSMutableOrderedSet.self else {
NSRequiresConcreteImplementation()
}
return NSGeneratorEnumerator(_orderedStorage.map { _SwiftValue.fetch(nonOptional: $0) }.reversed().makeIterator())
}
/*@NSCopying*/
public var reversed: NSOrderedSet {
return NSOrderedSet(array: _orderedStorage.map { _SwiftValue.fetch(nonOptional: $0) }.reversed())
}
// These two methods return a facade object for the receiving ordered set,
// which acts like an immutable array or set (respectively). Note that
// while you cannot mutate the ordered set through these facades, mutations
// to the original ordered set will "show through" the facade and it will
// appear to change spontaneously, since a copy of the ordered set is not
// being made.
public var array: [Any] { NSUnimplemented() }
public var set: Set<AnyHashable> { NSUnimplemented() }
open func enumerateObjects(_ block: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Swift.Void) { NSUnimplemented() }
open func enumerateObjects(options opts: NSEnumerationOptions = [], using block: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Swift.Void) { NSUnimplemented() }
open func enumerateObjects(at s: IndexSet, options opts: NSEnumerationOptions = [], using block: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Swift.Void) { NSUnimplemented() }
open func index(ofObjectPassingTest predicate: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Bool) -> Int { NSUnimplemented() }
open func index(_ opts: NSEnumerationOptions = [], ofObjectPassingTest predicate: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Bool) -> Int { NSUnimplemented() }
open func index(ofObjectAt s: IndexSet, options opts: NSEnumerationOptions = [], passingTest predicate: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Bool) -> Int { NSUnimplemented() }
open func indexes(ofObjectsPassingTest predicate: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Bool) -> IndexSet { NSUnimplemented() }
open func indexes(options opts: NSEnumerationOptions = [], ofObjectsPassingTest predicate: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Bool) -> IndexSet { NSUnimplemented() }
open func indexes(ofObjectsAt s: IndexSet, options opts: NSEnumerationOptions = [], passingTest predicate: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Bool) -> IndexSet { NSUnimplemented() }
open func index(of object: Any, inSortedRange range: NSRange, options opts: NSBinarySearchingOptions = [], usingComparator cmp: (Any, Any) -> ComparisonResult) -> Int { NSUnimplemented() } // binary search
open func sortedArray(comparator cmptr: (Any, Any) -> ComparisonResult) -> [Any] { NSUnimplemented() }
open func sortedArray(options opts: NSSortOptions = [], usingComparator cmptr: (Any, Any) -> ComparisonResult) -> [Any] { NSUnimplemented() }
public func description(withLocale locale: Locale?) -> String { NSUnimplemented() }
public func description(withLocale locale: Locale?, indent level: Int) -> String { NSUnimplemented() }
}
extension NSOrderedSet {
public convenience init(object: Any) {
self.init(array: [object])
}
public convenience init(orderedSet set: NSOrderedSet) {
self.init(orderedSet: set, copyItems: false)
}
public convenience init(orderedSet set: NSOrderedSet, copyItems flag: Bool) {
self.init(orderedSet: set, range: NSMakeRange(0, set.count), copyItems: flag)
}
public convenience init(orderedSet set: NSOrderedSet, range: NSRange, copyItems flag: Bool) {
// TODO: Use the array method here when available.
self.init(array: Array(set), range: range, copyItems: flag)
}
public convenience init(array: [Any]) {
let buffer = UnsafeMutablePointer<AnyObject>.allocate(capacity: array.count)
for (idx, element) in array.enumerated() {
buffer.advanced(by: idx).initialize(to: _SwiftValue.store(element))
}
self.init(objects: buffer, count: array.count)
buffer.deinitialize(count: array.count)
buffer.deallocate(capacity: array.count)
}
public convenience init(array set: [Any], copyItems flag: Bool) {
self.init(array: set, range: NSMakeRange(0, set.count), copyItems: flag)
}
public convenience init(array set: [Any], range: NSRange, copyItems flag: Bool) {
var objects = set
if let range = range.toCountableRange(), range.count != set.count || flag {
objects = [Any]()
for index in range.indices {
let object = set[index]
objects.append(flag ? (object as! NSObject).copy() : object)
}
}
self.init(array: objects)
}
public convenience init(set: Set<AnyHashable>) {
self.init(set: set, copyItems: false)
}
public convenience init(set: Set<AnyHashable>, copyItems flag: Bool) {
self.init(array: Array(set), copyItems: flag)
}
}
/**************** Mutable Ordered Set ****************/
open class NSMutableOrderedSet : NSOrderedSet {
open func insert(_ object: Any, at idx: Int) {
guard idx <= count && idx >= 0 else {
fatalError("\(self): Index out of bounds")
}
let value = _SwiftValue.store(object)
if contains(value) {
return
}
_storage.insert(value)
_orderedStorage.insert(value, at: idx)
}
open func removeObject(at idx: Int) {
_storage.remove(_orderedStorage[idx])
_orderedStorage.remove(at: idx)
}
open func replaceObject(at idx: Int, with obj: Any) {
guard idx < count && idx >= 0 else {
fatalError("\(self): Index out of bounds")
}
let value = _SwiftValue.store(obj)
let objectToReplace = _SwiftValue.store(object(at: idx))
_orderedStorage[idx] = value
_storage.remove(objectToReplace)
_storage.insert(value)
}
public init(capacity numItems: Int) {
super.init(objects: [], count: 0)
}
required public convenience init(arrayLiteral elements: Any...) {
self.init(capacity: 0)
addObjects(from: elements)
}
public required init?(coder aDecoder: NSCoder) { NSUnimplemented() }
fileprivate func _removeObject(_ object: Any) {
let value = _SwiftValue.store(object)
guard contains(object) else {
return
}
_storage.remove(value)
_orderedStorage.remove(at: index(of: object))
}
open override subscript(idx: Int) -> Any {
get {
return object(at: idx)
}
set {
replaceObject(at: idx, with: newValue)
}
}
}
extension NSMutableOrderedSet {
open func add(_ object: Any) {
_insertObject(object)
}
open func add(_ objects: UnsafePointer<AnyObject>!, count: Int) {
_insertObjects(objects, count: count)
}
open func addObjects(from array: [Any]) {
for object in array {
_insertObject(object)
}
}
open func exchangeObject(at idx1: Int, withObjectAt idx2: Int) {
guard idx1 < count && idx1 >= 0 && idx2 < count && idx2 >= 0 else {
fatalError("\(self): Index out of bounds")
}
let object1 = self.object(at: idx1)
let object2 = self.object(at: idx2)
_orderedStorage[idx1] = _SwiftValue.store(object2)
_orderedStorage[idx2] = _SwiftValue.store(object1)
}
open func moveObjects(at indexes: IndexSet, to idx: Int) {
var removedObjects = [Any]()
for index in indexes.lazy.reversed() {
let obj = object(at: index)
removedObjects.append(obj)
removeObject(at: index)
}
for removedObject in removedObjects {
insert(removedObject, at: idx)
}
}
open func insert(_ objects: [Any], at indexes: IndexSet) {
for (indexLocation, index) in indexes.enumerated() {
let object = objects[indexLocation]
insert(object, at: index)
}
}
open func setObject(_ obj: Any, at idx: Int) {
let object = _SwiftValue.store(obj)
_storage.insert(object)
if idx == _orderedStorage.count {
_orderedStorage.append(object)
} else {
_orderedStorage[idx] = object
}
}
open func replaceObjects(in range: NSRange, with objects: UnsafePointer<AnyObject>!, count: Int) {
if let range = range.toCountableRange() {
let buffer = UnsafeBufferPointer(start: objects, count: count)
for (indexLocation, index) in range.indices.lazy.reversed().enumerated() {
let object = buffer[indexLocation]
replaceObject(at: index, with: object)
}
}
}
open func replaceObjects(at indexes: IndexSet, with objects: [Any]) {
for (indexLocation, index) in indexes.enumerated() {
let object = objects[indexLocation]
replaceObject(at: index, with: object)
}
}
open func removeObjects(in range: NSRange) {
if let range = range.toCountableRange() {
for index in range.indices.lazy.reversed() {
removeObject(at: index)
}
}
}
open func removeObjects(at indexes: IndexSet) {
for index in indexes.lazy.reversed() {
removeObject(at: index)
}
}
public func removeAllObjects() {
_storage.removeAll()
_orderedStorage.removeAll()
}
open func remove(_ val: Any) {
let object = _SwiftValue.store(val)
_storage.remove(object)
_orderedStorage.remove(at: index(of: val))
}
open func removeObjects(in array: [Any]) {
array.forEach(remove)
}
open func intersect(_ other: NSOrderedSet) {
for item in self where !other.contains(item) {
remove(item)
}
}
open func minus(_ other: NSOrderedSet) {
for item in other where contains(item) {
remove(item)
}
}
open func union(_ other: NSOrderedSet) {
other.forEach(add)
}
open func intersectSet(_ other: Set<AnyHashable>) {
for case let item as AnyHashable in self where !other.contains(item) {
remove(item)
}
}
open func minusSet(_ other: Set<AnyHashable>) {
for item in other where contains(item) {
remove(item)
}
}
open func unionSet(_ other: Set<AnyHashable>) {
other.forEach(add)
}
open func sort(comparator cmptr: (Any, Any) -> ComparisonResult) {
sortRange(NSMakeRange(0, count), options: [], usingComparator: cmptr)
}
open func sort(options opts: NSSortOptions = [], usingComparator cmptr: (Any, Any) -> ComparisonResult) {
sortRange(NSMakeRange(0, count), options: opts, usingComparator: cmptr)
}
open func sortRange(_ range: NSRange, options opts: NSSortOptions = [], usingComparator cmptr: (Any, Any) -> ComparisonResult) {
// The sort options are not available. We use the Array's sorting algorithm. It is not stable neither concurrent.
guard opts.isEmpty else {
NSUnimplemented()
}
let swiftRange = Range(range)!
_orderedStorage[swiftRange].sort { lhs, rhs in
return cmptr(_SwiftValue.fetch(nonOptional: lhs), _SwiftValue.fetch(nonOptional: rhs)) == .orderedAscending
}
}
}