authorgravatar for eugenelf10@gmail.comTen Eugene <eugenelf10@gmail.com> 2026-09-21 07:53:28+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-21 07:53:28+02:00
log230c63650ff5ab470594a8b44e06be69654113e9
tree7cc4cca200cb7623c77505ca6ef744a020938834
parentabe2216699d46be45b32215733247db0e3a5e620

std.Io.Reader: add readAllocShort, mirror readAlloc* with readSlice* (#36807)

Closes #36767 Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36807 Reviewed-by: Ryan Liptak <squeek502@noreply.codeberg.org>

5 files changed, 65 insertions(+), 11 deletions(-)

lib/compiler/objcopy.zig+1-1
...@@ -409,7 +409,7 @@ const BinaryElfOutput = struct {...@@ -409,7 +409,7 @@ const BinaryElfOutput = struct {
409 const shstrtab_shdr = (try section_headers.next()).?;409 const shstrtab_shdr = (try section_headers.next()).?;
410410
411 try in.seekTo(shstrtab_shdr.sh_offset);411 try in.seekTo(shstrtab_shdr.sh_offset);
412 break :blk try in.interface.readAlloc(allocator, shstrtab_shdr.sh_size);412 break :blk try in.interface.readAllocAll(allocator, shstrtab_shdr.sh_size);
413 };413 };
414414
415 errdefer if (self.shstrtab) |shstrtab| allocator.free(shstrtab);415 errdefer if (self.shstrtab) |shstrtab| allocator.free(shstrtab);
lib/compiler/objdump.zig+4-4
...@@ -417,7 +417,7 @@ const coff = struct {...@@ -417,7 +417,7 @@ const coff = struct {
417 \\417 \\
418 );418 );
419419
420 const offsets = try r.readAlloc(gpa, num_symbols * 4);420 const offsets = try r.readAllocAll(gpa, num_symbols * 4);
421 defer gpa.free(offsets);421 defer gpa.free(offsets);
422422
423 for (0..num_symbols) |symbol_i| {423 for (0..num_symbols) |symbol_i| {
...@@ -549,7 +549,7 @@ const coff = struct {...@@ -549,7 +549,7 @@ const coff = struct {
549 .longnames => {549 .longnames => {
550 // This member is optional550 // This member is optional
551 if (std.mem.eql(u8, header.name, "//")) {551 if (std.mem.eql(u8, header.name, "//")) {
552 opt_longnames = try r.readAlloc(gpa, header.size);552 opt_longnames = try r.readAllocAll(gpa, header.size);
553 if (dump_header)553 if (dump_header)
554 try w.print("{t: >16} type\n", .{expected_kind});554 try w.print("{t: >16} type\n", .{expected_kind});
555555
...@@ -819,7 +819,7 @@ const coff = struct {...@@ -819,7 +819,7 @@ const coff = struct {
819 const string_table_len = r.peekInt(u32, .little) catch |err|819 const string_table_len = r.peekInt(u32, .little) catch |err|
820 return d.failParse("unable to read string table length: {t}", .{err});820 return d.failParse("unable to read string table length: {t}", .{err});
821821
822 const table = r.readAlloc(gpa, string_table_len) catch |err|822 const table = r.readAllocAll(gpa, string_table_len) catch |err|
823 return d.failParse("unable to read string table: {t}", .{err});823 return d.failParse("unable to read string table: {t}", .{err});
824824
825 try fr.seekTo(pos);825 try fr.seekTo(pos);
...@@ -1268,7 +1268,7 @@ const coff = struct {...@@ -1268,7 +1268,7 @@ const coff = struct {
1268 const dir = image_info.?.data_dirs[@backingInt(DIRECTORY_ENTRY.EXPORT)];1268 const dir = image_info.?.data_dirs[@backingInt(DIRECTORY_ENTRY.EXPORT)];
1269 const dir_end_rva = dir.virtual_address + dir.size;1269 const dir_end_rva = dir.virtual_address + dir.size;
1270 const dir_loc = fr.logicalPos();1270 const dir_loc = fr.logicalPos();
1271 const dir_slice = try r.readAlloc(gpa, dir.size);1271 const dir_slice = try r.readAllocAll(gpa, dir.size);
1272 defer gpa.free(dir_slice);1272 defer gpa.free(dir_slice);
12731273
1274 const dll_name = std.mem.sliceTo(dir_slice[name_loc - dir_loc ..], 0);1274 const dll_name = std.mem.sliceTo(dir_slice[name_loc - dir_loc ..], 0);
lib/std/Io/Reader.zig+55-1
...@@ -744,14 +744,27 @@ pub inline fn readSliceEndianAlloc(...@@ -744,14 +744,27 @@ pub inline fn readSliceEndianAlloc(
744 return dest;744 return dest;
745}745}
746746
747/// Deprecated; use readAllocAll. to be removed after 0.17.
748pub const readAlloc = readAllocAll;
749
747/// Shortcut for calling `readSliceAll` with a buffer provided by `allocator`.750/// Shortcut for calling `readSliceAll` with a buffer provided by `allocator`.
748pub fn readAlloc(r: *Reader, allocator: Allocator, len: usize) ReadAllocError![]u8 {751pub fn readAllocAll(r: *Reader, allocator: Allocator, len: usize) ReadAllocError![]u8 {
749 const dest = try allocator.alloc(u8, len);752 const dest = try allocator.alloc(u8, len);
750 errdefer allocator.free(dest);753 errdefer allocator.free(dest);
751 try readSliceAll(r, dest);754 try readSliceAll(r, dest);
752 return dest;755 return dest;
753}756}
754757
758/// Shortcut for calling `readSliceShort` with a buffer provided by `allocator`,
759/// shrinking allocation if stream reached the end.
760pub fn readAllocShort(r: *Reader, allocator: Allocator, len: usize) ReadAllocError![]u8 {
761 const dest = try allocator.alloc(u8, len);
762 errdefer allocator.free(dest);
763 const n = try readSliceShort(r, dest);
764 if (n == dest.len) return dest;
765 return try allocator.realloc(dest, n);
766}
767
755pub const DelimiterError = error{768pub const DelimiterError = error{
756 /// See the `Reader` implementation for detailed diagnostics.769 /// See the `Reader` implementation for detailed diagnostics.
757 ReadFailed,770 ReadFailed,
...@@ -1746,6 +1759,47 @@ test "readSliceShort with indirect reader" {...@@ -1746,6 +1759,47 @@ test "readSliceShort with indirect reader" {
1746 try testing.expectEqual(0, try ri.interface.readSliceShort(&buf));1759 try testing.expectEqual(0, try ri.interface.readSliceShort(&buf));
1747}1760}
17481761
1762test readAllocAll {
1763 const allocator = testing.allocator;
1764 var r: Reader = .fixed("HelloFren");
1765
1766 const s1 = try r.readAllocAll(allocator, 5);
1767 defer allocator.free(s1);
1768 try testing.expectEqualStrings("Hello", s1);
1769
1770 const s2 = try r.readAllocAll(allocator, 4);
1771 defer allocator.free(s2);
1772 try testing.expectEqualStrings("Fren", s2);
1773}
1774
1775test "readAllocAll with buffer bigger than content" {
1776 const allocator = testing.allocator;
1777 var r: Reader = .fixed("HelloFren");
1778
1779 const s1 = try r.readAllocAll(allocator, 5);
1780 defer allocator.free(s1);
1781 try testing.expectEqualStrings("Hello", s1);
1782
1783 const res = r.readAllocAll(allocator, 10);
1784 try testing.expectError(Error.EndOfStream, res);
1785}
1786
1787test readAllocShort {
1788 var r: Reader = .fixed("HelloFren");
1789
1790 const s1 = try r.readAllocShort(testing.allocator, 5);
1791 defer testing.allocator.free(s1);
1792 try testing.expectEqualStrings("Hello", s1);
1793
1794 const s2 = try r.readAllocShort(testing.allocator, 10);
1795 defer testing.allocator.free(s2);
1796 try testing.expectEqualStrings("Fren", s2);
1797
1798 const s3 = try r.readAllocShort(testing.allocator, 10);
1799 defer testing.allocator.free(s3);
1800 try testing.expectEqual(0, s3.len);
1801}
1802
1749test readVec {1803test readVec {
1750 var r: Reader = .fixed(std.ascii.letters);1804 var r: Reader = .fixed(std.ascii.letters);
1751 var flat_buffer: [52]u8 = undefined;1805 var flat_buffer: [52]u8 = undefined;
lib/std/debug/Pdb.zig+4-4
...@@ -171,7 +171,7 @@ pub fn parseIpiStream(self: *Pdb) !void {...@@ -171,7 +171,7 @@ pub fn parseIpiStream(self: *Pdb) !void {
171 const header = try stream.interface.peekStruct(pdb.IpiStreamHeader, .little);171 const header = try stream.interface.peekStruct(pdb.IpiStreamHeader, .little);
172 if (header.version != .v80) // only value observed by LLVM team172 if (header.version != .v80) // only value observed by LLVM team
173 return error.UnknownPDBVersion;173 return error.UnknownPDBVersion;
174 self.ipi = try stream.interface.readAlloc(gpa, @sizeOf(pdb.IpiStreamHeader) + header.type_record_bytes);174 self.ipi = try stream.interface.readAllocAll(gpa, @sizeOf(pdb.IpiStreamHeader) + header.type_record_bytes);
175}175}
176176
177pub fn parseInfoStream(self: *Pdb) !void {177pub fn parseInfoStream(self: *Pdb) !void {
...@@ -196,7 +196,7 @@ pub fn parseInfoStream(self: *Pdb) !void {...@@ -196,7 +196,7 @@ pub fn parseInfoStream(self: *Pdb) !void {
196 // Find the string table.196 // Find the string table.
197 const string_table_index = str_tab_index: {197 const string_table_index = str_tab_index: {
198 const name_bytes_len = try reader.takeInt(u32, .little);198 const name_bytes_len = try reader.takeInt(u32, .little);
199 const name_bytes = try reader.readAlloc(gpa, name_bytes_len);199 const name_bytes = try reader.readAllocAll(gpa, name_bytes_len);
200 defer gpa.free(name_bytes);200 defer gpa.free(name_bytes);
201201
202 const HashTableHeader = extern struct {202 const HashTableHeader = extern struct {
...@@ -865,9 +865,9 @@ pub fn getModule(self: *Pdb, index: usize) !?*Module {...@@ -865,9 +865,9 @@ pub fn getModule(self: *Pdb, index: usize) !?*Module {
865865
866 const gpa = self.allocator;866 const gpa = self.allocator;
867867
868 mod.symbols = try reader.readAlloc(gpa, mod.mod_info.sym_byte_size - 4);868 mod.symbols = try reader.readAllocAll(gpa, mod.mod_info.sym_byte_size - 4);
869 errdefer gpa.free(mod.symbols);869 errdefer gpa.free(mod.symbols);
870 mod.subsect_info = try reader.readAlloc(gpa, mod.mod_info.c13_byte_size);870 mod.subsect_info = try reader.readAllocAll(gpa, mod.mod_info.c13_byte_size);
871 errdefer gpa.free(mod.subsect_info);871 errdefer gpa.free(mod.subsect_info);
872 mod.inlinee_source_lines = b: {872 mod.inlinee_source_lines = b: {
873 var inlinee_source_lines: std.ArrayList(*align(1) const pdb.InlineeSourceLine) = .empty;873 var inlinee_source_lines: std.ArrayList(*align(1) const pdb.InlineeSourceLine) = .empty;
src/link/Coff.zig+1-1
...@@ -5290,7 +5290,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) Loa...@@ -5290,7 +5290,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) Loa
5290 .longnames => {5290 .longnames => {
5291 // This member is optional5291 // This member is optional
5292 if (std.mem.eql(u8, res.name, "//"))5292 if (std.mem.eql(u8, res.name, "//"))
5293 opt_longnames = try r.readAlloc(gpa, @intCast(res.size));5293 opt_longnames = try r.readAllocAll(gpa, @intCast(res.size));
52945294
5295 opt_expected_kind = null;5295 opt_expected_kind = null;
5296 break;5296 break;