authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-09-04 09:28:43+02:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-09-04 10:17:00+02:00
log90743881cf10c4f90da4a8c187997e9eab4d17d5
tree18aa129e10ce74b673b58e8766cec8dbae99d1bc
parent5f31d54064b204910c18667d0b68b8bf2b57cffb

std: Minor changes to the fs module

* Add a size_hint parameter to the read{toEnd,File}AllocOptions fns * Rename readAllAlloc{,Options} to readToEndAlloc{,Options} as they don't rewind the file before reading * Fix missing rewind in test case

5 files changed, 31 insertions(+), 13 deletions(-)

lib/std/fs.zig+7-2
......@@ -1437,24 +1437,29 @@ pub const Dir = struct {
14371437 /// On success, caller owns returned buffer.
14381438 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
14391439 pub fn readFileAlloc(self: Dir, allocator: *mem.Allocator, file_path: []const u8, max_bytes: usize) ![]u8 {
1440 return self.readFileAllocOptions(allocator, file_path, max_bytes, @alignOf(u8), null);
1440 return self.readFileAllocOptions(allocator, file_path, max_bytes, null, @alignOf(u8), null);
14411441 }
14421442
14431443 /// On success, caller owns returned buffer.
14441444 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
1445 /// If `size_hint` is specified the initial buffer size is calculated using
1446 /// that value, otherwise the effective file size is used instead.
14451447 /// Allows specifying alignment and a sentinel value.
14461448 pub fn readFileAllocOptions(
14471449 self: Dir,
14481450 allocator: *mem.Allocator,
14491451 file_path: []const u8,
14501452 max_bytes: usize,
1453 size_hint: ?usize,
14511454 comptime alignment: u29,
14521455 comptime optional_sentinel: ?u8,
14531456 ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) {
14541457 var file = try self.openFile(file_path, .{});
14551458 defer file.close();
14561459
1457 return file.readAllAllocOptions(allocator, max_bytes, alignment, optional_sentinel);
1460 const stat_size = size_hint orelse try file.getEndPos();
1461
1462 return file.readToEndAllocOptions(allocator, max_bytes, stat_size, alignment, optional_sentinel);
14581463 }
14591464
14601465 pub const DeleteTreeError = error{
lib/std/fs/file.zig+10-6
......@@ -363,25 +363,29 @@ pub const File = struct {
363363 try os.futimens(self.handle, &times);
364364 }
365365
366 /// Reads all the bytes from the current position to the end of the file.
366367 /// On success, caller owns returned buffer.
367368 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
368 pub fn readAllAlloc(self: File, allocator: *mem.Allocator, max_bytes: usize) ![]u8 {
369 return self.readAllAllocOptions(allocator, max_bytes, @alignOf(u8), null);
369 pub fn readToEndAlloc(self: File, allocator: *mem.Allocator, max_bytes: usize) ![]u8 {
370 return self.readToEndAllocOptions(allocator, max_bytes, null, @alignOf(u8), null);
370371 }
371372
373 /// Reads all the bytes from the current position to the end of the file.
372374 /// On success, caller owns returned buffer.
373375 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
376 /// If `size_hint` is specified the initial buffer size is calculated using
377 /// that value, otherwise an arbitrary value is used instead.
374378 /// Allows specifying alignment and a sentinel value.
375 pub fn readAllAllocOptions(
379 pub fn readToEndAllocOptions(
376380 self: File,
377381 allocator: *mem.Allocator,
378382 max_bytes: usize,
383 size_hint: ?usize,
379384 comptime alignment: u29,
380385 comptime optional_sentinel: ?u8,
381386 ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) {
382 const stat_size = try self.getEndPos();
383 const size = math.cast(usize, stat_size) catch math.maxInt(usize);
384 if (size > max_bytes) return error.FileTooBig;
387 // If no size hint is provided fall back to the size=0 code path
388 const size = size_hint orelse 0;
385389
386390 // The file size returned by stat is used as hint to set the buffer
387391 // size. If the reported size is zero, as it happens on Linux for files
lib/std/fs/test.zig+5-4
......@@ -188,7 +188,7 @@ test "readAllAlloc" {
188188 var file = try tmp_dir.dir.createFile("test_file", .{ .read = true });
189189 defer file.close();
190190
191 const buf1 = try file.readAllAlloc(testing.allocator, 1024);
191 const buf1 = try file.readToEndAlloc(testing.allocator, 1024);
192192 defer testing.allocator.free(buf1);
193193 testing.expect(buf1.len == 0);
194194
......@@ -197,20 +197,21 @@ test "readAllAlloc" {
197197 try file.seekTo(0);
198198
199199 // max_bytes > file_size
200 const buf2 = try file.readAllAlloc(testing.allocator, 1024);
200 const buf2 = try file.readToEndAlloc(testing.allocator, 1024);
201201 defer testing.allocator.free(buf2);
202202 testing.expectEqual(write_buf.len, buf2.len);
203203 testing.expect(std.mem.eql(u8, write_buf, buf2));
204204 try file.seekTo(0);
205205
206206 // max_bytes == file_size
207 const buf3 = try file.readAllAlloc(testing.allocator, write_buf.len);
207 const buf3 = try file.readToEndAlloc(testing.allocator, write_buf.len);
208208 defer testing.allocator.free(buf3);
209209 testing.expectEqual(write_buf.len, buf3.len);
210210 testing.expect(std.mem.eql(u8, write_buf, buf3));
211 try file.seekTo(0);
211212
212213 // max_bytes < file_size
213 testing.expectError(error.FileTooBig, file.readAllAlloc(testing.allocator, write_buf.len - 1));
214 testing.expectError(error.FileTooBig, file.readToEndAlloc(testing.allocator, write_buf.len - 1));
214215}
215216
216217test "directory operations on files" {
src-self-hosted/Module.zig+2
......@@ -595,6 +595,7 @@ pub const Scope = struct {
595595 module.gpa,
596596 self.sub_file_path,
597597 std.math.maxInt(u32),
598 null,
598599 1,
599600 0,
600601 );
......@@ -697,6 +698,7 @@ pub const Scope = struct {
697698 module.gpa,
698699 self.sub_file_path,
699700 std.math.maxInt(u32),
701 null,
700702 1,
701703 0,
702704 );
src-self-hosted/main.zig+7-1
......@@ -806,7 +806,13 @@ fn fmtPathFile(
806806 if (stat.kind == .Directory)
807807 return error.IsDir;
808808
809 const source_code = source_file.readAllAlloc(fmt.gpa, max_src_size) catch |err| switch (err) {
809 const source_code = source_file.readToEndAllocOptions(
810 fmt.gpa,
811 max_src_size,
812 stat.size,
813 @alignOf(u8),
814 null,
815 ) catch |err| switch (err) {
810816 error.ConnectionResetByPeer => unreachable,
811817 error.ConnectionTimedOut => unreachable,
812818 error.NotOpenForReading => unreachable,