commit 9dda196eea5fc5f299eb87feb93a8d7e756ba2fa (tree)
parent 7ff1556502ac3ec134b3c15d8c70fa9f7845a983
Author: Andrew Kelley <andrew@ziglang.org>
Date: Thu, 25 Jun 2026 01:59:23 +0200
Merge pull request 'std: move fmt.allocPrint to Allocator and document it' (#35926) from Allocator.print into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35926
Diffstat:
2 files changed, 62 insertions(+), 14 deletions(-)
diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
@@ -622,27 +622,19 @@ pub fn count(comptime fmt: []const u8, args: anytype) usize {
return @intCast(dw.count + dw.writer.end);
}
+/// Deprecated in favor of `Allocator.print`.
pub fn allocPrint(gpa: Allocator, comptime fmt: []const u8, args: anytype) Allocator.Error![]u8 {
- var aw = try Writer.Allocating.initCapacity(gpa, fmt.len);
- defer aw.deinit();
- aw.writer.print(fmt, args) catch |err| switch (err) {
- error.WriteFailed => return error.OutOfMemory,
- };
- return aw.toOwnedSlice();
+ return gpa.print(fmt, args);
}
+/// Deprecated in favor of `Allocator.printSentinel`.
pub fn allocPrintSentinel(
gpa: Allocator,
comptime fmt: []const u8,
args: anytype,
comptime sentinel: u8,
) Allocator.Error![:sentinel]u8 {
- var aw = try Writer.Allocating.initCapacity(gpa, fmt.len);
- defer aw.deinit();
- aw.writer.print(fmt, args) catch |err| switch (err) {
- error.WriteFailed => return error.OutOfMemory,
- };
- return aw.toOwnedSliceSentinel(sentinel);
+ return gpa.printSentinel(fmt, args, sentinel);
}
pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8 {
diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig
@@ -1,11 +1,12 @@
//! The standard memory allocation interface.
+const Allocator = @This();
+
+const builtin = @import("builtin");
const std = @import("../std.zig");
const assert = std.debug.assert;
const math = std.math;
const mem = std.mem;
-const Allocator = @This();
-const builtin = @import("builtin");
const Alignment = std.mem.Alignment;
pub const Error = error{OutOfMemory};
@@ -471,6 +472,61 @@ pub fn dupeSentinel(
return new_buf[0..m.len :sentinel];
}
+/// Allocates a formatted string which is returned on success.
+///
+/// Returned slice can be deallocated with `free`. If an arena-style allocator
+/// is used instead, such as `std.heap.ArenaAllocator`, then no call to `free`
+/// is necessary.
+///
+/// See `std.Io.Writer.print`.
+pub fn print(a: Allocator, comptime format: []const u8, args: anytype) Error![]u8 {
+ var aw = try std.Io.Writer.Allocating.initCapacity(a, format.len);
+ defer aw.deinit();
+ aw.writer.print(format, args) catch |err| switch (err) {
+ error.WriteFailed => return error.OutOfMemory,
+ };
+ return aw.toOwnedSlice();
+}
+
+test print {
+ const x: i32 = -1;
+ const y: []const u8 = "hi";
+ const a = std.testing.allocator;
+ const s = try print(a, "{d}={s}", .{ x, y });
+ defer free(a, s);
+ try std.testing.expectEqualStrings("-1=hi", s);
+}
+
+/// Like `print` but returned slice has the provided sentinel.
+///
+/// Returned slice can be deallocated with `free`. If an arena-style allocator
+/// is used instead, such as `std.heap.ArenaAllocator`, then no call to `free`
+/// is necessary. Illegal behavior occurs if the returned slice is type-coerced
+/// to a slice without the sentinel and then passed to `free`.
+pub fn printSentinel(
+ a: Allocator,
+ comptime format: []const u8,
+ args: anytype,
+ comptime sentinel: u8,
+) Allocator.Error![:sentinel]u8 {
+ var aw = try std.Io.Writer.Allocating.initCapacity(a, format.len);
+ defer aw.deinit();
+ aw.writer.print(format, args) catch |err| switch (err) {
+ error.WriteFailed => return error.OutOfMemory,
+ };
+ return aw.toOwnedSliceSentinel(sentinel);
+}
+
+test printSentinel {
+ const x: i32 = -1;
+ const y: []const u8 = "hi";
+ const a = std.testing.allocator;
+ const s = try printSentinel(a, "{d}={s}", .{ x, y }, 0);
+ defer free(a, s);
+ try std.testing.expectEqualStrings("-1=hi", s);
+ try std.testing.expectEqual(0, s[s.len]);
+}
+
/// An allocator that always fails to allocate.
pub const failing: Allocator = .{
.ptr = undefined,