Files
swift-mirror/stdlib/public/Darwin/Foundation/NSFastEnumeration.swift
Saleem Abdulrasool 41d9c2cc59 stdlib: restructure for OS family layout of SDK overlay
The SDK directory is now confusing as the Windows target also has a SDK
overlay.  In order to make this more uniform, move the SDK directory to
Darwin which covers the fact that this covers the XNU family of OSes.
The Windows directory contains the SDK overlay for the Windows target.
2018-12-06 11:32:05 -08:00

97 lines
4.7 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
/// A dummy value to be used as the target for `mutationsPtr` in fast enumeration implementations.
fileprivate var _fastEnumerationMutationsTarget: CUnsignedLong = 0
/// A dummy pointer to be used as `mutationsPtr` in fast enumeration implementations.
fileprivate let _fastEnumerationMutationsPtr = UnsafeMutablePointer<CUnsignedLong>(&_fastEnumerationMutationsTarget)
//===----------------------------------------------------------------------===//
// Fast enumeration
//===----------------------------------------------------------------------===//
public struct NSFastEnumerationIterator : IteratorProtocol {
var enumerable: NSFastEnumeration
var objects: (Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?, Unmanaged<AnyObject>?) = (nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
var state = NSFastEnumerationState(state: 0, itemsPtr: nil, mutationsPtr: _fastEnumerationMutationsPtr, extra: (0, 0, 0, 0, 0))
var index = 0
var count = 0
var useObjectsBuffer = false
public init(_ enumerable: NSFastEnumeration) {
self.enumerable = enumerable
}
public mutating func next() -> Any? {
if index + 1 > count {
index = 0
// ensure NO ivars of self are actually captured
let enumeratedObject = enumerable
var localState = state
var localObjects = objects
(count, useObjectsBuffer) = withUnsafeMutablePointer(to: &localObjects) {
let buffer = AutoreleasingUnsafeMutablePointer<AnyObject?>($0)
return withUnsafeMutablePointer(to: &localState) { (statePtr: UnsafeMutablePointer<NSFastEnumerationState>) -> (Int, Bool) in
let result = enumeratedObject.countByEnumerating(with: statePtr, objects: buffer, count: 16)
if statePtr.pointee.itemsPtr == buffer {
// Most cocoa classes will emit their own inner pointer buffers instead of traversing this path. Notable exceptions include NSDictionary and NSSet
return (result, true)
} else {
// this is the common case for things like NSArray
return (result, false)
}
}
}
state = localState // restore the state value
objects = localObjects // copy the object pointers back to the self storage
if count == 0 { return nil }
}
defer { index += 1 }
if !useObjectsBuffer {
return state.itemsPtr![index]
} else {
switch index {
case 0: return objects.0!.takeUnretainedValue()
case 1: return objects.1!.takeUnretainedValue()
case 2: return objects.2!.takeUnretainedValue()
case 3: return objects.3!.takeUnretainedValue()
case 4: return objects.4!.takeUnretainedValue()
case 5: return objects.5!.takeUnretainedValue()
case 6: return objects.6!.takeUnretainedValue()
case 7: return objects.7!.takeUnretainedValue()
case 8: return objects.8!.takeUnretainedValue()
case 9: return objects.9!.takeUnretainedValue()
case 10: return objects.10!.takeUnretainedValue()
case 11: return objects.11!.takeUnretainedValue()
case 12: return objects.12!.takeUnretainedValue()
case 13: return objects.13!.takeUnretainedValue()
case 14: return objects.14!.takeUnretainedValue()
case 15: return objects.15!.takeUnretainedValue()
default: fatalError("Access beyond storage buffer")
}
}
}
}
extension NSEnumerator : Sequence {
/// Return an *iterator* over the *enumerator*.
///
/// - Complexity: O(1).
public func makeIterator() -> NSFastEnumerationIterator {
return NSFastEnumerationIterator(self)
}
}