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 {...@@ -1437,24 +1437,29 @@ pub const Dir = struct {
1437 /// On success, caller owns returned buffer.1437 /// On success, caller owns returned buffer.
1438 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.1438 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
1439 pub fn readFileAlloc(self: Dir, allocator: *mem.Allocator, file_path: []const u8, max_bytes: usize) ![]u8 {1439 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);
1441 }1441 }
14421442
1443 /// On success, caller owns returned buffer.1443 /// On success, caller owns returned buffer.
1444 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.1444 /// 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.
1445 /// Allows specifying alignment and a sentinel value.1447 /// Allows specifying alignment and a sentinel value.
1446 pub fn readFileAllocOptions(1448 pub fn readFileAllocOptions(
1447 self: Dir,1449 self: Dir,
1448 allocator: *mem.Allocator,1450 allocator: *mem.Allocator,
1449 file_path: []const u8,1451 file_path: []const u8,
1450 max_bytes: usize,1452 max_bytes: usize,
1453 size_hint: ?usize,
1451 comptime alignment: u29,1454 comptime alignment: u29,
1452 comptime optional_sentinel: ?u8,1455 comptime optional_sentinel: ?u8,
1453 ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) {1456 ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) {
1454 var file = try self.openFile(file_path, .{});1457 var file = try self.openFile(file_path, .{});
1455 defer file.close();1458 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);
1458 }1463 }
14591464
1460 pub const DeleteTreeError = error{1465 pub const DeleteTreeError = error{
lib/std/fs/file.zig+10-6
...@@ -363,25 +363,29 @@ pub const File = struct {...@@ -363,25 +363,29 @@ pub const File = struct {
363 try os.futimens(self.handle, &times);363 try os.futimens(self.handle, &times);
364 }364 }
365365
366 /// Reads all the bytes from the current position to the end of the file.
366 /// On success, caller owns returned buffer.367 /// On success, caller owns returned buffer.
367 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.368 /// 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 pub fn readToEndAlloc(self: File, allocator: *mem.Allocator, max_bytes: usize) ![]u8 {
369 return self.readAllAllocOptions(allocator, max_bytes, @alignOf(u8), null);370 return self.readToEndAllocOptions(allocator, max_bytes, null, @alignOf(u8), null);
370 }371 }
371372
373 /// Reads all the bytes from the current position to the end of the file.
372 /// On success, caller owns returned buffer.374 /// On success, caller owns returned buffer.
373 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.375 /// 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.
374 /// Allows specifying alignment and a sentinel value.378 /// Allows specifying alignment and a sentinel value.
375 pub fn readAllAllocOptions(379 pub fn readToEndAllocOptions(
376 self: File,380 self: File,
377 allocator: *mem.Allocator,381 allocator: *mem.Allocator,
378 max_bytes: usize,382 max_bytes: usize,
383 size_hint: ?usize,
379 comptime alignment: u29,384 comptime alignment: u29,
380 comptime optional_sentinel: ?u8,385 comptime optional_sentinel: ?u8,
381 ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) {386 ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) {
382 const stat_size = try self.getEndPos();387 // If no size hint is provided fall back to the size=0 code path
383 const size = math.cast(usize, stat_size) catch math.maxInt(usize);388 const size = size_hint orelse 0;
384 if (size > max_bytes) return error.FileTooBig;
385389
386 // The file size returned by stat is used as hint to set the buffer390 // The file size returned by stat is used as hint to set the buffer
387 // size. If the reported size is zero, as it happens on Linux for files391 // 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" {...@@ -188,7 +188,7 @@ test "readAllAlloc" {
188 var file = try tmp_dir.dir.createFile("test_file", .{ .read = true });188 var file = try tmp_dir.dir.createFile("test_file", .{ .read = true });
189 defer file.close();189 defer file.close();
190190
191 const buf1 = try file.readAllAlloc(testing.allocator, 1024);191 const buf1 = try file.readToEndAlloc(testing.allocator, 1024);
192 defer testing.allocator.free(buf1);192 defer testing.allocator.free(buf1);
193 testing.expect(buf1.len == 0);193 testing.expect(buf1.len == 0);
194194
...@@ -197,20 +197,21 @@ test "readAllAlloc" {...@@ -197,20 +197,21 @@ test "readAllAlloc" {
197 try file.seekTo(0);197 try file.seekTo(0);
198198
199 // max_bytes > file_size199 // max_bytes > file_size
200 const buf2 = try file.readAllAlloc(testing.allocator, 1024);200 const buf2 = try file.readToEndAlloc(testing.allocator, 1024);
201 defer testing.allocator.free(buf2);201 defer testing.allocator.free(buf2);
202 testing.expectEqual(write_buf.len, buf2.len);202 testing.expectEqual(write_buf.len, buf2.len);
203 testing.expect(std.mem.eql(u8, write_buf, buf2));203 testing.expect(std.mem.eql(u8, write_buf, buf2));
204 try file.seekTo(0);204 try file.seekTo(0);
205205
206 // max_bytes == file_size206 // 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);
208 defer testing.allocator.free(buf3);208 defer testing.allocator.free(buf3);
209 testing.expectEqual(write_buf.len, buf3.len);209 testing.expectEqual(write_buf.len, buf3.len);
210 testing.expect(std.mem.eql(u8, write_buf, buf3));210 testing.expect(std.mem.eql(u8, write_buf, buf3));
211 try file.seekTo(0);
211212
212 // max_bytes < file_size213 // 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));
214}215}
215216
216test "directory operations on files" {217test "directory operations on files" {
src-self-hosted/Module.zig+2
...@@ -595,6 +595,7 @@ pub const Scope = struct {...@@ -595,6 +595,7 @@ pub const Scope = struct {
595 module.gpa,595 module.gpa,
596 self.sub_file_path,596 self.sub_file_path,
597 std.math.maxInt(u32),597 std.math.maxInt(u32),
598 null,
598 1,599 1,
599 0,600 0,
600 );601 );
...@@ -697,6 +698,7 @@ pub const Scope = struct {...@@ -697,6 +698,7 @@ pub const Scope = struct {
697 module.gpa,698 module.gpa,
698 self.sub_file_path,699 self.sub_file_path,
699 std.math.maxInt(u32),700 std.math.maxInt(u32),
701 null,
700 1,702 1,
701 0,703 0,
702 );704 );
src-self-hosted/main.zig+7-1
...@@ -806,7 +806,13 @@ fn fmtPathFile(...@@ -806,7 +806,13 @@ fn fmtPathFile(
806 if (stat.kind == .Directory)806 if (stat.kind == .Directory)
807 return error.IsDir;807 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) {
810 error.ConnectionResetByPeer => unreachable,816 error.ConnectionResetByPeer => unreachable,
811 error.ConnectionTimedOut => unreachable,817 error.ConnectionTimedOut => unreachable,
812 error.NotOpenForReading => unreachable,818 error.NotOpenForReading => unreachable,