| ... | @@ -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. |
| 76 | pub fn writeSliceAssumeCapacity(self: *RingBuffer, bytes: []const u8) void { | 76 | pub 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. |
| 106 | pub fn writeSliceForwardsAssumeCapacity(self: *RingBuffer, bytes: []const u8) void { | 107 | pub 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. |
| 149 | pub fn readFirstAssumeLength(self: *RingBuffer, dest: []u8, length: usize) void { | 151 | pub 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 | } |
| 159 | | 157 | |
| 160 | /// Reads last `length` bytes written to the ring buffer into `dest`; Returns | 158 | /// Reads last `length` bytes written to the ring buffer into `dest`; Returns |
| 161 | /// Error.ReadLengthInvalid if length greater than ring or dest length | 159 | /// 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`. |
| 163 | pub fn readLast(self: *RingBuffer, dest: []u8, length: usize) Error!void { | 162 | pub 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 length | 168 | /// 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`. |
| 171 | pub fn readLastAssumeLength(self: *RingBuffer, dest: []u8, length: usize) void { | 171 | pub 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 | } |
| 181 | | 180 | |
| 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 | } |
| 191 | | 190 | |
| 192 | /// Returns the length | 191 | /// Returns the length of data available for reading |
| 193 | pub fn len(self: RingBuffer) usize { | 192 | pub 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 { |
| 202 | pub const Slice = struct { | 201 | pub 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 | }; |
| 206 | | 211 | |
| 207 | /// Returns a `Slice` for the region of the ring buffer starting at | 212 | /// Returns a `Slice` for the region of the ring buffer starting at |