Commit 76f3921544

Lee Cannon <leecannon@leecannon.xyz>
2020-12-02 13:53:38
Add `readUntilDelimiterOrEofArrayList` & `readUntilDelimiterOrEofAlloc`
1 parent db0cb54
Changed files (1)
lib
std
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