Skip to content

Commit afbcbfd

Browse files
authored
Merge pull request #13071 from glessard/umbp-nonmutating-swapat
nonmutating swapAt implementations for UnsafeMutable(Raw)BufferPointer
2 parents 520d6b9 + 0c95f90 commit afbcbfd

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

stdlib/public/core/UnsafeBufferPointer.swift.gyb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,29 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle
341341
}
342342
% end
343343
}
344+
% if mutable:
345+
346+
/// Exchanges the values at the specified indices of the buffer.
347+
///
348+
/// Both parameters must be valid indices of the buffer, and not
349+
/// equal to `endIndex`. Passing the same index as both `i` and `j` has no
350+
/// effect.
351+
///
352+
/// - Parameters:
353+
/// - i: The index of the first value to swap.
354+
/// - j: The index of the second value to swap.
355+
@_inlineable
356+
public func swapAt(_ i: Int, _ j: Int) {
357+
guard i != j else { return }
358+
_debugPrecondition(i >= 0 && j >= 0)
359+
_debugPrecondition(i < endIndex && j < endIndex)
360+
let pi = (_position! + i)
361+
let pj = (_position! + j)
362+
let tmp = pi.move()
363+
pi.moveInitialize(from: pj, count: 1)
364+
pj.initialize(to: tmp, count: 1)
365+
}
366+
% end # mutable
344367
}
345368
346369
extension Unsafe${Mutable}BufferPointer {

stdlib/public/core/UnsafeRawBufferPointer.swift.gyb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,30 @@ extension Unsafe${Mutable}RawBufferPointer: ${Mutable}Collection {
223223
% end # mutable
224224
}
225225

226+
% if mutable:
227+
/// Exchanges the byte values at the specified indices
228+
/// in this buffer's memory.
229+
///
230+
/// Both parameters must be valid indices of the buffer, and not
231+
/// equal to `endIndex`. Passing the same index as both `i` and `j` has no
232+
/// effect.
233+
///
234+
/// - Parameters:
235+
/// - i: The index of the first byte to swap.
236+
/// - j: The index of the second byte to swap.
237+
@_inlineable
238+
public func swapAt(_ i: Int, _ j: Int) {
239+
guard i != j else { return }
240+
_debugPrecondition(i >= 0 && j >= 0)
241+
_debugPrecondition(i < endIndex && j < endIndex)
242+
let pi = (_position! + i)
243+
let pj = (_position! + j)
244+
let tmp = pi.load(fromByteOffset: 0, as: UInt8.self)
245+
pi.copyMemory(from: pj, byteCount: MemoryLayout<UInt8>.size)
246+
pj.storeBytes(of: tmp, toByteOffset: 0, as: UInt8.self)
247+
}
248+
249+
% end # mutable
226250
/// The number of bytes in the buffer.
227251
///
228252
/// If the `baseAddress` of this buffer is `nil`, the count is zero. However,

validation-test/stdlib/UnsafeBufferPointer.swift.gyb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,49 @@ UnsafeMutable${'Raw' if IsRaw else ''}BufferPointerTestSuite.test("subscript/set
914914
expectEqual(1, buffer[3])
915915
}
916916

917+
UnsafeMutable${'Raw' if IsRaw else ''}BufferPointerTestSuite.test("nonmutating-swapAt") {
918+
% if IsRaw:
919+
let allocated = UnsafeMutableRawPointer.allocate(bytes: 4, alignedTo: 8)
920+
let buffer = UnsafeMutableRawBufferPointer(start: allocated, count: 3)
921+
allocated.storeBytes(of: UInt8.max, toByteOffset: 3, as: UInt8.self)
922+
% else:
923+
let allocated = UnsafeMutablePointer<Int>.allocate(capacity: 4)
924+
let buffer = UnsafeMutableBufferPointer(start: allocated, count: 3)
925+
allocated[3] = Int.max
926+
% end
927+
defer { allocated.deallocate() }
928+
929+
buffer[0] = 0
930+
buffer[1] = 1
931+
buffer[2] = 2
932+
933+
buffer.swapAt(0, 0)
934+
expectEqual(Array(buffer), [0, 1, 2])
935+
936+
buffer.swapAt(0, 2)
937+
expectEqual(Array(buffer), [2, 1, 0])
938+
939+
if _isDebugAssertConfiguration() {
940+
expectCrashLater()
941+
}
942+
buffer.swapAt(2, 3)
943+
}
944+
945+
% if not IsRaw:
946+
UnsafeMutableBufferPointerTestSuite.test("nonmutating-swapAt-withARC") {
947+
let buffer = UnsafeMutableBufferPointer<String>.allocate(capacity: 3)
948+
defer { buffer.deallocate() }
949+
950+
_ = buffer.initialize(from: (0..<3).map(String.init(describing:)))
951+
952+
buffer.swapAt(0, 0)
953+
expectEqual(Array(buffer), ["0", "1", "2"])
954+
955+
buffer.swapAt(0, 2)
956+
expectEqual(Array(buffer), ["2", "1", "0"])
957+
}
958+
% end
959+
917960
% end # SelfName
918961

919962
runAllTests()

0 commit comments

Comments
 (0)