authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-06-25 01:59:23+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-06-25 01:59:23+02:00
log9dda196eea5fc5f299eb87feb93a8d7e756ba2fa
treed22b00e37dce9acf292ff0428f97141e4788c9dc
parent7ff1556502ac3ec134b3c15d8c70fa9f7845a983
parent243192c60ec4e1f09042ff3cfd0542972c639566

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

2 files changed, 62 insertions(+), 14 deletions(-)

lib/std/fmt.zig+4-12
...@@ -622,27 +622,19 @@ pub fn count(comptime fmt: []const u8, args: anytype) usize {...@@ -622,27 +622,19 @@ pub fn count(comptime fmt: []const u8, args: anytype) usize {
622 return @intCast(dw.count + dw.writer.end);622 return @intCast(dw.count + dw.writer.end);
623}623}
624624
625/// Deprecated in favor of `Allocator.print`.
625pub fn allocPrint(gpa: Allocator, comptime fmt: []const u8, args: anytype) Allocator.Error![]u8 {626pub fn allocPrint(gpa: Allocator, comptime fmt: []const u8, args: anytype) Allocator.Error![]u8 {
626 var aw = try Writer.Allocating.initCapacity(gpa, fmt.len);627 return gpa.print(fmt, args);
627 defer aw.deinit();
628 aw.writer.print(fmt, args) catch |err| switch (err) {
629 error.WriteFailed => return error.OutOfMemory,
630 };
631 return aw.toOwnedSlice();
632}628}
633629
630/// Deprecated in favor of `Allocator.printSentinel`.
634pub fn allocPrintSentinel(631pub fn allocPrintSentinel(
635 gpa: Allocator,632 gpa: Allocator,
636 comptime fmt: []const u8,633 comptime fmt: []const u8,
637 args: anytype,634 args: anytype,
638 comptime sentinel: u8,635 comptime sentinel: u8,
639) Allocator.Error![:sentinel]u8 {636) Allocator.Error![:sentinel]u8 {
640 var aw = try Writer.Allocating.initCapacity(gpa, fmt.len);637 return gpa.printSentinel(fmt, args, sentinel);
641 defer aw.deinit();
642 aw.writer.print(fmt, args) catch |err| switch (err) {
643 error.WriteFailed => return error.OutOfMemory,
644 };
645 return aw.toOwnedSliceSentinel(sentinel);
646}638}
647639
648pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8 {640pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8 {
lib/std/mem/Allocator.zig+58-2
...@@ -1,11 +1,12 @@...@@ -1,11 +1,12 @@
1//! The standard memory allocation interface.1//! The standard memory allocation interface.
2const Allocator = @This();
3
4const builtin = @import("builtin");
25
3const std = @import("../std.zig");6const std = @import("../std.zig");
4const assert = std.debug.assert;7const assert = std.debug.assert;
5const math = std.math;8const math = std.math;
6const mem = std.mem;9const mem = std.mem;
7const Allocator = @This();
8const builtin = @import("builtin");
9const Alignment = std.mem.Alignment;10const Alignment = std.mem.Alignment;
1011
11pub const Error = error{OutOfMemory};12pub const Error = error{OutOfMemory};
...@@ -471,6 +472,61 @@ pub fn dupeSentinel(...@@ -471,6 +472,61 @@ pub fn dupeSentinel(
471 return new_buf[0..m.len :sentinel];472 return new_buf[0..m.len :sentinel];
472}473}
473474
475/// Allocates a formatted string which is returned on success.
476///
477/// Returned slice can be deallocated with `free`. If an arena-style allocator
478/// is used instead, such as `std.heap.ArenaAllocator`, then no call to `free`
479/// is necessary.
480///
481/// See `std.Io.Writer.print`.
482pub fn print(a: Allocator, comptime format: []const u8, args: anytype) Error![]u8 {
483 var aw = try std.Io.Writer.Allocating.initCapacity(a, format.len);
484 defer aw.deinit();
485 aw.writer.print(format, args) catch |err| switch (err) {
486 error.WriteFailed => return error.OutOfMemory,
487 };
488 return aw.toOwnedSlice();
489}
490
491test print {
492 const x: i32 = -1;
493 const y: []const u8 = "hi";
494 const a = std.testing.allocator;
495 const s = try print(a, "{d}={s}", .{ x, y });
496 defer free(a, s);
497 try std.testing.expectEqualStrings("-1=hi", s);
498}
499
500/// Like `print` but returned slice has the provided sentinel.
501///
502/// Returned slice can be deallocated with `free`. If an arena-style allocator
503/// is used instead, such as `std.heap.ArenaAllocator`, then no call to `free`
504/// is necessary. Illegal behavior occurs if the returned slice is type-coerced
505/// to a slice without the sentinel and then passed to `free`.
506pub fn printSentinel(
507 a: Allocator,
508 comptime format: []const u8,
509 args: anytype,
510 comptime sentinel: u8,
511) Allocator.Error![:sentinel]u8 {
512 var aw = try std.Io.Writer.Allocating.initCapacity(a, format.len);
513 defer aw.deinit();
514 aw.writer.print(format, args) catch |err| switch (err) {
515 error.WriteFailed => return error.OutOfMemory,
516 };
517 return aw.toOwnedSliceSentinel(sentinel);
518}
519
520test printSentinel {
521 const x: i32 = -1;
522 const y: []const u8 = "hi";
523 const a = std.testing.allocator;
524 const s = try printSentinel(a, "{d}={s}", .{ x, y }, 0);
525 defer free(a, s);
526 try std.testing.expectEqualStrings("-1=hi", s);
527 try std.testing.expectEqual(0, s[s.len]);
528}
529
474/// An allocator that always fails to allocate.530/// An allocator that always fails to allocate.
475pub const failing: Allocator = .{531pub const failing: Allocator = .{
476 .ptr = undefined,532 .ptr = undefined,