mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
250 lines
7.6 KiB
Plaintext
250 lines
7.6 KiB
Plaintext
//===--- Flatten.swift.gyb ------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 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 flattened view of a base generator-of-sequences.
|
|
///
|
|
/// The elements generated are the concatenation of those in each
|
|
/// sequence generated by the base generator.
|
|
///
|
|
/// - Note: this is the `GeneratorType` used by `FlattenSequence`,
|
|
/// `FlattenCollection`, and `BidirectionalFlattenCollection`.
|
|
public struct _prext_FlattenGenerator<
|
|
Base : GeneratorType where Base.Element : SequenceType
|
|
> : GeneratorType, SequenceType {
|
|
|
|
/// Construct around a generator for the `base` sequence.
|
|
public init(_ base: Base) {
|
|
self._base = base
|
|
}
|
|
|
|
/// Advance to the next element and return it, or `nil` if no next
|
|
/// element exists.
|
|
///
|
|
/// - Requires: `next()` has not been applied to a copy of `self`
|
|
/// since the copy was made, and no preceding call to `self.next()`
|
|
/// has returned `nil`.
|
|
public mutating func next() -> Base.Element.Generator.Element? {
|
|
repeat {
|
|
if _fastPath(_inner != nil) {
|
|
let ret = _inner!.next()
|
|
if _fastPath(ret != nil) {
|
|
return ret
|
|
}
|
|
}
|
|
let s = _base.next()
|
|
if _slowPath(s == nil) {
|
|
return nil
|
|
}
|
|
_inner = s!.generate()
|
|
}
|
|
while true
|
|
}
|
|
|
|
internal var _base: Base
|
|
internal var _inner: Base.Element.Generator? = nil
|
|
}
|
|
|
|
/// A flattened view of a base sequence-of-sequences.
|
|
///
|
|
/// The elements of this view are a concatenation of the elements of
|
|
/// each sequence in the base.
|
|
public struct _prext_FlattenSequence<
|
|
Base : SequenceType where Base.Generator.Element : SequenceType
|
|
> : SequenceType {
|
|
|
|
/// Creates a concatenation of the elements of the elements of `base`.
|
|
///
|
|
/// - Complexity: O(1)
|
|
public init(_ base: Base) {
|
|
self._base = base
|
|
}
|
|
|
|
/// Return a *generator* over the elements of this *sequence*.
|
|
///
|
|
/// - Complexity: O(1).
|
|
public func generate() -> _prext_FlattenGenerator<Base.Generator> {
|
|
return _prext_FlattenGenerator(_base.generate())
|
|
}
|
|
|
|
internal var _base: Base
|
|
}
|
|
|
|
extension SequenceType where Generator.Element : SequenceType {
|
|
/// A concatenation of the elements of `self`.
|
|
public var _prext_flatten: _prext_FlattenSequence<Self> {
|
|
return _prext_FlattenSequence(self)
|
|
}
|
|
}
|
|
|
|
extension _prext_LazySequenceType
|
|
where Elements.Generator.Element == Generator.Element,
|
|
Generator.Element : SequenceType {
|
|
/// A concatenation of the elements of `self`.
|
|
public var _prext_flatten: _prext_LazySequence<
|
|
_prext_FlattenSequence<Elements>
|
|
> {
|
|
return _prext_FlattenSequence(elements)._prext_lazy
|
|
}
|
|
}
|
|
|
|
% for traversal in ('Forward', 'Bidirectional'):
|
|
% t = '' if traversal == 'Forward' else traversal
|
|
% Collection = '_prext_Flatten%sCollection' % t
|
|
% constraints = 'Base.Generator.Element : CollectionType'
|
|
% if traversal == 'Bidirectional':
|
|
% constraints += ''' , Base.Index : BidirectionalIndexType,
|
|
% Base.Generator.Element.Index : BidirectionalIndexType'''
|
|
% Index = Collection + 'Index'
|
|
public struct ${Index}<
|
|
Base: CollectionType where ${constraints}
|
|
> : ${traversal}IndexType {
|
|
/// Returns the next consecutive value after `self`.
|
|
///
|
|
/// - Requires: the next value is representable.
|
|
public func successor() -> ${Index} {
|
|
let nextInner = _inner!.successor()
|
|
if _fastPath(nextInner != _base[_outer].endIndex) {
|
|
return ${Index}(_base, _outer, nextInner)
|
|
}
|
|
let tailIndices = _outer.successor()..<_base.endIndex
|
|
if let nextOuter = tailIndices.indexOf({ !_base[$0].isEmpty }) {
|
|
return ${Index}(
|
|
_base, nextOuter, _base[nextOuter].startIndex)
|
|
}
|
|
return ${Index}(_base, _base.endIndex, nil)
|
|
}
|
|
|
|
% if traversal == 'Bidirectional':
|
|
/// Returns the previous consecutive value before `self`.
|
|
///
|
|
/// - Requires: The previous value is representable.
|
|
public func predecessor() -> ${Index} {
|
|
var outer = _outer
|
|
var inner = _inner
|
|
|
|
while inner == nil || inner! == _base[outer].startIndex {
|
|
inner = _base[--outer].endIndex
|
|
}
|
|
return ${Index}(_base, outer, inner!.predecessor())
|
|
}
|
|
% end
|
|
|
|
/// Construct the `startIndex` for a flattened view of `base`.
|
|
internal init(_startIndexOfFlattened base: Base) {
|
|
if let outer = base.indexOf({ !$0.isEmpty }) {
|
|
self._base = base
|
|
self._outer = outer
|
|
self._inner = base[outer].startIndex
|
|
}
|
|
else {
|
|
self = ${Index}(_endIndexOfFlattened: base)
|
|
}
|
|
}
|
|
|
|
/// Construct the `endIndex` for a flattened view of `base`.
|
|
internal init(_endIndexOfFlattened _base: Base) {
|
|
self._base = _base
|
|
self._outer = _base.endIndex
|
|
self._inner = nil
|
|
}
|
|
|
|
internal init(
|
|
_ _base: Base,
|
|
_ outer: Base.Index,
|
|
_ inner: Base.Generator.Element.Index?) {
|
|
self._base = _base
|
|
self._outer = outer
|
|
self._inner = inner
|
|
}
|
|
|
|
internal let _base: Base
|
|
internal let _outer: Base.Index
|
|
internal let _inner: Base.Generator.Element.Index?
|
|
}
|
|
|
|
public func == <Base> (lhs: ${Index}<Base>, rhs: ${Index}<Base>) -> Bool {
|
|
return lhs._outer == rhs._outer && lhs._inner == rhs._inner
|
|
}
|
|
|
|
/// A flattened view of a base collection-of-collections.
|
|
///
|
|
/// The elements of this view are a concatenation of the elements of
|
|
/// each collection in the base.
|
|
public struct ${Collection}<
|
|
Base: CollectionType where ${constraints}
|
|
> : CollectionType {
|
|
/// 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.
|
|
public typealias Index = ${Index}<Base>
|
|
|
|
/// Creates a flattened view of `base`.
|
|
public init(_ base: Base) {
|
|
self._base = base
|
|
}
|
|
|
|
/// Return a *generator* over the elements of this *sequence*.
|
|
///
|
|
/// - Complexity: O(1).
|
|
public func generate() -> _prext_FlattenGenerator<Base.Generator> {
|
|
return _prext_FlattenGenerator(_base.generate())
|
|
}
|
|
|
|
/// The position of the first element in a non-empty collection.
|
|
///
|
|
/// In an empty collection, `startIndex == endIndex`.
|
|
public var startIndex: Index {
|
|
return ${Index}(_startIndexOfFlattened: _base)
|
|
}
|
|
|
|
/// 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()`.
|
|
public var endIndex: Index {
|
|
return ${Index}(_endIndexOfFlattened: _base)
|
|
}
|
|
|
|
/// Access the element at `position`.
|
|
///
|
|
/// - Requires: `position` is a valid position in `self` and
|
|
/// `position != endIndex`.
|
|
public subscript(
|
|
position: Index
|
|
) -> Base.Generator.Element.Generator.Element {
|
|
return _base[position._outer][position._inner!]
|
|
}
|
|
|
|
internal var _base: Base
|
|
}
|
|
|
|
extension CollectionType where ${constraints.replace('Base.', '')} {
|
|
/// A concatenation of the elements of `self`.
|
|
public var _prext_flatten: ${Collection}<Self> {
|
|
return ${Collection}(self)
|
|
}
|
|
}
|
|
|
|
extension _prext_LazyCollectionType
|
|
where ${constraints.replace('Base.', '')},
|
|
${constraints.replace('Base.', 'Elements.')},
|
|
Generator.Element == Elements.Generator.Element {
|
|
/// A concatenation of the elements of `self`.
|
|
public var _prext_flatten: _prext_LazyCollection<${Collection}<Elements>> {
|
|
return ${Collection}(elements)._prext_lazy
|
|
}
|
|
}
|
|
|
|
% end
|