Files
swift-mirror/stdlib/public/core/Join.swift
Nate Cook 51251dc133 Convert imperative function summaries to present.
i.e., "Return ..." -> "Returns ..."
2016-02-12 04:20:39 -06:00

193 lines
5.5 KiB
Swift

//===--- Join.swift - Protocol and Algorithm for concatenation ------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
internal enum _JoinGeneratorState {
case Start
case GeneratingElements
case GeneratingSeparator
case End
}
/// A generator that presents the elements of the sequences generated
/// by `Base`, concatenated using a given separator.
public struct JoinGenerator<
Base : GeneratorType where Base.Element : SequenceType
> : GeneratorType {
/// Creates a generator that presents the elements of the sequences
/// generated by `base`, concatenated using `separator`.
///
/// - Complexity: O(`separator.count`).
public init<
Separator : SequenceType
where
Separator.Generator.Element == Base.Element.Generator.Element
>(base: Base, separator: Separator) {
self._base = base
self._separatorData = ContiguousArray(separator)
}
/// Advance to the next element and return it, or `nil` if no next
/// element exists.
public mutating func next() -> Base.Element.Generator.Element? {
repeat {
switch _state {
case .Start:
if let nextSubSequence = _base.next() {
_inner = nextSubSequence.generate()
_state = .GeneratingElements
} else {
_state = .End
return nil
}
case .GeneratingElements:
let result = _inner!.next()
if _fastPath(result != nil) {
return result
}
if _separatorData.isEmpty {
_inner = _base.next()?.generate()
if _inner == nil {
_state = .End
return nil
}
} else {
_inner = _base.next()?.generate()
if _inner == nil {
_state = .End
return nil
}
_separator = _separatorData.generate()
_state = .GeneratingSeparator
}
case .GeneratingSeparator:
let result = _separator!.next()
if _fastPath(result != nil) {
return result
}
_state = .GeneratingElements
case .End:
return nil
}
}
while true
}
internal var _base: Base
internal var _inner: Base.Element.Generator? = nil
internal var _separatorData: ContiguousArray<Base.Element.Generator.Element>
internal var _separator: ContiguousArray<Base.Element.Generator.Element>.Generator?
internal var _state: _JoinGeneratorState = .Start
}
/// A sequence that presents the elements of the `Base` sequences
/// concatenated using a given separator.
public struct JoinSequence<
Base : SequenceType where Base.Generator.Element : SequenceType
> : SequenceType {
/// Creates a sequence that presents the elements of `base` sequences
/// concatenated using `separator`.
///
/// - Complexity: O(`separator.count`).
public init<
Separator : SequenceType
where
Separator.Generator.Element ==
Base.Generator.Element.Generator.Element
>(base: Base, separator: Separator) {
self._base = base
self._separator = ContiguousArray(separator)
}
/// Returns a generator over the elements of this sequence.
///
/// - Complexity: O(1).
public func generate() -> JoinGenerator<Base.Generator> {
return JoinGenerator(
base: _base.generate(),
separator: _separator)
}
public func _copyToNativeArrayBuffer()
-> _ContiguousArrayBuffer<Base.Generator.Element.Generator.Element> {
var result = ContiguousArray<Generator.Element>()
let separatorSize: Int = numericCast(_separator.count)
let reservation = _base._preprocessingPass {
() -> Int in
var r = 0
for chunk in _base {
r += separatorSize + chunk.underestimateCount()
}
return r - separatorSize
}
if let n = reservation {
result.reserveCapacity(numericCast(n))
}
if separatorSize != 0 {
var gen = _base.generate()
if let first = gen.next() {
result.appendContentsOf(first)
while let next = gen.next() {
result.appendContentsOf(_separator)
result.appendContentsOf(next)
}
}
} else {
for x in _base {
result.appendContentsOf(x)
}
}
return result._buffer
}
internal var _base: Base
internal var _separator:
ContiguousArray<Base.Generator.Element.Generator.Element>
}
extension SequenceType where Generator.Element : SequenceType {
/// Returns a view, whose elements are the result of interposing a given
/// `separator` between the elements of the sequence `self`.
///
/// For example,
/// `[[1, 2, 3], [4, 5, 6], [7, 8, 9]].joinWithSeparator([-1, -2])`
/// yields `[1, 2, 3, -1, -2, 4, 5, 6, -1, -2, 7, 8, 9]`.
@warn_unused_result
public func joinWithSeparator<
Separator : SequenceType
where
Separator.Generator.Element == Generator.Element.Generator.Element
>(separator: Separator) -> JoinSequence<Self> {
return JoinSequence(base: self, separator: separator)
}
}
@available(*, unavailable, message="call the 'joinWithSeparator()' method on the sequence of elements")
public func join<
C : RangeReplaceableCollectionType, S : SequenceType
where S.Generator.Element == C
>(
separator: C, _ elements: S
) -> C {
fatalError("unavailable function can't be called")
}