//===--- 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 is a fast, contiguous array of T with a known // backing store. // // - Slice presents an arbitrary subsequence of some contiguous sequence // of Ts. // // - Array is like ContiguousArray 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`'), ('_UnitTestArray', 'a `_UnitTestArray`') ] }% % 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`, `ContiguousArray`, and `Slice`. /// 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` 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`. 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. elif Self == '_UnitTestArray': SelfDocComment = "\n/// Temporary" else: raise AssertionError('Unhandled case: ' + Self) }% ${SelfDocComment} public struct ${Self} : 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 { %if Self == 'Array': get { _checkSubscript(index) return _getElement(index) } %else: address { _checkSubscript(index) return UnsafePointer(_buffer.baseAddress + index) } %end mutableAddress { _makeMutableAndUnique() _checkSubscript(index) return _getElementAddress(index) } } /// 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 /// Access the elements indicated by the given half-open /// `subRange`. O(1) public subscript(subRange: Range) -> 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( count: buffer.count, minimumCapacity: buffer.count) let target = buffer._uninitializedCopy( 0..= 0, "Negative ${Self} index is out of range") } @semantics("array.get_element") func _getElement(index: Int) -> Element { return _buffer[index] } @semantics("array.get_element_address") func _getElementAddress(index: Int) -> UnsafeMutablePointer { return _buffer.baseAddress + index } public typealias _Buffer = _${Self.strip('_')}Buffer /// 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} : _ArrayType { public func _doCopyToNativeArrayBuffer() -> _ContiguousArrayBuffer { return _extractOrCopyToNativeArrayBuffer(self._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 } // Referenced by the compiler to allocate array literals. @semantics("array.uninitialized") public func _allocateUninitialized${Self}(count: Builtin.Word) -> (${Self}, Builtin.RawPointer) { let (array, ptr) = ${Self}._allocateUninitialized(Int(count)) return (array, ptr._rawValue) } 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 (self, p) = ${Self}._allocateUninitialized(count) for _ in 0..= 0, "Can't construct ${Self} with count < 0") _buffer = _Buffer() // Performance optimization: avoid reserveCapacity call if not needed. if count > 0 { 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) { 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 { return _buffer.baseAddress } %if Self != 'Array': # // Array does not necessarily have contiguous storage var _baseAddress: UnsafeMutablePointer { 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( count: count, minimumCapacity: minimumCapacity) _buffer._uninitializedCopy(0..= 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: // // 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).. 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(\ `count(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} >(elements: S) -> ${Self} { 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(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 /// `__ /// 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 /// `__ /// 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(transform: (T)->U) -> ${Self} { return ${Self}(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}, 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( body: (UnsafeBufferPointer) -> 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( body: (inout UnsafeMutableBufferPointer)->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 struct _InitializeMemoryFromCollection< C: CollectionType > : _PointerFunctionType { func call(rawMemory: UnsafeMutablePointer, count: Int) { var p = rawMemory var q = newValues.startIndex for _ in 0..( inout source: B, subRange: Range, newValues: C, insertCount: Int ) { let growth = insertCount - count(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( 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, insertCount: Int, newValues: C) { let oldCount = target.count let eraseCount = count(subRange) let growth = insertCount - eraseCount target.count = oldCount + growth let _:() = target.withUnsafeMutableBufferPointer { let elements = $0.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.. 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(\ `count(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, 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 = Swift.count(subRange) let insertCount = numericCast(Swift.count(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 + count(newElements)`\ ). public mutating func splice< S: CollectionType where S.Generator.Element == T >(newElements: S, atIndex i: Int) { // FIXME: // Swift.splice(&self, newElements, atIndex: i) self.replaceRange(i..) { Swift.removeRange(&self, subRange) } } /// Extend `lhs` with the elements of `rhs` public func += < T, S: SequenceType where S.Generator.Element == T >(inout lhs: ${Self}, 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}, rhs: C) { let rhsCount = numericCast(count(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, 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 _:() = source.withUnsafeMutableBufferPointer { let sourceStart = $0.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.. : _PointerFunctionType { func call(rawMemory: UnsafeMutablePointer, 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) { let _:() = buffer.withUnsafeMutableBufferPointer { ($0.baseAddress + oldCount).initialize(newValue) } } else { _arrayOutOfPlaceUpdate( &buffer, &newBuffer, oldCount, 1, _InitializePointer(newValue)) } } struct _IgnorePointer : _PointerFunctionType { func call(_:UnsafeMutablePointer, 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 _:() = buffer.withUnsafeMutableBufferPointer { let base = $0.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 and Array, not // Slice and Array. /// Returns true if these arrays contain the same elements. public func ==(lhs: ${Self}, rhs: ${Self}) -> 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 !=(lhs: ${Self}, rhs: ${Self}) -> Bool { return !(lhs == rhs) } %end /// Returns an Array 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(a: Array) -> Array { 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 deferred = source as? _SwiftDeferredNSArray { if let nativeStorage = deferred._nativeStorage as? _ContiguousArrayStorage { return Array(_ContiguousArrayBuffer(nativeStorage)) } } return nil } /// Construct from the given `_NSArrayCoreType`. /// /// 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: _NSArrayCoreType, noCopy: Bool = false) { var selectedSource: _NSArrayCoreType = noCopy ? source : unsafeBitCast( source.copyWithZone(nil), _NSArrayCoreType.self) self = Array(_ArrayBuffer(selectedSource)) } } // ${'Local Variables'}: // eval: (read-only-mode 1) // End: