File: Deque%2BExtras.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (192 lines) | stat: -rw-r--r-- 7,386 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Collections open source project
//
// Copyright (c) 2021 - 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//

#if !COLLECTIONS_SINGLE_MODULE
import InternalCollectionsUtilities
#endif

extension Deque {
  /// Creates a deque with the specified capacity, then calls the given
  /// closure with a buffer covering the array's uninitialized memory.
  ///
  /// Inside the closure, set the `initializedCount` parameter to the number of
  /// elements that are initialized by the closure. The memory in the range
  /// `buffer[0..<initializedCount]` must be initialized at the end of the
  /// closure's execution, and the memory in the range
  /// `buffer[initializedCount...]` must be uninitialized. This postcondition
  /// must hold even if the `initializer` closure throws an error.
  ///
  /// - Note: While the resulting deque may have a capacity larger than the
  ///   requested amount, the buffer passed to the closure will cover exactly
  ///   the requested number of elements.
  ///
  /// - Parameters:
  ///   - unsafeUninitializedCapacity: The number of elements to allocate
  ///     space for in the new deque.
  ///   - initializer: A closure that initializes elements and sets the count
  ///     of the new deque.
  ///     - Parameters:
  ///       - buffer: A buffer covering uninitialized memory with room for the
  ///         specified number of elements.
  ///       - initializedCount: The count of initialized elements in the deque,
  ///         which begins as zero. Set `initializedCount` to the number of
  ///         elements you initialize.
  @inlinable
  public init(
    unsafeUninitializedCapacity capacity: Int,
    initializingWith initializer:
      (inout UnsafeMutableBufferPointer<Element>, inout Int) throws -> Void
  ) rethrows {
    self._storage = .init(minimumCapacity: capacity)
    try _storage.update { handle in
      handle.startSlot = .zero
      var count = 0
      var buffer = handle.mutableBuffer(for: .zero ..< _Slot(at: capacity))
      defer {
        precondition(count <= capacity,
          "Initialized count set to greater than specified capacity")
        let b = handle.mutableBuffer(for: .zero ..< _Slot(at: capacity))
        precondition(buffer.baseAddress == b.baseAddress && buffer.count == b.count,
          "Initializer relocated Deque storage")
        handle.count = count
      }
      try initializer(&buffer, &count)
    }
  }
}

extension Deque {
  /// Removes and returns the first element of this deque, if it exists.
  ///
  /// - Returns: The first element of the original collection if the collection
  ///    isn't empty; otherwise, `nil`.
  ///
  /// - Complexity: O(1) when this instance has a unique reference to its
  ///    underlying storage; O(`count`) otherwise.
  @inlinable
  public mutating func popFirst() -> Element? {
    // FIXME: Add this to the stdlib on BidirectionalCollection
    // where Self == Self.SubSequence
    guard count > 0 else { return nil }
    _storage.ensureUnique()
    return _storage.update {
      $0.uncheckedRemoveFirst()
    }
  }

  // Note: `popLast` is implemented by the stdlib as a
  // `RangeReplaceableCollection` extension, defined in terms of
  // `_customRemoveLast`.


  /// Adds a new element at the front of the deque.
  ///
  /// Use this method to append a single element to the front of a deque.
  ///
  ///     var numbers: Deque = [1, 2, 3, 4, 5]
  ///     numbers.prepend(100)
  ///     print(numbers)
  ///     // Prints "[100, 1, 2, 3, 4, 5]"
  ///
  /// Because deques increase their allocated capacity using an exponential
  /// strategy, prepending a single element to a deque is an O(1) operation when
  /// averaged over many calls to the `prepend(_:)` method. When a deque has
  /// additional capacity and is not sharing its storage with another instance,
  /// prepending an element is O(1). When a deque needs to reallocate storage
  /// before prepending or its storage is shared with another copy, prepending
  /// is O(`count`).
  ///
  /// - Parameter newElement: The element to prepend to the deque.
  ///
  /// - Complexity: Amortized O(1).
  ///
  /// - SeeAlso: `append(_:)`
  @inlinable
  public mutating func prepend(_ newElement: Element) {
    _storage.ensureUnique(minimumCapacity: count + 1)
    return _storage.update {
      $0.uncheckedPrepend(newElement)
    }
  }

  /// Adds the elements of a collection to the front of the deque.
  ///
  /// Use this method to prepend the elements of a collection to the front of
  /// this deque. This example prepends the elements of a `Range<Int>` instance
  /// to a deque of integers.
  ///
  ///     var numbers: Deque = [1, 2, 3, 4, 5]
  ///     numbers.prepend(contentsOf: 10...15)
  ///     print(numbers)
  ///     // Prints "[10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5]"
  ///
  /// - Parameter newElements: The elements to prepend to the deque.
  ///
  /// - Complexity: Amortized O(`newElements.count`).
  ///
  /// - SeeAlso: `append(contentsOf:)`
  @inlinable
  public mutating func prepend(
    contentsOf newElements: some Collection<Element>
  ) {
    let done: Void? = newElements.withContiguousStorageIfAvailable { source in
      _storage.ensureUnique(minimumCapacity: count + source.count)
      _storage.update { $0.uncheckedPrepend(contentsOf: source) }
    }
    guard done == nil else { return }

    let c = newElements.count
    guard c > 0 else { return }
    _storage.ensureUnique(minimumCapacity: count + c)
    _storage.update { target in
      let gaps = target.availableSegments().suffix(c)
      gaps.initialize(from: newElements)
      target.count += c
      target.startSlot = target.slot(target.startSlot, offsetBy: -c)
    }
  }

  /// Adds the elements of a sequence to the front of the deque.
  ///
  /// Use this method to prepend the elements of a sequence to the front of this
  /// deque. This example prepends the elements of a `Range<Int>` instance to a
  /// deque of integers.
  ///
  ///     var numbers: Deque = [1, 2, 3, 4, 5]
  ///     numbers.prepend(contentsOf: 10...15)
  ///     print(numbers)
  ///     // Prints "[10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5]"
  ///
  /// - Parameter newElements: The elements to prepend to the deque.
  ///
  /// - Complexity: Amortized O(`newElements.count`).
  ///
  /// - SeeAlso: `append(contentsOf:)`
  @inlinable
  public mutating func prepend(contentsOf newElements: some Sequence<Element>) {
    let done: Void? = newElements.withContiguousStorageIfAvailable { source in
      _storage.ensureUnique(minimumCapacity: count + source.count)
      _storage.update { $0.uncheckedPrepend(contentsOf: source) }
    }
    guard done == nil else { return }

    let originalCount = self.count
    self.append(contentsOf: newElements)
    let newCount = self.count
    let c = newCount - originalCount
    _storage.update { target in
      target.startSlot = target.slot(forOffset: originalCount)
      target.count = target.capacity
      target.closeGap(offsets: c ..< c + (target.capacity - newCount))
      assert(target.count == newCount)
    }
  }
}