//===----------------------------------------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// /// A type that provides subscript access to its elements. /// /// - Important: In most cases, it's best to ignore this protocol and use /// `CollectionType` instead, as it has a more complete interface. public protocol IndexableBase { // FIXME(ABI)(compiler limitation): there is no reason for this protocol // to exist apart from missing compiler features that we emulate with it. // // This protocol is almost an implementation detail of the standard // library; it is used to deduce things like the `SubSequence` and // `Iterator` type from a minimal collection, but it is also used in // exposed places like as a constraint on `IndexingIterator`. /// A type that represents a valid position in the collection. /// /// Valid indices consist of the position of every element and a /// "past the end" position that's not valid for use as a subscript. associatedtype Index : Comparable /// The position of the first element in a non-empty collection. /// /// In an empty collection, `startIndex == endIndex`. /// /// - Complexity: O(1) var startIndex: Index { get } /// The collection's "past the end" position. /// /// `endIndex` is not a valid argument to `subscript`, and is always /// reachable from `startIndex` by zero or more applications of /// `successor()`. /// /// - Complexity: O(1) var endIndex: Index { get } // The declaration of _Element and subscript here is a trick used to // break a cyclic conformance/deduction that Swift can't handle. We // need something other than a Collection.Iterator.Element that can // be used as IndexingIterator's Element. Here we arrange for // the Collection itself to have an Element type that's deducible from // its subscript. Ideally we'd like to constrain this Element to be the same // as Collection.Iterator.Element (see below), but we have no way of // expressing it today. associatedtype _Element /// Returns the element at the given `position`. /// /// - Complexity: O(1) subscript(position: Index) -> _Element { get } // WORKAROUND: rdar://25214066 associatedtype SubSequence subscript(bounds: Range) -> SubSequence { get } /// Performs a range check in O(1), or a no-op when a range check is not /// implementable in O(1). /// /// The range check, if performed, is equivalent to: /// /// precondition(bounds.contains(index)) /// /// Use this function to perform a cheap range check for QoI purposes when /// memory safety is not a concern. Do not rely on this range check for /// memory safety. /// /// The default implementation for forward and bidirectional indices is a /// no-op. The default implementation for random access indices performs a /// range check. /// /// - Complexity: O(1). func _failEarlyRangeCheck(index: Index, bounds: Range) /// Performs a range check in O(1), or a no-op when a range check is not /// implementable in O(1). /// /// The range check, if performed, is equivalent to: /// /// precondition( /// bounds.contains(range.lowerBound) || /// range.lowerBound == bounds.upperBound) /// precondition( /// bounds.contains(range.upperBound) || /// range.upperBound == bounds.upperBound) /// /// Use this function to perform a cheap range check for QoI purposes when /// memory safety is not a concern. Do not rely on this range check for /// memory safety. /// /// The default implementation for forward and bidirectional indices is a /// no-op. The default implementation for random access indices performs a /// range check. /// /// - Complexity: O(1). func _failEarlyRangeCheck(range: Range, bounds: Range) /// Returns the next consecutive `Index` in a discrete sequence of /// `Index` values. /// /// - Precondition: `i` has a well-defined successor. @warn_unused_result func successor(of i: Index) -> Index func successor(updating i: inout Index) } public protocol Indexable : IndexableBase { /// A type that can represent the number of steps between pairs of /// `Index` values where one value is reachable from the other. /// /// Reachability is defined by the ability to produce one value from /// the other via zero or more applications of `successor(of: i)`. associatedtype IndexDistance : SignedInteger = Int @warn_unused_result func advance(i: Index, by n: IndexDistance) -> Index @warn_unused_result func advance(i: Index, by n: IndexDistance, limit: Index) -> Index @warn_unused_result func distance(from start: Index, to end: Index) -> IndexDistance } /// The iterator used for collections that don't specify one. public struct IndexingIterator< Elements : IndexableBase // FIXME(compiler limitation): // Elements : Collection > : IteratorProtocol, Sequence { /// Create an *iterator* over the given collection. public /// @testable init(_elements: Elements) { self._elements = _elements self._position = _elements.startIndex } /// Advance to the next element and return it, or `nil` if no next /// element exists. /// /// - Precondition: No preceding call to `self.next()` has returned `nil`. public mutating func next() -> Elements._Element? { if _position == _elements.endIndex { return nil } let element = _elements[_position] _elements.successor(updating: &_position) return element } internal let _elements: Elements internal var _position: Elements.Index } /// A multi-pass sequence with addressable positions. /// /// Positions are represented by an associated `Index` type. Whereas /// an arbitrary sequence may be consumed as it is traversed, a /// collection is multi-pass: any element may be revisited merely by /// saving its index. /// /// The sequence view of the elements is identical to the collection /// view. In other words, the following code binds the same series of /// values to `x` as does `for x in self {}`: /// /// for i in startIndex.. // FIXME: Needed here so that the `Iterator` is properly deduced from // a custom `makeIterator()` function. Otherwise we get an // `IndexingIterator`. func makeIterator() -> Iterator /// A `Sequence` that can represent a contiguous subrange of `self`'s /// elements. /// /// - Note: This associated type appears as a requirement in /// `Sequence`, but is restated here with stricter /// constraints: in a `Collection`, the `SubSequence` should /// also be a `Collection`. associatedtype SubSequence : IndexableBase, Sequence = Slice // FIXME(compiler limitation): // associatedtype SubSequence : Collection // where // Iterator.Element == SubSequence.Iterator.Element, // SubSequence.Index == Index, // SubSequence.SubSequence == SubSequence // // ( Implement recursive protocol // constraints) // // These constraints allow processing collections in generic code by // repeatedly slicing them in a loop. /// Returns the element at the given `position`. subscript(position: Index) -> Iterator.Element { get } /// Returns a collection representing a contiguous sub-range of /// `self`'s elements. /// /// - Complexity: O(1) subscript(bounds: Range) -> SubSequence { get } /// A type for the collection of indices for this collection. /// /// An instance of `Indices` can hold a strong reference to the collection /// itself, causing the collection to be non-uniquely referenced. If you /// need to mutate the collection while iterating over its indices, use the /// `next()` method to produce indices instead. associatedtype Indices : IndexableBase, Sequence = DefaultIndices // FIXME(compiler limitation): // associatedtype Indices : Collection // where // Indices.Iterator.Element == Index, // Indices.Index == Index, // Indices.SubSequence == Indices // = DefaultIndices /// The collection of indices of this collection that can be used for /// subscripting. var indices: Indices { get } /// Returns `self[startIndex.. SubSequence /// Returns `self[start.. SubSequence /// Returns `prefix(upTo: position.successor())` /// /// - Complexity: O(1) @warn_unused_result func prefix(through position: Index) -> SubSequence /// Returns `true` iff `self` is empty. var isEmpty: Bool { get } /// Returns the number of elements. /// /// - Complexity: O(1) if `Index` conforms to `RandomAccessIndex`; /// O(N) otherwise. var count: IndexDistance { get } // The following requirement enables dispatching for indexOf when // the element type is Equatable. /// Returns `Optional(Optional(index))` if an element was found; /// `nil` otherwise. /// /// - Complexity: O(N). @warn_unused_result func _customIndexOfEquatableElement(element: Iterator.Element) -> Index?? /// Returns the first element of `self`, or `nil` if `self` is empty. var first: Iterator.Element? { get } /// Returns the result of advancing `i` by `n` positions. /// /// - Returns: /// - If `n > 0`, returns a new index applying `next` on `i` `n` /// times. /// - If `n < 0`, returns a new index by applying `previous` on `i` /// `-n` times. /// - Otherwise, `i` unmodified. /// /// - Precondition: `n >= 0` if only conforming to `Collection` /// /// - Complexity: /// - O(1) if conforming to `RandomAccessCollection` /// - O(`abs(n)`) otherwise @warn_unused_result func advance(i: Index, by n: IndexDistance) -> Index /// Returns the result of advancing `self` by `n` positions, or until it /// equals `limit`. /// /// - Returns: /// - If `n > 0`, returns `i` modified by applying `next` on `i` `n` /// times but not past `limit`. /// - If `n < 0`, returns `i` modified by applying `previous` on `i` /// `-n` times but not past `limit`. /// - Otherwise, return `i` unmodified. /// /// - Precondition: `n >= 0` if only conforming to `Collection`. /// /// - Complexity: /// - O(1) if conforming to `RandomAccessCollection` /// - O(`abs(n)`) otherwise @warn_unused_result func advance(i: Index, by n: IndexDistance, limit: Index) -> Index /// Measure the distance between `start` and `end` indexes. /// /// - Precondition: /// - `start` and `end` are part of the same sequence when conforming to /// `RandomAccessSequenceType`. /// - `end` is reachable from `start` by incrementation otherwise. /// /// - Complexity: /// - O(1) if conforming to `RandomAccessIndex` /// - O(`n`) otherwise, where `n` is the function's result. @warn_unused_result func distance(from start: Index, to end: Index) -> IndexDistance } /// Default implementation for forward collections. extension Indexable { @inline(__always) public func successor(updating i: inout Index) { // FIXME: swift-3-indexing-model: tests. i = successor(of: i) } public func _failEarlyRangeCheck(index: Index, bounds: Range) { // FIXME: swift-3-indexing-model: tests. _precondition( bounds.lowerBound <= index, "index is out of bounds: index designates a position before bounds.lowerBound") _precondition( index < bounds.upperBound, "index is out of bounds: index designates the bounds.upperBound position or a position after it") } public func _failEarlyRangeCheck(range: Range, bounds: Range) { // FIXME: swift-3-indexing-model: tests. _precondition( bounds.lowerBound <= range.lowerBound, "range.lowerBound is out of bounds: index designates a position before bounds.lowerBound") _precondition( bounds.lowerBound <= range.upperBound, "range.upperBound is out of bounds: index designates a position before bounds.lowerBound") _precondition( range.lowerBound <= bounds.upperBound, "range.lowerBound is out of bounds: index designates a position after bounds.upperBound") _precondition( range.upperBound <= bounds.upperBound, "range.lowerBound is out of bounds: index designates a position after bounds.upperBound") } @warn_unused_result public func advance(i: Index, by n: IndexDistance) -> Index { // FIXME: swift-3-indexing-model: tests. return self._advanceForward(i, by: n) } @warn_unused_result public func advance(i: Index, by n: IndexDistance, limit: Index) -> Index { // FIXME: swift-3-indexing-model: tests. return self._advanceForward(i, by: n, limit: limit) } @warn_unused_result public func distance(from start: Index, to end: Index) -> IndexDistance { // FIXME: swift-3-indexing-model: tests. _precondition(start <= end, "Only BidirectionalCollections can have end come before start") var start = start var count: IndexDistance = 0 while start != end { count = count + 1 successor(updating: &start) } return count } /// Do not use this method directly; call advanced(by: n) instead. @inline(__always) @warn_unused_result internal func _advanceForward(i: Index, by n: IndexDistance) -> Index { _precondition(n >= 0, "Only BidirectionalCollections can be advanced by a negative amount") var i = i for _ in 0.. Index { _precondition(n >= 0, "Only BidirectionalCollections can be advanced by a negative amount") var i = i for _ in 0.. Index { // FIXME: swift-3-indexing-model: tests. _failEarlyRangeCheck(i, bounds: startIndex.. Index { _precondition(n >= 0, "Only BidirectionalCollections can be advanced by a negative amount") // FIXME: swift-3-indexing-model: range check i // FIXME: swift-3-indexing-model - error: cannot invoke 'advanced' with an argument list of type '(by: Self.IndexDistance)' return i.advanced(by: n) } @warn_unused_result public func advance(i: Index, by n: IndexDistance, limit: Index) -> Index { _precondition(n >= 0, "Only BidirectionalCollections can be advanced by a negative amount") // FIXME: swift-3-indexing-model: range check i // FIXME: swift-3-indexing-model - error: cannot invoke 'advanced' with an argument list of type '(by: Self.IndexDistance)' let i = i.advanced(by: n) if (i >= limit) { return limit } return i } @warn_unused_result public func distance(from start: Index, to end: Index) -> IndexDistance { _precondition(start <= end, "Only BidirectionalCollections can have end come before start") // FIXME: swift-3-indexing-model: range check supplied start and end? // FIXME: swift-3-indexing-model - error: cannot invoke 'distance' with an argument list of type '(to: Self.Index)' return start.distance(to: end) } */ } /// Supply the default `makeIterator()` method for `Collection` models /// that accept the default associated `Iterator`, /// `IndexingIterator`. extension Collection where Iterator == IndexingIterator { public func makeIterator() -> IndexingIterator { return IndexingIterator(_elements: self) } } /// Supply the default "slicing" `subscript` for `Collection` models /// that accept the default associated `SubSequence`, `Slice`. extension Collection where SubSequence == Slice { public subscript(bounds: Range) -> Slice { _failEarlyRangeCheck(bounds, bounds: startIndex.. Iterator.Element? { guard !isEmpty else { return nil } let element = first! self = self[successor(of: startIndex).. Index?? { return nil } } //===----------------------------------------------------------------------===// // Default implementations for Collection //===----------------------------------------------------------------------===// extension Collection { // TODO: swift-3-indexing-model - review the following /// Returns an `Array` containing the results of mapping `transform` /// over `self`. /// /// - Complexity: O(N). @warn_unused_result public func map( @noescape transform: (Iterator.Element) throws -> T ) rethrows -> [T] { let count: Int = numericCast(self.count) if count == 0 { return [] } var result = ContiguousArray() result.reserveCapacity(count) var i = self.startIndex for _ in 0..= 0` /// - Complexity: O(`n`) @warn_unused_result public func dropFirst(n: Int) -> SubSequence { _precondition(n >= 0, "Can't drop a negative number of elements from a collection") let start = advance(startIndex, by: numericCast(n), limit: endIndex) return self[start..= 0` /// - Complexity: O(`self.count`) @warn_unused_result public func dropLast(n: Int) -> SubSequence { _precondition( n >= 0, "Can't drop a negative number of elements from a collection") let amount = Swift.max(0, numericCast(count) - n) let end = advance(startIndex, by: numericCast(amount), limit: endIndex) return self[startIndex..= 0` /// - Complexity: O(`maxLength`) @warn_unused_result public func prefix(maxLength: Int) -> SubSequence { _precondition( maxLength >= 0, "Can't take a prefix of negative length from a collection") let end = advance(startIndex, by: numericCast(maxLength), limit: endIndex) return self[startIndex..= 0` /// - Complexity: O(`self.count`) @warn_unused_result public func suffix(maxLength: Int) -> SubSequence { _precondition( maxLength >= 0, "Can't take a suffix of negative length from a collection") let amount = Swift.max(0, numericCast(count) - maxLength) let start = advance(startIndex, by: numericCast(amount), limit: endIndex) return self[start.. SubSequence { return self[startIndex.. SubSequence { return self[start.. SubSequence { return prefix(upTo: successor(of: position)) } // TODO: swift-3-indexing-model - review the following /// Returns the maximal `SubSequence`s of `self`, in order, that /// don't contain elements satisfying the predicate `isSeparator`. /// /// - Parameter maxSplits: The maximum number of `SubSequence`s to /// return, minus 1. /// If `maxSplits + 1` `SubSequence`s are returned, the last one is /// a suffix of `self` containing *all* the elements of `self` following the /// last split point. /// The default value is `Int.max`. /// /// - Parameter omittingEmptySubsequences: If `false`, an empty `SubSequence` /// is produced in the result for each pair of consecutive elements /// satisfying `isSeparator`. /// The default value is `true`. /// /// - Precondition: `maxSplits >= 0` @warn_unused_result public func split( maxSplits maxSplits: Int = Int.max, omittingEmptySubsequences: Bool = true, @noescape isSeparator: (Iterator.Element) throws -> Bool ) rethrows -> [SubSequence] { _precondition(maxSplits >= 0, "Must take zero or more splits") var result: [SubSequence] = [] var subSequenceStart: Index = startIndex func appendSubsequence(end end: Index) -> Bool { if subSequenceStart == end && omittingEmptySubsequences { return false } result.append(self[subSequenceStart..= 0` @warn_unused_result public func split( separator separator: Iterator.Element, maxSplits: Int = Int.max, omittingEmptySubsequences: Bool = true ) -> [SubSequence] { return split( maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences, isSeparator: { $0 == separator }) } } // TODO: swift-3-indexing-model - review the following extension Collection where SubSequence == Self { /// Remove the element at `startIndex` and return it. /// /// - Complexity: O(1) /// - Precondition: `!self.isEmpty`. public mutating func removeFirst() -> Iterator.Element { _precondition(!isEmpty, "can't remove items from an empty collection") let element = first! self = self[successor(of: startIndex)..= 0 && self.count >= n`. public mutating func removeFirst(n: Int) { if n == 0 { return } _precondition(n >= 0, "number of elements to remove should be non-negative") _precondition(count >= numericCast(n), "can't remove more items from a collection than it contains") self = self[advance(startIndex, by: numericCast(n)).. ) -> UnsafeMutablePointer { let s = self._baseAddressIfContiguous if s != nil { let count = self.count ptr.initializeFrom(s, count: count) _fixLifetime(self._owner) return ptr + count } else { var p = ptr for x in self { p.initialize(with: x) p += 1 } return p } } } // TODO: swift-3-indexing-model - review the following extension Collection { public func _preprocessingPass(@noescape preprocess: () -> R) -> R? { return preprocess() } } @available(*, unavailable, message: "Bit enum has been deprecated. Please use Int instead.") public enum Bit {} @available(*, unavailable, renamed: "IndexingIterator") public struct IndexingGenerator {} @available(*, unavailable, renamed: "Collection") public typealias CollectionType = Collection extension Collection { @available(*, unavailable, renamed: "Iterator") public typealias Generator = Iterator @available(*, unavailable, renamed: "iterator") public func generate() -> Iterator { fatalError("unavailable function can't be called") } @available(*, unavailable, message: "Removed in Swift 3. Please use underestimatedCount property.") public func underestimateCount() -> Int { fatalError("unavailable function can't be called") } @available(*, unavailable, message: "Please use split(_:omittingEmptySubsequences:isSeparator:) instead") public func split( maxSplit: Int = Int.max, allowEmptySlices: Bool = false, @noescape isSeparator: (Iterator.Element) throws -> Bool ) rethrows -> [SubSequence] { fatalError("unavailable function can't be called") } } extension Collection where Iterator.Element : Equatable { @available(*, unavailable, message: "Please use split(separator:maxSplits:omittingEmptySubsequences:) instead") public func split( separator: Iterator.Element, maxSplit: Int = Int.max, allowEmptySlices: Bool = false ) -> [SubSequence] { fatalError("unavailable function can't be called") } } @available(*, unavailable, message: "PermutationGenerator has been removed in Swift 3") public struct PermutationGenerator {}