zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit b60e9f2e85e1ca42d80d8822783dbbaed55e0526 (tree)
parent eb375525366ba51c3f626cf9b27d97fc81e2c938
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Fri, 11 Jul 2025 10:56:24 +0200

Merge pull request #24394 from ziglang/fixes

buffering fixes
Diffstat:
Mlib/std/Io/Reader.zig | 9+++++++++
Mlib/std/Io/Writer.zig | 5+++++
Mlib/std/debug.zig | 10+++++++---
Mlib/std/log.zig | 19++++++++-----------
4 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/lib/std/Io/Reader.zig b/lib/std/Io/Reader.zig @@ -840,6 +840,9 @@ pub fn peekDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { /// Returns number of bytes streamed, which may be zero, or error.EndOfStream /// if the delimiter was not found. /// +/// Asserts buffer capacity of at least one. This function performs better with +/// larger buffers. +/// /// See also: /// * `streamDelimiterEnding` /// * `streamDelimiterLimit` @@ -858,6 +861,9 @@ pub fn streamDelimiter(r: *Reader, w: *Writer, delimiter: u8) StreamError!usize /// Returns number of bytes streamed, which may be zero. End of stream can be /// detected by checking if the next byte in the stream is the delimiter. /// +/// Asserts buffer capacity of at least one. This function performs better with +/// larger buffers. +/// /// See also: /// * `streamDelimiter` /// * `streamDelimiterLimit` @@ -884,6 +890,9 @@ pub const StreamDelimiterLimitError = error{ /// /// Returns number of bytes streamed, which may be zero. End of stream can be /// detected by checking if the next byte in the stream is the delimiter. +/// +/// Asserts buffer capacity of at least one. This function performs better with +/// larger buffers. pub fn streamDelimiterLimit( r: *Reader, w: *Writer, diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig @@ -572,6 +572,10 @@ pub fn writeAllPreserve(w: *Writer, preserve_length: usize, bytes: []const u8) E /// A user type may be a `struct`, `vector`, `union` or `enum` type. /// /// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`. +/// +/// Asserts `buffer` capacity of at least 2 if a union is printed. This +/// requirement could be lifted by adjusting the code, but if you trigger that +/// assertion it is a clue that you should probably be using a buffer. pub fn print(w: *Writer, comptime fmt: []const u8, args: anytype) Error!void { const ArgsType = @TypeOf(args); const args_type_info = @typeInfo(ArgsType); @@ -942,6 +946,7 @@ pub fn printAddress(w: *Writer, value: anytype) Error!void { @compileError("cannot format non-pointer type " ++ @typeName(T) ++ " with * specifier"); } +/// Asserts `buffer` capacity of at least 2 if `value` is a union. pub fn printValue( w: *Writer, comptime fmt: []const u8, diff --git a/lib/std/debug.zig b/lib/std/debug.zig @@ -219,10 +219,14 @@ pub fn unlockStderrWriter() void { std.Progress.unlockStderrWriter(); } -/// Print to stderr, unbuffered, and silently returning on failure. Intended -/// for use in "printf debugging". Use `std.log` functions for proper logging. +/// Print to stderr, silently returning on failure. Intended for use in "printf +/// debugging". Use `std.log` functions for proper logging. +/// +/// Uses a 64-byte buffer for formatted printing which is flushed before this +/// function returns. pub fn print(comptime fmt: []const u8, args: anytype) void { - const bw = lockStderrWriter(&.{}); + var buffer: [64]u8 = undefined; + const bw = lockStderrWriter(&buffer); defer unlockStderrWriter(); nosuspend bw.print(fmt, args) catch return; } diff --git a/lib/std/log.zig b/lib/std/log.zig @@ -137,8 +137,11 @@ pub fn defaultLogEnabled(comptime message_level: Level) bool { return comptime logEnabled(message_level, default_log_scope); } -/// The default implementation for the log function, custom log functions may +/// The default implementation for the log function. Custom log functions may /// forward log messages to this function. +/// +/// Uses a 64-byte buffer for formatted printing which is flushed before this +/// function returns. pub fn defaultLog( comptime message_level: Level, comptime scope: @Type(.enum_literal), @@ -147,16 +150,10 @@ pub fn defaultLog( ) void { const level_txt = comptime message_level.asText(); const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): "; - const stderr = std.fs.File.stderr().deprecatedWriter(); - var bw = std.io.bufferedWriter(stderr); - const writer = bw.writer(); - - std.debug.lockStdErr(); - defer std.debug.unlockStdErr(); - nosuspend { - writer.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return; - bw.flush() catch return; - } + var buffer: [64]u8 = undefined; + const stderr = std.debug.lockStderrWriter(&buffer); + defer std.debug.unlockStderrWriter(); + nosuspend stderr.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return; } /// Returns a scoped logging namespace that logs all messages using the scope