| ... | @@ -1,11 +1,12 @@ | ... | @@ -1,11 +1,12 @@ |
| 1 | //! The standard memory allocation interface. | 1 | //! The standard memory allocation interface. |
| | 2 | const Allocator = @This(); |
| | 3 | |
| | 4 | const builtin = @import("builtin"); |
| 2 | | 5 | |
| 3 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 4 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 5 | const math = std.math; | 8 | const math = std.math; |
| 6 | const mem = std.mem; | 9 | const mem = std.mem; |
| 7 | const Allocator = @This(); | | |
| 8 | const builtin = @import("builtin"); | | |
| 9 | const Alignment = std.mem.Alignment; | 10 | const Alignment = std.mem.Alignment; |
| 10 | | 11 | |
| 11 | pub const Error = error{OutOfMemory}; | 12 | pub 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 | } |
| 473 | | 474 | |
| | 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`. |
| | 482 | pub 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 | |
| | 491 | test 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`. |
| | 506 | pub 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 | |
| | 520 | test 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. |
| 475 | pub const failing: Allocator = .{ | 531 | pub const failing: Allocator = .{ |
| 476 | .ptr = undefined, | 532 | .ptr = undefined, |