Files
swift-mirror/stdlib/public/SDK/Foundation/NSFastEnumeration.swift
2017-01-06 16:41:22 +01:00

79 lines
2.4 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
//===----------------------------------------------------------------------===//
// Fast enumeration
//===----------------------------------------------------------------------===//
// NB: This is a class because fast enumeration passes around interior pointers
// to the enumeration state, so the state cannot be moved in memory. We will
// probably need to implement fast enumeration in the compiler as a primitive
// to implement it both correctly and efficiently.
final public class NSFastEnumerationIterator : IteratorProtocol {
var enumerable: NSFastEnumeration
var state: [NSFastEnumerationState]
var n: Int
var count: Int
/// Size of ObjectsBuffer, in ids.
static var STACK_BUF_SIZE: Int { return 4 }
var objects: [Unmanaged<AnyObject>?]
public func next() -> Any? {
if n == count {
// FIXME: Is this check necessary before refresh()?
if count == 0 { return nil }
refresh()
if count == 0 { return nil }
}
let next: Any = state[0].itemsPtr![n]!
n += 1
return next
}
func refresh() {
_sanityCheck(objects.count > 0)
n = 0
objects.withUnsafeMutableBufferPointer {
count = enumerable.countByEnumerating(
with: &state,
objects: AutoreleasingUnsafeMutablePointer($0.baseAddress!),
count: $0.count)
}
}
public init(_ enumerable: NSFastEnumeration) {
self.enumerable = enumerable
self.state = [ NSFastEnumerationState(
state: 0, itemsPtr: nil,
mutationsPtr: _fastEnumerationStorageMutationsPtr,
extra: (0, 0, 0, 0, 0)) ]
self.objects = Array(
repeating: nil, count: NSFastEnumerationIterator.STACK_BUF_SIZE)
self.n = -1
self.count = -1
}
}
extension NSEnumerator : Sequence {
/// Return an *iterator* over the *enumerator*.
///
/// - Complexity: O(1).
public func makeIterator() -> NSFastEnumerationIterator {
return NSFastEnumerationIterator(self)
}
}