authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-03-11 18:49:16-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-03-11 18:49:16-07:00
logda5b16f9e2b76534b1cab9093566693482084360
tree1cb23ffd7a396728a64033b44d10c7ee0b939b57
parentcb4e087fda07a3bec296d1e75da6416112fa2fd1
parent6fe2b4077896218083f778e926217f596a58a550
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #19238 from dweiller/ring-buffer

std.RingBuffer: minor cleanup and doc improvements

1 files changed, 19 insertions(+), 14 deletions(-)

lib/std/RingBuffer.zig+19-14
...@@ -74,6 +74,7 @@ pub fn writeSlice(self: *RingBuffer, bytes: []const u8) Error!void {...@@ -74,6 +74,7 @@ pub fn writeSlice(self: *RingBuffer, bytes: []const u8) Error!void {
74/// bytes will be overwritten.74/// bytes will be overwritten.
75/// Uses memcpy and so `bytes` must not overlap ring buffer data.75/// Uses memcpy and so `bytes` must not overlap ring buffer data.
76pub fn writeSliceAssumeCapacity(self: *RingBuffer, bytes: []const u8) void {76pub fn writeSliceAssumeCapacity(self: *RingBuffer, bytes: []const u8) void {
77 assert(bytes.len <= self.data.len);
77 const data_start = self.mask(self.write_index);78 const data_start = self.mask(self.write_index);
78 const part1_data_end = @min(data_start + bytes.len, self.data.len);79 const part1_data_end = @min(data_start + bytes.len, self.data.len);
79 const part1_len = part1_data_end - data_start;80 const part1_len = part1_data_end - data_start;
...@@ -104,6 +105,7 @@ pub fn writeSliceForwards(self: *RingBuffer, bytes: []const u8) Error!void {...@@ -104,6 +105,7 @@ pub fn writeSliceForwards(self: *RingBuffer, bytes: []const u8) Error!void {
104/// bytes will be overwritten.105/// bytes will be overwritten.
105/// Uses copyForwards and can write slices from this RingBuffer into itself.106/// Uses copyForwards and can write slices from this RingBuffer into itself.
106pub fn writeSliceForwardsAssumeCapacity(self: *RingBuffer, bytes: []const u8) void {107pub fn writeSliceForwardsAssumeCapacity(self: *RingBuffer, bytes: []const u8) void {
108 assert(bytes.len <= self.data.len);
107 const data_start = self.mask(self.write_index);109 const data_start = self.mask(self.write_index);
108 const part1_data_end = @min(data_start + bytes.len, self.data.len);110 const part1_data_end = @min(data_start + bytes.len, self.data.len);
109 const part1_len = part1_data_end - data_start;111 const part1_len = part1_data_end - data_start;
...@@ -148,18 +150,15 @@ pub fn readFirst(self: *RingBuffer, dest: []u8, length: usize) Error!void {...@@ -148,18 +150,15 @@ pub fn readFirst(self: *RingBuffer, dest: []u8, length: usize) Error!void {
148/// Uses memcpy and so `dest` must not overlap ring buffer data.150/// Uses memcpy and so `dest` must not overlap ring buffer data.
149pub fn readFirstAssumeLength(self: *RingBuffer, dest: []u8, length: usize) void {151pub fn readFirstAssumeLength(self: *RingBuffer, dest: []u8, length: usize) void {
150 assert(length <= self.len() and length <= dest.len);152 assert(length <= self.len() and length <= dest.len);
151 const data_start = self.mask(self.read_index);153 const slice = self.sliceAt(self.read_index, length);
152 const part1_data_end = @min(self.data.len, data_start + length);154 slice.copyTo(dest);
153 const part1_len = part1_data_end - data_start;
154 const part2_len = length - part1_len;
155 @memcpy(dest[0..part1_len], self.data[data_start..part1_data_end]);
156 @memcpy(dest[part1_len..length], self.data[0..part2_len]);
157 self.read_index = self.mask2(self.read_index + length);155 self.read_index = self.mask2(self.read_index + length);
158}156}
159157
160/// Reads last `length` bytes written to the ring buffer into `dest`; Returns158/// Reads last `length` bytes written to the ring buffer into `dest`; Returns
161/// Error.ReadLengthInvalid if length greater than ring or dest length159/// Error.ReadLengthInvalid if length greater than ring or dest length
162/// Uses memcpy and so `dest` must not overlap ring buffer data.160/// Uses memcpy and so `dest` must not overlap ring buffer data.
161/// Reduces write index by `length`.
163pub fn readLast(self: *RingBuffer, dest: []u8, length: usize) Error!void {162pub fn readLast(self: *RingBuffer, dest: []u8, length: usize) Error!void {
164 if (length > self.len() or length > dest.len) return error.ReadLengthInvalid;163 if (length > self.len() or length > dest.len) return error.ReadLengthInvalid;
165 self.readLastAssumeLength(dest, length);164 self.readLastAssumeLength(dest, length);
...@@ -168,15 +167,15 @@ pub fn readLast(self: *RingBuffer, dest: []u8, length: usize) Error!void {...@@ -168,15 +167,15 @@ pub fn readLast(self: *RingBuffer, dest: []u8, length: usize) Error!void {
168/// Reads last `length` bytes written to the ring buffer into `dest`;167/// Reads last `length` bytes written to the ring buffer into `dest`;
169/// Asserts that length not greater than ring buffer or dest length168/// Asserts that length not greater than ring buffer or dest length
170/// Uses memcpy and so `dest` must not overlap ring buffer data.169/// Uses memcpy and so `dest` must not overlap ring buffer data.
170/// Reduces write index by `length`.
171pub fn readLastAssumeLength(self: *RingBuffer, dest: []u8, length: usize) void {171pub fn readLastAssumeLength(self: *RingBuffer, dest: []u8, length: usize) void {
172 assert(length <= self.len() and length <= dest.len);172 assert(length <= self.len() and length <= dest.len);
173 const data_start = self.mask(self.write_index + self.data.len - length);173 const slice = self.sliceLast(length);
174 const part1_data_end = @min(self.data.len, data_start + length);174 slice.copyTo(dest);
175 const part1_len = part1_data_end - data_start;175 self.write_index = if (self.write_index >= self.data.len)
176 const part2_len = length - part1_len;176 self.write_index - length
177 @memcpy(dest[0..part1_len], self.data[data_start..part1_data_end]);177 else
178 @memcpy(dest[part1_len..length], self.data[0..part2_len]);178 self.mask(self.write_index + self.data.len - length);
179 self.write_index = if (self.write_index >= self.data.len) self.write_index - length else data_start;
180}179}
181180
182/// Returns `true` if the ring buffer is empty and `false` otherwise.181/// Returns `true` if the ring buffer is empty and `false` otherwise.
...@@ -189,7 +188,7 @@ pub fn isFull(self: RingBuffer) bool {...@@ -189,7 +188,7 @@ pub fn isFull(self: RingBuffer) bool {
189 return self.mask2(self.write_index + self.data.len) == self.read_index;188 return self.mask2(self.write_index + self.data.len) == self.read_index;
190}189}
191190
192/// Returns the length191/// Returns the length of data available for reading
193pub fn len(self: RingBuffer) usize {192pub fn len(self: RingBuffer) usize {
194 const wrap_offset = 2 * self.data.len * @intFromBool(self.write_index < self.read_index);193 const wrap_offset = 2 * self.data.len * @intFromBool(self.write_index < self.read_index);
195 const adjusted_write_index = self.write_index + wrap_offset;194 const adjusted_write_index = self.write_index + wrap_offset;
...@@ -202,6 +201,12 @@ pub fn len(self: RingBuffer) usize {...@@ -202,6 +201,12 @@ pub fn len(self: RingBuffer) usize {
202pub const Slice = struct {201pub const Slice = struct {
203 first: []u8,202 first: []u8,
204 second: []u8,203 second: []u8,
204
205 /// Copy data from `self` into `dest`
206 pub fn copyTo(self: Slice, dest: []u8) void {
207 @memcpy(dest[0..self.first.len], self.first);
208 @memcpy(dest[self.first.len..][0..self.second.len], self.second);
209 }
205};210};
206211
207/// Returns a `Slice` for the region of the ring buffer starting at212/// Returns a `Slice` for the region of the ring buffer starting at