//===--- UnsafeBufferPointer.swift.gyb ------------------------*- swift -*-===// // // 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 // //===----------------------------------------------------------------------===// /// An iterator for the elements in the buffer referenced by /// `UnsafeBufferPointer` or `UnsafeMutableBufferPointer`. public struct UnsafeBufferPointerIterator : IteratorProtocol, Sequence { /// Advances to the next element and returns it, or `nil` if no next element /// exists. /// /// Once `nil` has been returned, all subsequent calls return `nil`. public mutating func next() -> Element? { if _position == _end { return nil } let result = _position!.pointee _position! += 1 return result } internal var _position, _end: UnsafePointer? } %for Mutable in ('Mutable', ''): /// A non-owning pointer to a buffer of ${Mutable.lower()} elements stored /// contiguously in memory, presenting a collection interface to the /// underlying elements. /// /// The pointer should be aligned to `MemoryLayout.alignment`. public struct Unsafe${Mutable}BufferPointer : _${Mutable}Indexable, ${Mutable}Collection, RandomAccessCollection { public typealias Index = Int public typealias IndexDistance = Int public typealias Iterator = IndexingIterator> /// Always zero, which is the index of the first element in a /// non-empty buffer. public var startIndex: Int { return 0 } /// The "past the end" position---that is, the position one greater than the /// last valid subscript argument. /// /// The `endIndex` property of an `Unsafe${Mutable}BufferPointer` instance is /// always identical to `count`. public var endIndex: Int { return count } public func index(after i: Int) -> Int { // NOTE: this is a manual specialization of index movement for a Strideable // index that is required for UnsafeBufferPointer performance. The // optimizer is not capable of creating partial specializations yet. // NOTE: Range checks are not performed here, because it is done later by // the subscript function. return i + 1 } public func formIndex(after i: inout Int) { // NOTE: this is a manual specialization of index movement for a Strideable // index that is required for UnsafeBufferPointer performance. The // optimizer is not capable of creating partial specializations yet. // NOTE: Range checks are not performed here, because it is done later by // the subscript function. i += 1 } public func index(before i: Int) -> Int { // NOTE: this is a manual specialization of index movement for a Strideable // index that is required for UnsafeBufferPointer performance. The // optimizer is not capable of creating partial specializations yet. // NOTE: Range checks are not performed here, because it is done later by // the subscript function. return i - 1 } public func formIndex(before i: inout Int) { // NOTE: this is a manual specialization of index movement for a Strideable // index that is required for UnsafeBufferPointer performance. The // optimizer is not capable of creating partial specializations yet. // NOTE: Range checks are not performed here, because it is done later by // the subscript function. i -= 1 } public func index(_ i: Int, offsetBy n: Int) -> Int { // NOTE: this is a manual specialization of index movement for a Strideable // index that is required for UnsafeBufferPointer performance. The // optimizer is not capable of creating partial specializations yet. // NOTE: Range checks are not performed here, because it is done later by // the subscript function. return i + n } public func index( _ i: Int, offsetBy n: Int, limitedBy limit: Int ) -> Int? { // NOTE: this is a manual specialization of index movement for a Strideable // index that is required for UnsafeBufferPointer performance. The // optimizer is not capable of creating partial specializations yet. // NOTE: Range checks are not performed here, because it is done later by // the subscript function. let l = limit - i if n > 0 ? l >= 0 && l < n : l <= 0 && n < l { return nil } return i + n } public func distance(from start: Int, to end: Int) -> Int { // NOTE: this is a manual specialization of index movement for a Strideable // index that is required for UnsafeBufferPointer performance. The // optimizer is not capable of creating partial specializations yet. // NOTE: Range checks are not performed here, because it is done later by // the subscript function. return end - start } public func _failEarlyRangeCheck(_ index: Int, bounds: Range) { // NOTE: This method is a no-op for performance reasons. } public func _failEarlyRangeCheck(_ range: Range, bounds: Range) { // NOTE: This method is a no-op for performance reasons. } public typealias Indices = CountableRange public var indices: Indices { return startIndex.. Element { get { _debugPrecondition(i >= 0) _debugPrecondition(i < endIndex) return _position![i] } %if Mutable: nonmutating set { _debugPrecondition(i >= 0) _debugPrecondition(i < endIndex) _position![i] = newValue } %end } public subscript(bounds: Range) -> ${Mutable}RandomAccessSlice> { get { _debugPrecondition(bounds.lowerBound >= startIndex) _debugPrecondition(bounds.upperBound <= endIndex) return ${Mutable}RandomAccessSlice( base: self, bounds: bounds) } % if Mutable: set { _debugPrecondition(bounds.lowerBound >= startIndex) _debugPrecondition(bounds.upperBound <= endIndex) // FIXME: swift-3-indexing-model: tests. _writeBackMutableSlice(&self, bounds: bounds, slice: newValue) } % end } /// Creates an Unsafe${Mutable}Pointer over the `count` contiguous /// `Element` instances beginning at `start`. /// /// If `start` is nil, `count` must be 0. However, `count` may be 0 even for /// a nonzero `start`. public init(start: Unsafe${Mutable}Pointer?, count: Int) { _precondition( count >= 0, "Unsafe${Mutable}BufferPointer with negative count") _precondition( count == 0 || start != nil, "Unsafe${Mutable}BufferPointer has a nil start and nonzero count") _position = start _end = start.map { $0 + count } } /// Returns an iterator over the elements of this sequence. /// /// - Complexity: O(1). public func makeIterator() -> UnsafeBufferPointerIterator { return UnsafeBufferPointerIterator(_position: _position, _end: _end) } /// A pointer to the first element of the buffer. public var baseAddress: Unsafe${Mutable}Pointer? { return _position } /// The number of elements in the buffer. public var count: Int { switch(_position, _end) { case (.some(let pos), .some(let end)): return (end - pos) case _: return 0 } } let _position, _end: Unsafe${Mutable}Pointer? } extension Unsafe${Mutable}BufferPointer : CustomDebugStringConvertible { /// A textual representation of `self`, suitable for debugging. public var debugDescription: String { return "Unsafe${Mutable}BufferPointer" + "(start: \(_position.map(String.init(describing:)) ?? "nil"), count: \(count))" } } %end @available(*, unavailable, renamed: "UnsafeBufferPointerIterator") public struct UnsafeBufferPointerGenerator {} // ${'Local Variables'}: // eval: (read-only-mode 1) // End: