Commit f7bcc8e040

Andrew Kelley <andrew@ziglang.org>
2020-06-19 03:08:30
rework zig fmt to only make one allocation
taking advantage of the fstat size
1 parent 8b49487
Changed files (3)
lib
src-self-hosted
lib/std/fs/file.zig
@@ -306,6 +306,33 @@ pub const File = struct {
         try os.futimens(self.handle, &times);
     }
 
+    /// On success, caller owns returned buffer.
+    /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
+    pub fn readAllAlloc(self: File, allocator: *mem.Allocator, stat_size: u64, max_bytes: usize) ![]u8 {
+        return self.readAllAllocOptions(allocator, stat_size, max_bytes, @alignOf(u8), null);
+    }
+
+    /// On success, caller owns returned buffer.
+    /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
+    /// Allows specifying alignment and a sentinel value.
+    pub fn readAllAllocOptions(
+        self: File,
+        allocator: *mem.Allocator,
+        stat_size: u64,
+        max_bytes: usize,
+        comptime alignment: u29,
+        comptime optional_sentinel: ?u8,
+    ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) {
+        const size = math.cast(usize, stat_size) catch math.maxInt(usize);
+        if (size > max_bytes) return error.FileTooBig;
+
+        const buf = try allocator.allocWithOptions(u8, size, alignment, optional_sentinel);
+        errdefer allocator.free(buf);
+
+        try self.inStream().readNoEof(buf);
+        return buf;
+    }
+
     pub const ReadError = os.ReadError;
     pub const PReadError = os.PReadError;
 
lib/std/fs.zig
@@ -1229,14 +1229,9 @@ pub const Dir = struct {
         var file = try self.openFile(file_path, .{});
         defer file.close();
 
-        const size = math.cast(usize, try file.getEndPos()) catch math.maxInt(usize);
-        if (size > max_bytes) return error.FileTooBig;
+        const stat_size = try file.getEndPos();
 
-        const buf = try allocator.allocWithOptions(u8, size, alignment, optional_sentinel);
-        errdefer allocator.free(buf);
-
-        try file.inStream().readNoEof(buf);
-        return buf;
+        return file.readAllAllocOptions(allocator, stat_size, max_bytes, alignment, optional_sentinel);
     }
 
     pub const DeleteTreeError = error{
src-self-hosted/main.zig
@@ -707,7 +707,13 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
     };
     defer source_file.close();
 
-    const source_code = source_file.reader().readAllAlloc(fmt.gpa, max_src_size) catch |err| {
+    const stat = source_file.stat() catch |err| {
+        std.debug.warn("unable to stat '{}': {}\n", .{ file_path, err });
+        fmt.any_error = true;
+        return;
+    };
+
+    const source_code = source_file.readAllAlloc(fmt.gpa, stat.size, max_src_size) catch |err| {
         std.debug.warn("unable to read '{}': {}\n", .{ file_path, err });
         fmt.any_error = true;
         return;
@@ -736,7 +742,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
             fmt.any_error = true;
         }
     } else {
-        const baf = try io.BufferedAtomicFile.create(fmt.gpa, fs.cwd(), real_path, .{ .mode = try source_file.mode() });
+        const baf = try io.BufferedAtomicFile.create(fmt.gpa, fs.cwd(), real_path, .{ .mode = stat.mode });
         defer baf.destroy();
 
         const anything_changed = try std.zig.render(fmt.gpa, baf.stream(), tree);