Skip to content

Commit 5dc06ac

Browse files
authored
Merge pull request kodecocodes#584 from alessandro-martin/RingBufferRefinements
Ring Buffer Refinements
2 parents fbfd206 + dd1ed39 commit 5dc06ac

File tree

2 files changed

+75
-27
lines changed

2 files changed

+75
-27
lines changed

Ring Buffer/RingBuffer.playground/Contents.swift

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,25 @@ public struct RingBuffer<T> {
1414
array = [T?](repeating: nil, count: count)
1515
}
1616

17+
/* Returns false if out of space. */
18+
@discardableResult
1719
public mutating func write(_ element: T) -> Bool {
18-
if !isFull {
19-
array[writeIndex % array.count] = element
20-
writeIndex += 1
21-
return true
22-
} else {
23-
return false
20+
guard !isFull else { return false }
21+
defer {
22+
writeIndex += 1
2423
}
24+
array[wrapped: writeIndex] = element
25+
return true
2526
}
26-
27+
28+
/* Returns nil if the buffer is empty. */
2729
public mutating func read() -> T? {
28-
if !isEmpty {
29-
let element = array[readIndex % array.count]
30-
readIndex += 1
31-
return element
32-
} else {
33-
return nil
30+
guard !isEmpty else { return nil }
31+
defer {
32+
array[wrapped: readIndex] = nil
33+
readIndex += 1
3434
}
35+
return array[wrapped: readIndex]
3536
}
3637

3738
fileprivate var availableSpaceForReading: Int {
@@ -51,6 +52,30 @@ public struct RingBuffer<T> {
5152
}
5253
}
5354

55+
extension RingBuffer: Sequence {
56+
public func makeIterator() -> AnyIterator<T> {
57+
var index = readIndex
58+
return AnyIterator {
59+
guard index < self.writeIndex else { return nil }
60+
defer {
61+
index += 1
62+
}
63+
return self.array[wrapped: index]
64+
}
65+
}
66+
}
67+
68+
private extension Array {
69+
subscript (wrapped index: Int) -> Element {
70+
get {
71+
return self[index % count]
72+
}
73+
set {
74+
self[index % count] = newValue
75+
}
76+
}
77+
}
78+
5479
var buffer = RingBuffer<Int>(count: 5)
5580
buffer.array // [nil, nil, nil, nil, nil]
5681
buffer.readIndex // 0

Ring Buffer/RingBuffer.swift

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,28 @@ public struct RingBuffer<T> {
1616
private var writeIndex = 0
1717

1818
public init(count: Int) {
19-
array = [T?](count: count, repeatedValue: nil)
19+
array = [T?](repeating: nil, count: count)
2020
}
2121

2222
/* Returns false if out of space. */
23-
public mutating func write(element: T) -> Bool {
24-
if !isFull {
25-
array[writeIndex % array.count] = element
26-
writeIndex += 1
27-
return true
28-
} else {
29-
return false
23+
@discardableResult
24+
public mutating func write(_ element: T) -> Bool {
25+
guard !isFull else { return false }
26+
defer {
27+
writeIndex += 1
3028
}
29+
array[wrapped: writeIndex] = element
30+
return true
3131
}
3232

3333
/* Returns nil if the buffer is empty. */
3434
public mutating func read() -> T? {
35-
if !isEmpty {
36-
let element = array[readIndex % array.count]
37-
readIndex += 1
38-
return element
39-
} else {
40-
return nil
35+
guard !isEmpty else { return nil }
36+
defer {
37+
array[wrapped: readIndex] = nil
38+
readIndex += 1
4139
}
40+
return array[wrapped: readIndex]
4241
}
4342

4443
private var availableSpaceForReading: Int {
@@ -57,3 +56,27 @@ public struct RingBuffer<T> {
5756
return availableSpaceForWriting == 0
5857
}
5958
}
59+
60+
public extension RingBuffer: Sequence {
61+
public func makeIterator() -> AnyIterator<T> {
62+
var index = readIndex
63+
return AnyIterator {
64+
guard index < self.writeIndex else { return nil }
65+
defer {
66+
index += 1
67+
}
68+
return self.array[wrapped: index]
69+
}
70+
}
71+
}
72+
73+
private extension Array {
74+
subscript (wrapped index: Int) -> Element {
75+
get {
76+
return self[index % count]
77+
}
78+
set {
79+
self[index % count] = newValue
80+
}
81+
}
82+
}

0 commit comments

Comments
 (0)