From 76f39215447e0eec4cf00e7c2916ff189a82a37f Mon Sep 17 00:00:00 2001 From: Lee Cannon Date: Wed, 2 Dec 2020 12:53:38 +0000 Subject: [PATCH] Add `readUntilDelimiterOrEofArrayList` & `readUntilDelimiterOrEofAlloc` --- lib/std/io/reader.zig | 52 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/lib/std/io/reader.zig b/lib/std/io/reader.zig index b29c92526d..762521cabe 100644 --- a/lib/std/io/reader.zig +++ b/lib/std/io/reader.zig @@ -60,12 +60,7 @@ pub fn Reader( return self.readAllArrayListAligned(null, array_list, max_append_size); } - pub fn readAllArrayListAligned( - self: Self, - comptime alignment: ?u29, - array_list: *std.ArrayListAligned(u8, alignment), - max_append_size: usize - ) !void { + pub fn readAllArrayListAligned(self: Self, comptime alignment: ?u29, array_list: *std.ArrayListAligned(u8, alignment), max_append_size: usize) !void { try array_list.ensureCapacity(math.min(max_append_size, 4096)); const original_len = array_list.items.len; var start_index: usize = original_len; @@ -101,6 +96,35 @@ pub fn Reader( return array_list.toOwnedSlice(); } + /// Replaces the `std.ArrayList` contents by reading from the stream until `delimiter` or end-of-stream is found. + /// Does not include the delimiter in the result. + /// If the `std.ArrayList` length would exceed `max_size`, `error.StreamTooLong` is returned and the + /// `std.ArrayList` is populated with `max_size` bytes from the stream. + pub fn readUntilDelimiterOrEofArrayList( + self: Self, + array_list: *std.ArrayList(u8), + delimiter: u8, + max_size: usize, + ) !void { + array_list.shrink(0); + while (true) { + var byte: u8 = self.readByte() catch |err| switch (err) { + error.EndOfStream => return, + else => |e| return e, + }; + + if (byte == delimiter) { + return; + } + + if (array_list.items.len == max_size) { + return error.StreamTooLong; + } + + try array_list.append(byte); + } + } + /// Replaces the `std.ArrayList` contents by reading from the stream until `delimiter` is found. /// Does not include the delimiter in the result. /// If the `std.ArrayList` length would exceed `max_size`, `error.StreamTooLong` is returned and the @@ -143,6 +167,22 @@ pub fn Reader( return array_list.toOwnedSlice(); } + /// Allocates enough memory to read until `delimiter` or end-of-stream. + /// If the allocated memory would be greater than `max_size`, returns `error.StreamTooLong`. + /// Caller owns returned memory. + /// If this function returns an error, the contents from the stream read so far are lost. + pub fn readUntilDelimiterOrEofAlloc( + self: Self, + allocator: *mem.Allocator, + delimiter: u8, + max_size: usize, + ) ![]u8 { + var array_list = std.ArrayList(u8).init(allocator); + defer array_list.deinit(); + try self.readUntilDelimiterOrEofArrayList(&array_list, delimiter, max_size); + return array_list.toOwnedSlice(); + } + /// Reads from the stream until specified byte is found. If the buffer is not /// large enough to hold the entire contents, `error.StreamTooLong` is returned. /// If end-of-stream is found, returns the rest of the stream. If this