Files
swift-mirror/stdlib/core/Arrays.swift.gyb
Dave Abrahams 66d2ba43c6 [stdlib] underscore APIs made visible by r22212
That commit made a protocol public.  The protocol was underscored but
some of its APIs were not, and those became unintentionally publicly
visible.  This commit corrects that problem.  Since Builtin.RawPointer
properties were being renamed from "value" to "_rawValue" for clarity,
COpaquePointer got that treatment too, even though it wasn't strictly
necessary, for consistency.

Swift SVN r22252
2014-09-24 02:50:43 +00:00

1183 lines
36 KiB
Swift

//===--- Arrays.swift.gyb - ContiguousArray, Array, and Slice -*- 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
//
//===----------------------------------------------------------------------===//
//
// Three generic, mutable array-like types with value semantics.
//
// - ContiguousArray<T> is a fast, contiguous array of T with a known
// backing store.
//
// - Slice<T> presents an arbitrary subsequence of some contiguous sequence
// of Ts.
//
// - Array<T> is like ContiguousArray<T> when T is not an ObjC type.
// Otherwise, it may use an NSArray bridged from Cocoa for storage
//
//===----------------------------------------------------------------------===//
%{
arrayTypes = [
('ContiguousArray', 'a ContiguousArray'),
('Slice', 'a `Slice`'),
('Array', 'an `Array`')
]
}%
% for (Self, a_Self) in arrayTypes:
%{
if True:
O1 = ("O(1) unless `self`'s storage is"
+ ' shared with another live array; O(`count`) '
+ ('if `self` does not wrap a bridged `NSArray`; '
+ 'otherwise the efficiency is unspecified.'
if Self == 'Array' else 'otherwise.'))
contiguousCaveat = (
' If no such storage exists, it is first created.' if Self == 'Array'
else '')
if Self == 'ContiguousArray':
SelfDocComment = """\
/// A fast, contiguously-stored array of `T`.
///
/// Efficiency is equivalent to that of `Array`, unless `T` is a
/// `class` or `@objc` `protocol` type, in which case using
/// `ContiguousArray` may be more efficient. Note, however, that
/// `ContiguousArray` does not bridge to Objective-C. See `Array`,
/// with which `ContiguousArray` shares most properties, for more
/// detail."""
elif Self == 'Slice':
SelfDocComment = """\
/// The `Array`-like type that represents a sub-sequence of any
/// `Array`, `ContiguousArray`, or other `Slice`.
///
/// `Slice` always uses contiguous storage and does not bridge to
/// Objective-C.
///
/// .. Warning:: Long-term storage of `Slice` instances is discouraged
///
/// Because a `Slice` presents a *view* onto the storage of some
/// larger array even after the original array's lifetime ends,
/// storing the slice may prolong the lifetime of elements that are
/// no longer accessible, which can manifest as apparent memory and
/// object leakage. To prevent this effect, use `Slice` only for
/// transient computation."""
elif Self == 'Array':
SelfDocComment = """\
/// Conceptually_, `Array` is an efficient, tail-growable random-access
/// collection of arbitrary elements.
///
/// Common Properties of Array Types
/// ================================
///
/// The information in this section applies to all three of Swift's
/// array types, `Array<T>`, `ContiguousArray<T>`, and `Slice<T>`.
/// When you read the word "array" here in a normal typeface, it
/// applies to all three of them.
///
/// Value Semantics
/// ---------------
///
/// Each array variable, let binding, or stored property has an
/// independent value that includes the values of all of its elements.
/// Therefore, mutations to the array are not observable through its
/// copies::
///
/// var a = [1, 2, 3]
/// var b = a
/// b[0] = 4
/// println("a=\(a), b=\(b)") // a=[1, 2, 3], b=[4, 2, 3]
///
/// (Of course, if the array stores `class` references, the objects
/// are shared; only the values of the references are independent)
///
/// Arrays use Copy-on-Write so that their storage and elements are
/// only copied lazily, upon mutation, when more than one array
/// instance is using the same buffer. Therefore, the first in any
/// sequence of mutating operations may cost `O(N)` time and space,
/// where `N` is the length of the array.
///
/// Growth and Capacity
/// -------------------
///
/// When an array's contiguous storage fills up, new storage must be
/// allocated and elements must be moved to the new storage. `Array`,
/// `ContiguousArray`, and `Slice` share an exponential growth
/// strategy that makes `append` a constant time operation *when
/// amortized over many invocations*. In addition to a `count`
/// property, these array types have a `capacity` that reflects their
/// potential to store elements without reallocation, and when you
/// know how many elements you'll store, you can call
/// `reserveCapacity` to pre-emptively reallocate and prevent
/// intermediate reallocations.
///
/// .. _Conceptually:
///
/// Objective-C Bridge
/// ==================
///
/// The main distinction between `Array` and the other array types is
/// that it interoperates seamlessly and efficiently with Objective-C.
///
/// `Array<T>` is considered bridged to Objective-C iff `T` is bridged
/// to Objective-C.
///
/// When `T` is a `class` or `@objc` protocol type, `Array` may store
/// its elements in an `NSArray`. Since any arbitrary subclass of
/// `NSArray` can become an `Array`, there are no guarantees about
/// representation or efficiency in this case (see also
/// `ContiguousArray`). Since `NSArray` is immutable, it is just as
/// though the storage was shared by some copy: the first in any
/// sequence of mutating operations causes elements to be copied into
/// unique, contiguous storage which may cost `O(N)` time and space,
/// where `N` is the length of the array (or more, if the underlying
/// `NSArray` is has unusual performance characteristics).
///
/// Bridging to Objective-C
/// -----------------------
///
/// Any bridged `Array` can be implicitly converted to an `NSArray`.
/// When `T` is a `class` or `@objc` protocol, bridging takes O(1)
/// time and O(1) space. Other `Array`\ s must be bridged
/// element-by-element, allocating a new object for each element, at a
/// cost of at least O(`count`) time and space.
///
/// Bridging from Objective-C
/// -------------------------
///
/// An `NSArray` can be implicitly or explicitly converted to any
/// bridged `Array<T>`. This conversion calls `copyWithZone` on the
/// `NSArray`, to ensure it won't be modified, and stores the result
/// in the `Array`. Type-checking, to ensure the `NSArray`\ 's
/// elements match or can be bridged to `T`, is deferred until the
/// first element access."""
# FIXME: Write about Array up/down-casting.
else:
raise AssertionError('Unhandled case: ' + Self)
}%
${SelfDocComment}
public struct ${Self}<T> : MutableCollectionType, Sliceable {
/// The type of element stored by this `${Self}`
public typealias Element = T
/// Always zero, which is the index of the first element when non-empty.
public var startIndex: Int {
return 0
}
/// A "past-the-end" element index; the successor of the last valid
/// subscript argument.
public var endIndex: Int {
return _getCount()
}
/// Access the `index`\ th element. Reading is O(1). Writing is
/// ${O1}.
public subscript(index: Int) -> Element {
get {
_checkSubscript(index)
return _getElement(index)
}
set {
_makeMutableAndUnique()
_checkSubscript(index)
_setElement(index, newValue: newValue)
}
}
/// Return a *generator* over the elements.
///
/// Complexity: O(1)
public func generate() -> IndexingGenerator<${Self}> {
return IndexingGenerator(self)
}
/// A type that can represent a sub-range of ${a_Self}
public typealias SubSlice = Slice<T>
/// Access the elements indicated by the given half-open
/// `subRange`. O(1)
public subscript(subRange: Range<Int>) -> SubSlice {
get {
_checkIndex(subRange.startIndex)
_checkIndex(subRange.endIndex)
return Slice(_buffer[subRange])
}
set(rhs) {
_checkIndex(subRange.startIndex)
_checkIndex(subRange.endIndex)
if self[subRange]._buffer.identity != rhs._buffer.identity {
self.replaceRange(subRange, with: rhs)
}
}
}
//===--- private --------------------------------------------------------===//
@semantics("array.get_count")
func _getCount() -> Int {
return _buffer.count
}
@semantics("array.get_capacity")
func _getCapacity() -> Int {
return _buffer.capacity
}
func _copyBuffer(inout buffer: _Buffer) {
var newBuffer = _ContiguousArrayBuffer<T>(
count: buffer.count, minimumCapacity: buffer.count)
let target = buffer._uninitializedCopy(
0..<count, target: newBuffer.baseAddress)
buffer = _Buffer(newBuffer)
}
@semantics("array.make_mutable")
mutating func _makeMutableAndUnique() {
if _slowPath(!_buffer.isMutableAndUniquelyReferenced()) {
_copyBuffer(&_buffer)
}
}
/// Check that the given `index` is valid for subscripting, i.e. `0
/// index < count`
@semantics("array.check_subscript")
func _checkSubscript(index: Int) {
_precondition(_buffer._isValidSubscript(index), "${Self} index out of range")
}
/// Check that the given `index` is valid, i.e. `0 index count`
@semantics("array.check_index")
func _checkIndex(index: Int) {
_precondition(index <= count, "${Self} index out of range")
_precondition(index >= 0, "Negative ${Self} index is out of range")
}
@semantics("array.get_element")
func _getElement(index: Int) -> Element {
return _buffer[index]
}
@semantics("array.set_element")
mutating func _setElement(
index: Int, newValue: Element
) {
_buffer[index] = newValue
}
public
typealias _Buffer = _${Self}Buffer<T>
/// Initialization from an existing buffer does not have "array.init"
/// semantics because the caller may retain an alias to buffer.
public
init(_ buffer: _Buffer) {
self._buffer = buffer
}
public var _buffer: _Buffer
}
extension ${Self} : ArrayLiteralConvertible {
%if Self == 'Array':
// Optimized implementation for Array
/// Create an instance containing `elements`.
public init(arrayLiteral elements: Element...) {
self = elements
}
%else:
/// Create an instance containing `elements`.
public init(arrayLiteral elements: Element...) {
self.init(_extractOrCopyToNativeArrayBuffer(elements._buffer))
}
%end
}
extension ${Self} {
public func _asCocoaArray() -> _SwiftNSArrayRequiredOverridesType {
return _buffer._asCocoaArray()
}
}
extension ${Self} : ArrayType {
/// Construct an empty ${Self}
@semantics("array.init")
public init() {
_buffer = _Buffer()
}
/// Construct from an arbitrary sequence with elements of type `T`
public init<
S: SequenceType where S.Generator.Element == _Buffer.Element
>(_ s: S) {
self = ${Self}(_Buffer(s~>_copyToNativeArrayBuffer()))
}
/// Construct a ${Self} of `count` elements, each initialized to
/// `repeatedValue`.
@semantics("array.init")
public init(count: Int, repeatedValue: T) {
var p: UnsafeMutablePointer<T>
(self, p) = ${Self}._allocateUninitialized(count)
for _ in 0..<count {
p.initialize(repeatedValue)
++p
}
}
/// Construct a ${Self} of `count` uninitialized elements
internal init(_uninitializedCount count: Int) {
_precondition(count >= 0, "Can't construct ${Self} with count < 0")
_buffer = _Buffer()
reserveCapacity(count)
_buffer.count = count
}
/// Entry point for `Array` literal construction; builds and returns
/// a ${Self} of `count` uninitialized elements
internal static func _allocateUninitialized(
count: Int
) -> (${Self}, UnsafeMutablePointer<T>) {
var result = ${Self}(_uninitializedCount: count)
return (result, result._buffer.baseAddress)
}
/// How many elements the ${Self} stores
public var count: Int {
return _getCount()
}
/// How many elements the `${Self}` can store without reallocation
public var capacity: Int {
return _getCapacity()
}
/// `true` if and only if the `${Self}` is empty
public var isEmpty: Bool {
return count == 0
}
/// The first element, or `nil` if the array is empty
public var first: Element? {
return Swift.first(self)
}
/// The last element, or `nil` if the array is empty
public var last: Element? {
return Swift.last(self)
}
/// An object that guarantees the lifetime of this array's elements
public
var _owner: AnyObject? {
return _buffer.owner
}
/// If the elements are stored contiguously, a pointer to the first
/// element. Otherwise, nil.
public var _baseAddressIfContiguous: UnsafeMutablePointer<Element> {
return _buffer.baseAddress
}
%if Self != 'Array': # // Array does not necessarily have contiguous storage
var _baseAddress: UnsafeMutablePointer<Element> {
return _buffer.baseAddress
}
%end
//===--- basic mutations ------------------------------------------------===//
/// Reserve enough space to store minimumCapacity elements.
///
/// PostCondition: `capacity >= minimumCapacity` and the array has
/// mutable contiguous storage.
///
/// Complexity: O(`count`)
@semantics("array.mutate_unknown")
public mutating func reserveCapacity(minimumCapacity: Int) {
if _buffer.requestUniqueMutableBackingBuffer(minimumCapacity) == nil {
var newBuffer = _ContiguousArrayBuffer<T>(
count: count, minimumCapacity: minimumCapacity)
_buffer._uninitializedCopy(0..<count, target: newBuffer.baseAddress)
_buffer = _Buffer(newBuffer)
}
_sanityCheck(capacity >= minimumCapacity)
}
/// Append newElement to the ${Self}
///
/// Complexity: amortized ${O1}
@semantics("array.mutate_unknown")
public mutating func append(newElement: T) {
_arrayAppend(&_buffer, newElement)
}
/// Append the elements of `newElements` to `self`.
///
/// Complexity: O(*length of result*)
///
public mutating func extend<
S : SequenceType
where S.Generator.Element == T
>(newElements: S) {
// Calling a helper free function instead of writing the code inline
// because of:
//
// <rdar://problem/16954386> Type checker assertion: Unable to solve for
// call to witness?
_${Self}Extend(&self, newElements)
}
/// Remove an element from the end of the ${Self} in O(1).
/// Requires: count > 0
public mutating func removeLast() -> T {
_precondition(count > 0, "can't removeLast from an empty ${Self}")
let c = count
let result = self[c - 1]
self.replaceRange((c - 1)..<c, with: EmptyCollection())
return result
}
/// Insert `newElement` at index `i`.
///
/// Requires: `i <= count`
///
/// Complexity: O(\ `count`\ ).
public mutating func insert(newElement: T, atIndex i: Int) {
_checkIndex(i)
self.replaceRange(i..<i, with: CollectionOfOne(newElement))
}
/// Remove and return the element at index `i`
///
/// Invalidates all indices with respect to `self`.
///
/// Complexity: O(\ `count`\ ).
public mutating func removeAtIndex(index: Int) -> T {
let result = self[index]
self.replaceRange(index..<(index + 1), with: EmptyCollection())
return result
}
/// Remove all elements.
///
/// Postcondition: `capacity == 0` iff `keepCapacity` is `false`.
///
/// Complexity: O(\ `countElements(self)`\ ).
public mutating func removeAll(keepCapacity: Bool = false) {
if !keepCapacity {
_buffer = _Buffer()
}
else {
self.replaceRange(indices(self), with: EmptyCollection())
}
}
//===--- algorithms -----------------------------------------------------===//
/// Interpose `self` between each consecutive pair of `elements`,
/// and concatenate the elements of the resulting sequence. For
/// example, `[-1, -2].join([[1, 2, 3], [4, 5, 6], [7, 8, 9]])`
/// yields `[1, 2, 3, -1, -2, 4, 5, 6, -1, -2, 7, 8, 9]`
public func join<
S : SequenceType where S.Generator.Element == ${Self}<T>
>(elements: S) -> ${Self}<T> {
return Swift.join(self, elements)
}
/// Return the result of repeatedly calling `combine` with an
/// accumulated value initialized to `initial` and each element of
/// `self`, in turn, i.e. return
/// `combine(combine(...combine(combine(initial, self[0]),
/// self[1]),...self[count-2]), self[count-1])`.
public func reduce<U>(initial: U, combine: (U, T)->U) -> U {
return Swift.reduce(self, initial, combine)
}
/// Sort `self` in-place according to `isOrderedBefore`. Requires:
/// `isOrderedBefore` induces a `strict weak ordering
/// <http://en.wikipedia.org/wiki/Strict_weak_order#Strict_weak_orderings>`__
/// over the elements.
public mutating func sort(isOrderedBefore: (T, T)->Bool) {
return withUnsafeMutableBufferPointer {
me in Swift.sort(&me, isOrderedBefore)
return
}
}
/// Return a copy of `self` that has been sorted according to
/// `isOrderedBefore`. Requires: `isOrderedBefore` induces a
/// `strict weak ordering
/// <http://en.wikipedia.org/wiki/Strict_weak_order#Strict_weak_orderings>`__
/// over the elements.
public func sorted(isOrderedBefore: (T, T)->Bool) -> ${Self} {
var result = self
result.sort(isOrderedBefore)
return result
}
/// Return ${a_Self} containing the results of calling
/// `transform(x)` on each element `x` of `self`
public func map<U>(transform: (T)->U) -> ${Self}<U> {
return ${Self}<U>(lazy(self).map(transform))
}
/// A ${Self} containing the elements of `self` in reverse order
public func reverse() -> ${Self} {
return ${Self}(lazy(self).reverse())
}
/// Return ${a_Self} containing the elements `x` of `self` for which
/// `includeElement(x)` is `true`
public func filter(includeElement: (T)->Bool) -> ${Self} {
return ${Self}(lazy(self).filter(includeElement))
}
}
func _${Self}Extend<
T, S : SequenceType
where S.Generator.Element == T
>(inout a: ${Self}<T>, sequence: S) {
a += sequence
}
extension ${Self} : Reflectable {
/// Returns a mirror that reflects `self`.
public func getMirror() -> MirrorType {
return _ArrayTypeMirror(self)
}
}
extension ${Self} : Printable, DebugPrintable {
func _makeDescription(#isDebug: Bool) -> String {
var result = "["
var first = true
for item in self {
if first {
first = false
} else {
result += ", "
}
if isDebug {
debugPrint(item, &result)
} else {
print(item, &result)
}
}
result += "]"
return result
}
/// A textual representation of `self`.
public var description: String {
return _makeDescription(isDebug: false)
}
/// A textual representation of `self`, suitable for debugging.
public var debugDescription: String {
return _makeDescription(isDebug: true)
}
}
extension ${Self} {
@transparent
func _cPointerArgs() -> (AnyObject?, Builtin.RawPointer) {
let p = _baseAddressIfContiguous
if _fastPath(p != nil || count == 0) {
return (_owner, p._rawValue)
}
let n = _extractOrCopyToNativeArrayBuffer(self._buffer)
return (n.owner, n.baseAddress._rawValue)
}
}
extension ${Self} {
/// Call `body(p)`, where `p` is a pointer to the `${Self}`\ 's
/// contiguous storage.${contiguousCaveat}
///
/// Often, the optimizer can eliminate bounds checks within an
/// array algorithm, but when that fails, invoking the
/// same algorithm on `body`\ 's argument lets you trade safety for
/// speed.
public func withUnsafeBufferPointer<R>(
body: (UnsafeBufferPointer<T>) -> R
) -> R {
return _buffer.withUnsafeBufferPointer(body)
}
/// Call `body(p)`, where `p` is a pointer to the `${Self}`\ 's
/// mutable contiguous storage.${contiguousCaveat}
///
/// Often, the optimizer can eliminate bounds- and uniqueness-checks
/// within an array algorithm, but when that fails, invoking the
/// same algorithm on `body`\ 's argument lets you trade safety for
/// speed.
public mutating func withUnsafeMutableBufferPointer<R>(
body: (inout UnsafeMutableBufferPointer<T>)->R
) -> R {
// Ensure unique storage
_arrayReserve(&_buffer, 0)
// Ensure that body can't invalidate the storage or its bounds by
// moving self into a temporary working array.
var work = ${Self}()
swap(&work, &self)
// Create an UnsafeBufferPointer over work that we can pass to body
var a = UnsafeMutableBufferPointer(
start: work._buffer.baseAddress, count: work.count)
// Invoke the body
let ret = body(&a)
// Put the working array back before returning.
swap(&work, &self)
return ret
}
}
%end
extension Array {
/// This function "seeds" the ArrayLiteralConvertible protocol
@effects(readonly)
public static func convertFromHeapArray(
base: Builtin.RawPointer,
owner: Builtin.NativeObject,
count: Builtin.Word
) -> Array {
let elements = UnsafeBufferPointer(
start: unsafeBitCast(base, UnsafeMutablePointer<T>.self),
count: unsafeBitCast(count, Int.self)
)
let r = Array(elements)
_fixLifetime(owner)
return r
}
}
struct _InitializeMemoryFromCollection<
C: CollectionType
> : _PointerFunctionType {
func call(rawMemory: UnsafeMutablePointer<C.Generator.Element>, count: Int) {
var p = rawMemory
var q = newValues.startIndex
for _ in 0..<count {
p++.initialize(newValues[q++])
}
_expectEnd(q, newValues)
}
init(_ newValues: C) {
self.newValues = newValues
}
var newValues: C
}
@inline(never)
func _arrayOutOfPlaceReplace<
B: _ArrayBufferType, C: CollectionType
where C.Generator.Element == B.Element, B.Index == Int
>(
inout source: B, subRange: Range<Int>, newValues: C, insertCount: Int
) {
let growth = insertCount - countElements(subRange)
let newCount = source.count + growth
var newBuffer = Optional(
_forceCreateUniqueMutableBuffer(&source, newCount, newCount))
_arrayOutOfPlaceUpdate(
&source, &newBuffer,
subRange.startIndex, insertCount,
_InitializeMemoryFromCollection(newValues)
)
}
/// A _debugPrecondition check that `i` has exactly reached the end of
/// `s`. This test is never used to ensure memory safety; that is
/// always guaranteed by measuring `s` once and re-using that value.
internal func _expectEnd<C: CollectionType>(
i: C.Index, s: C
) {
_debugPrecondition(
i == s.endIndex,
"invalid CollectionType: count differed in successive traversals"
)
}
func _arrayNonSliceInPlaceReplace<
B: _ArrayBufferType, C: CollectionType
where C.Generator.Element == B.Element, B.Index == Int
>(inout target: B, subRange: Range<Int>, insertCount: Int, newValues: C) {
let oldCount = target.count
let eraseCount = countElements(subRange)
let growth = insertCount - eraseCount
target.count = oldCount + growth
let elements = target.baseAddress
_sanityCheck(elements != nil)
let oldTailIndex = subRange.endIndex
let oldTailStart = elements + oldTailIndex
let newTailIndex = oldTailIndex + growth
let newTailStart = oldTailStart + growth
let tailCount = oldCount - subRange.endIndex
if growth > 0 {
// Slide the tail part of the buffer forwards, in reverse order
// so as not to self-clobber.
newTailStart.moveInitializeBackwardFrom(oldTailStart, count: tailCount)
// Assign over the original subRange
var i = newValues.startIndex
for j in subRange {
elements[j] = newValues[i++]
}
// Initialize the hole left by sliding the tail forward
for j in oldTailIndex..<newTailIndex {
(elements + j).initialize(newValues[i++])
}
_expectEnd(i, newValues)
}
else { // We're not growing the buffer
// Assign all the new elements into the start of the subRange
var i = subRange.startIndex
var j = newValues.startIndex
for _ in 0..<insertCount {
elements[i++] = newValues[j++]
}
_expectEnd(j, newValues)
// If the size didn't change, we're done.
if growth == 0 {
return
}
// Move the tail backward to cover the shrinkage.
let shrinkage = -growth
if tailCount > shrinkage { // If the tail length exceeds the shrinkage
// Assign over the rest of the replaced range with the first
// part of the tail.
newTailStart.moveAssignFrom(oldTailStart, count: shrinkage)
// slide the rest of the tail back
oldTailStart.moveInitializeFrom(
oldTailStart + shrinkage, count: tailCount - shrinkage)
}
else { // tail fits within erased elements
// Assign over the start of the replaced range with the tail
newTailStart.moveAssignFrom(oldTailStart, count: tailCount)
// destroy elements remaining after the tail in subRange
(newTailStart + tailCount).destroy(shrinkage - tailCount)
}
}
}
func _growArrayCapacity(capacity: Int) -> Int {
return capacity * 2
}
% for (Self, a_Self) in arrayTypes:
extension ${Self} {
/// Replace the given `subRange` of elements with `newElements`.
///
/// Complexity: O(\ `countElements(subRange)`\ ) if `subRange.endIndex
/// == self.endIndex` and `isEmpty(newElements)`\ , O(N) otherwise.
@semantics("array.mutate_unknown")
public mutating func replaceRange<
C: CollectionType where C.Generator.Element == _Buffer.Element
>(
subRange: Range<Int>, with newElements: C
) {
_precondition(subRange.startIndex >= 0,
"${Self} replace: subRange start is negative")
_precondition(subRange.endIndex <= self._buffer.endIndex,
"${Self} replace: subRange extends past the end")
let oldCount = self._buffer.count
let eraseCount = countElements(subRange)
let insertCount = numericCast(countElements(newElements)) as Int
let growth = insertCount - eraseCount
if self._buffer.requestUniqueMutableBackingBuffer(oldCount + growth) != nil {
self._buffer.replace(subRange: subRange, with: insertCount, elementsOf: newElements)
} else {
_arrayOutOfPlaceReplace(&self._buffer, subRange, newElements, insertCount)
}
}
/// Insert `newElements` at index `i`
///
/// Invalidates all indices with respect to `self`.
///
/// Complexity: O(\ `count + countElements(newElements)`\ ).
public mutating func splice<
S: CollectionType where S.Generator.Element == T
>(newElements: S, atIndex i: Int) {
// FIXME: <rdar://problem/17866066>
// Swift.splice(&self, newElements, atIndex: i)
self.replaceRange(i..<i, with: newElements)
}
/// Remove the indicated `subRange` of elements
///
/// Complexity: O(\ `count`\ ).
public mutating func removeRange(subRange: Range<Int>) {
Swift.removeRange(&self, subRange)
}
}
/// Extend `lhs` with the elements of `rhs`
public
func += <
T, S: SequenceType
where S.Generator.Element == T
>(inout lhs: ${Self}<T>, rhs: S) {
let oldCount = lhs.count
let capacity = lhs.capacity
let newCount = oldCount + underestimateCount(rhs)
if newCount > capacity {
lhs.reserveCapacity(
max(newCount, _growArrayCapacity(capacity)))
}
_arrayAppendSequence(&lhs._buffer, rhs)
}
/// Extend `lhs` with the elements of `rhs`
public
func += <
T, C: CollectionType
where C.Generator.Element == T
>(inout lhs: ${Self}<T>, rhs: C) {
let rhsCount = numericCast(countElements(rhs)) as Int
let oldCount = lhs.count
let capacity = lhs.capacity
let newCount = oldCount + rhsCount
// Ensure uniqueness, mutability, and sufficient storage. Note that
// for consistency, we need unique lhs even if rhs is empty.
lhs.reserveCapacity(
newCount > capacity ?
max(newCount, _growArrayCapacity(capacity))
: newCount)
var p = lhs._buffer.baseAddress + oldCount
for x in rhs {
(p++).initialize(x)
}
lhs._buffer.count = newCount
}
% end
//===--- generic helpers --------------------------------------------------===//
/// Ensure there's a _ContiguousArrayBuffer capable of storing
/// max(newCount, minimumCapacity) elements, with count set to
/// newCount.
///
/// If source has sufficient capacity, returns nil. Otherwise,
/// returns a new buffer.
///
/// NOTE: does not initialize or destroy any elements. In general,
/// the buffer that satisfies the capacity request now has a count
/// that does not match its number of initialized elements, and that
/// needs to be corrected before the buffer can go back into circulation.
func _createUniqueMutableBuffer<_Buffer: _ArrayBufferType>(
inout source: _Buffer, newCount: Int, minimumCapacity: Int = 0)
-> _ContiguousArrayBuffer<_Buffer.Element>? {
_sanityCheck(newCount >= 0)
let requiredCapacity = max(newCount, minimumCapacity)
if let b = source.requestUniqueMutableBackingBuffer(requiredCapacity) {
source.count = newCount
return nil
}
return _forceCreateUniqueMutableBuffer(&source, newCount, requiredCapacity)
}
func _forceCreateUniqueMutableBuffer<_Buffer: _ArrayBufferType>(
inout source: _Buffer, newCount: Int, requiredCapacity: Int
) -> _ContiguousArrayBuffer<_Buffer.Element> {
_sanityCheck(newCount >= 0)
_sanityCheck(requiredCapacity >= newCount)
let minimumCapacity = max(
requiredCapacity,
newCount > source.capacity
? _growArrayCapacity(source.capacity) : source.capacity)
return _ContiguousArrayBuffer(
count: newCount, minimumCapacity: minimumCapacity)
}
protocol _PointerFunctionType {
typealias Element
func call(UnsafeMutablePointer<Element>, count: Int)
}
/// initialize the elements of dest by copying the first headCount
/// items from source, calling initializeNewElements on the next
/// uninitialized element, and finally by copying the last N items
/// from source into the N remaining uninitialized elements of dest.
///
/// As an optimization, may move elements out of source rather than
/// copying when it isUniquelyReferenced.
func _arrayOutOfPlaceUpdate<
_Buffer: _ArrayBufferType, Initializer: _PointerFunctionType
where Initializer.Element == _Buffer.Element
>(
inout source: _Buffer,
inout dest: _ContiguousArrayBuffer<_Buffer.Element>?,
headCount: Int, // Count of initial source elements to copy/move
newCount: Int, // Count of new elements to insert
initializeNewElements: Initializer
) {
_sanityCheck(headCount >= 0)
_sanityCheck(newCount >= 0)
// Count of trailing source elements to copy/move
let tailCount = dest!.count - headCount - newCount
_sanityCheck(headCount + tailCount <= source.count)
let sourceCount = source.count
let oldCount = sourceCount - headCount - tailCount
let destStart = dest!.baseAddress
let newStart = destStart + headCount
let newEnd = newStart + newCount
// Check to see if we have storage we can move from
if let backing = source.requestUniqueMutableBackingBuffer(sourceCount) {
let sourceStart = source.baseAddress
let oldStart = sourceStart + headCount
// Destroy any items that may be lurking in a _SliceBuffer before
// its real first element
let backingStart = backing.baseAddress
let sourceOffset = sourceStart - backingStart
backingStart.destroy(sourceOffset)
// Move the head items
destStart.moveInitializeFrom(sourceStart, count: headCount)
// Destroy unused source items
oldStart.destroy(oldCount)
initializeNewElements.call(newStart, count: newCount)
// Move the tail items
newEnd.moveInitializeFrom(oldStart + oldCount, count: tailCount)
// Destroy any items that may be lurking in a _SliceBuffer after
// its real last element
let backingEnd = backingStart + backing.count
let sourceEnd = sourceStart + sourceCount
sourceEnd.destroy(backingEnd - sourceEnd)
backing.count = 0
}
else {
let newStart = source._uninitializedCopy(0..<headCount, target: destStart)
initializeNewElements.call(newStart, count: newCount)
source._uninitializedCopy(headCount + oldCount..<sourceCount,
target: newEnd)
}
source = _Buffer(dest!)
}
struct _InitializePointer<T> : _PointerFunctionType {
func call(rawMemory: UnsafeMutablePointer<T>, count: Int) {
_sanityCheck(count == 1)
// FIXME: it would be better if we could find a way to move, here
rawMemory.initialize(newValue)
}
@transparent
init(_ newValue: T) {
self.newValue = newValue
}
var newValue: T
}
func _arrayAppend<_Buffer: _ArrayBufferType>(
inout buffer: _Buffer, newValue: _Buffer.Element
) {
let oldCount = buffer.count
var newBuffer = _createUniqueMutableBuffer(&buffer, oldCount + 1)
if _fastPath(newBuffer == nil) {
(buffer.baseAddress + oldCount).initialize(newValue)
}
else {
_arrayOutOfPlaceUpdate(
&buffer, &newBuffer, oldCount, 1, _InitializePointer(newValue))
}
}
struct _IgnorePointer<T> : _PointerFunctionType {
func call(_:UnsafeMutablePointer<T>, count: Int) {
_sanityCheck(count == 0)
}
}
func _arrayReserve<_Buffer: _ArrayBufferType>(
inout buffer: _Buffer, minimumCapacity: Int
) {
let oldCount = buffer.count
var newBuffer = _createUniqueMutableBuffer(
&buffer, oldCount, minimumCapacity: minimumCapacity)
if _slowPath(newBuffer != nil){
_arrayOutOfPlaceUpdate(&buffer, &newBuffer, oldCount, 0, _IgnorePointer())
}
}
public func _extractOrCopyToNativeArrayBuffer<
_Buffer: _ArrayBufferType
where _Buffer.Generator.Element == _Buffer.Element,
_Buffer.Element == _Buffer._Element
>(source: _Buffer)
-> _ContiguousArrayBuffer<_Buffer.Element>
{
if let n = source.requestNativeBuffer() {
return n
}
return _copyCollectionToNativeArrayBuffer(source)
}
/// Append items from newItems to buffer
func _arrayAppendSequence<
_Buffer: _ArrayBufferType,
S: SequenceType where S.Generator.Element == _Buffer.Element
>(
inout buffer: _Buffer, newItems: S
) {
var stream = newItems.generate()
var nextItem = stream.next()
if nextItem == nil {
return
}
// This will force uniqueness
_arrayAppend(&buffer, nextItem!)
var count = buffer.count
nextItem = stream.next()
while nextItem != nil {
let capacity = buffer.capacity
let base = buffer.baseAddress
while (nextItem != nil) && count < capacity {
(base + count++).initialize(nextItem!)
nextItem = stream.next()
}
buffer.count = count
if nextItem != nil {
_arrayReserve(&buffer, _growArrayCapacity(capacity))
}
}
}
% for (Self, a_Self) in arrayTypes:
// NOTE: The '==' and '!=' below only handles array types
// that are the same, e.g. Array<Int> and Array<Int>, not
// Slice<Int> and Array<Int>.
/// Returns true if these arrays contain the same elements.
public func ==<T: Equatable>(lhs: ${Self}<T>, rhs: ${Self}<T>) -> Bool {
let lhsCount = lhs.count
if lhsCount != rhs.count {
return false
}
// Test referential equality.
if lhsCount == 0 || lhs._buffer.identity == rhs._buffer.identity {
return true
}
var streamLHS = lhs.generate()
var streamRHS = rhs.generate()
var nextLHS = streamLHS.next()
while nextLHS != nil {
let nextRHS = streamRHS.next()
if nextLHS != nextRHS {
return false
}
nextLHS = streamLHS.next()
}
return true
}
/// Returns true if the arrays do not contain the same elements.
public func !=<T: Equatable>(lhs: ${Self}<T>, rhs: ${Self}<T>) -> Bool {
return !(lhs == rhs)
}
%end
/// Returns an Array<Base> containing the same elements as a in
/// O(1). Requires: Base is a base class or base @objc protocol (such
/// as AnyObject) of Derived.
public func _arrayUpCast<Derived, Base>(a: Array<Derived>) -> Array<Base> {
return Array(a._buffer.castToBufferOf(Base.self))
}
extension Array {
/// Try to downcast the source `NSArray` as our native buffer type.
/// If it succeeds, create a new `Array` around it and return that.
/// Return `nil` otherwise.
// Note: this function exists here so that Foundation doesn't have
// to know Array's implementation details.
public static func _bridgeFromObjectiveCAdoptingNativeStorage(
source: AnyObject
) -> Array? {
if let nsSwiftArray = source as? _NSSwiftArrayImpl {
if let nativeStorage =
nsSwiftArray._nativeStorage as? _ContiguousArrayStorage<T> {
return Array(_ContiguousArrayBuffer(nativeStorage))
}
}
return nil
}
/// Construct from the given `_SwiftNSArrayRequiredOverridesType`.
///
/// If `noCopy` is `true`, either `source` must be known to be immutable,
/// or the resulting / `Array` must not survive across code that could mutate
/// `source`.
public init(
_fromCocoaArray source: _SwiftNSArrayRequiredOverridesType,
noCopy: Bool = false) {
var selectedSource: _SwiftNSArrayRequiredOverridesType =
noCopy ?
source :
unsafeBitCast(
source.copyWithZone(nil),
_SwiftNSArrayRequiredOverridesType.self)
self = Array(_ArrayBuffer(selectedSource))
}
}
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End: