//===--- Concatenate.swift.gyb - Concatenate sequence elements-*- swift -*-===// // // 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 // //===----------------------------------------------------------------------===// // Unfortunately it is required to make some types in this file public // (@testable) just because _lazyConcatenate is called from the // stdlib unit tests. /// The `GeneratorType` used by `_ConcatenateSequenceView`, /// `_ForwardConcatenateView`, and `_BidirectionalConcatenateView`. /// Generates a sequence of the elements of the elements of its /// argument. public // @testable struct _ConcatenateSequenceGenerator< Outer: GeneratorType where Outer.Element : SequenceType >: GeneratorType, SequenceType { /// Construct around a generator for the outer sequence init(_ outer: Outer) { self._outer = outer } /// 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 // @testable mutating func next() -> Outer.Element.Generator.Element? { do { if _fastPath(_inner != nil) { let ret = _inner!.next() if _fastPath(ret != nil) { return ret } } let s = _outer.next() if _slowPath(s == nil) { return nil } _inner = s!.generate() } while true } /// `_ConcatenateSequenceGenerator` is also a `SequenceType`, so it /// `generate`\ 's a copy of itself public // @testable func generate() -> _ConcatenateSequenceGenerator { return self } var _outer: Outer var _inner: Outer.Element.Generator? = nil } //===--- Sequences --------------------------------------------------------===// /// A `SequenceType` whose elements consist of those *contained in* in /// the elements of its `Base` sequence. struct _ConcatenateSequenceView< Base: SequenceType where Base.Generator.Element: SequenceType > : SequenceType { /// Present the elmeents of the elements of `base` init(_ base: Base) { self._base = base } /// Return a *generator* over the elements of this *sequence*. /// /// Complexity: O(1) func generate() -> _ConcatenateSequenceGenerator { return _ConcatenateSequenceGenerator(_base.generate()) } var _base: Base } /// Return a sequence that is a concatenation of the elements of /// `source`\ 's elements func _lazyConcatenate< S:SequenceType where S.Generator.Element: SequenceType >(source: S) -> LazySequence<_ConcatenateSequenceView> { return LazySequence(_ConcatenateSequenceView(source)) } /// Return an `Array` containing the results of mapping `transform` /// over `source`. func _concatenate< S:SequenceType where S.Generator.Element: SequenceType >( source: S ) -> [S.Generator.Element.Generator.Element] { return _lazyConcatenate(source).array } //===--- Collections ------------------------------------------------------===// % for traversal in ('Forward', 'Bidirectional'): % View = '_%sConcatenateView' % traversal % Self = '_Lazy%sCollection' % traversal % Index = '_Concatenate%sIndex' % traversal % IndexProtocol = '%sIndexType' % traversal /// A wrapper for a `${IndexProtocol}` for a collection of /// collections, that can be used to index the inner elements. public // @testable struct ${Index}< C: CollectionType where C.Index : ${IndexProtocol}, C.Generator.Element: CollectionType, C.Generator.Element.Index : ${IndexProtocol} > : ${IndexProtocol} { typealias Outer = C.Index typealias Inner = C.Generator.Element.Index var _data: C var _outer: Outer var _inner: Inner? init(_ data: C, _ outer: Outer, _ inner: Inner?) { self._data = data self._outer = outer self._inner = inner } static func adjustForward( data: C, var _ outer: Outer, _ inner: Inner? ) -> ${Index} { if _fastPath(inner != nil) { if _fastPath(inner! != data[outer].endIndex) { return ${Index}(data, outer, inner) } ++outer } for ; outer != data.endIndex ; ++outer { if !isEmpty(data[outer]) { return ${Index}(data, outer, data[outer].startIndex) } } return ${Index}(data, outer, nil) } /// Returns the next consecutive value after `self`. /// /// Requires: the next value is representable. public // @testable func successor() -> ${Index} { return ${Index}.adjustForward(_data, _outer, _inner!.successor()) } % if traversal == 'Bidirectional': /// Returns the previous consecutive value before `self`. /// /// Requires: the previous value is representable. public // @testable func predecessor() -> ${Index} { var outer = _outer var inner = _inner while inner == nil || inner! == _data[outer].startIndex { inner = _data[--outer].endIndex } return ${Index}(_data, outer, inner!.predecessor()) } % end } public // @testable func == (lhs: ${Index}, rhs: ${Index}) -> Bool { return lhs._outer == rhs._outer && lhs._inner == rhs._inner } /// The lazy `CollectionType` returned by `lazyConcatenate(c)` where `c` is a /// `CollectionType` having an `Index` conforming to `${IndexProtocol}` public // @testable struct ${View}< C: CollectionType where C.Index: ${IndexProtocol}, C.Generator.Element: CollectionType, C.Generator.Element.Index : ${IndexProtocol} > : 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. typealias Index = ${Index} init(_ _base: C) { self._base = _base } /// Return a *generator* over the elements of this *sequence*. /// /// Complexity: O(1) public // @testable func generate() -> _ConcatenateSequenceGenerator { return _ConcatenateSequenceGenerator(_base.generate()) } /// The position of the first element in a non-empty collection. /// /// Identical to `endIndex` in an empty collection. public // @testable var startIndex: Index { return ${Index}.adjustForward(_base, _base.startIndex, nil) } /// 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 // @testable var endIndex: Index { return ${Index}(_base, _base.endIndex, nil) } /// Access the element at `position`. /// /// Requires: `position` is a valid position in `self` and /// `position != endIndex`. public // @testable subscript(position: Index) -> C.Generator.Element.Generator.Element { return _base[position._outer][position._inner!] } var _base: C } /// Return a collection that is a concatenation of the elements of /// `source`\ 's elements public // @testable func _lazyConcatenate< C: CollectionType where C.Index: ${IndexProtocol}, C.Generator.Element: CollectionType, C.Generator.Element.Index : ${IndexProtocol} >(source: C) -> Lazy${traversal}Collection<${View}> { return Lazy${traversal}Collection(${View}(source)) } % end /// Return an `Array` containing the results of mapping `transform` /// over `source`. func _concatenate< C : CollectionType where C.Generator.Element : CollectionType >( source: C ) -> [C.Generator.Element.Generator.Element] { return _lazyConcatenate(source).array } // ${'Local Variables'}: // eval: (read-only-mode 1) // End: