| author | |
| committer | |
| log | 9a0970a12bdcae105b6f3f65c0a72d95a209bd35 |
| tree | ab0de8f2447b5e52c2bb5c92a976a52fb4b613ee |
| parent | 79f267f6b9e7f80a6fed3b1019f9de942841c3be |
Also, breaking API changes to:
* std.fs.Dir.readFileAlloc
* std.fs.Dir.readFileAllocOptions24 files changed, 280 insertions(+), 150 deletions(-)
lib/compiler/reduce.zig+2-3| ... | @@ -398,10 +398,9 @@ fn transformationsToFixups( | ... | @@ -398,10 +398,9 @@ fn transformationsToFixups( |
| 398 | 398 | ||
| 399 | fn parse(gpa: Allocator, file_path: []const u8) !Ast { | 399 | fn parse(gpa: Allocator, file_path: []const u8) !Ast { |
| 400 | const source_code = std.fs.cwd().readFileAllocOptions( | 400 | const source_code = std.fs.cwd().readFileAllocOptions( |
| 401 | gpa, | ||
| 402 | file_path, | 401 | file_path, |
| 403 | std.math.maxInt(u32), | 402 | gpa, |
| 404 | null, | 403 | .limited(std.math.maxInt(u32)), |
| 405 | .fromByteUnits(1), | 404 | .fromByteUnits(1), |
| 406 | 0, | 405 | 0, |
| 407 | ) catch |err| { | 406 | ) catch |err| { |
lib/compiler/std-docs.zig+2-2| ... | @@ -173,7 +173,7 @@ fn serveDocsFile( | ... | @@ -173,7 +173,7 @@ fn serveDocsFile( |
| 173 | // The desired API is actually sendfile, which will require enhancing std.http.Server. | 173 | // The desired API is actually sendfile, which will require enhancing std.http.Server. |
| 174 | // We load the file with every request so that the user can make changes to the file | 174 | // We load the file with every request so that the user can make changes to the file |
| 175 | // and refresh the HTML page without restarting this server. | 175 | // and refresh the HTML page without restarting this server. |
| 176 | const file_contents = try context.lib_dir.readFileAlloc(gpa, name, 10 * 1024 * 1024); | 176 | const file_contents = try context.lib_dir.readFileAlloc(name, gpa, .limited(10 * 1024 * 1024)); |
| 177 | defer gpa.free(file_contents); | 177 | defer gpa.free(file_contents); |
| 178 | try request.respond(file_contents, .{ | 178 | try request.respond(file_contents, .{ |
| 179 | .extra_headers = &.{ | 179 | .extra_headers = &.{ |
| ... | @@ -263,7 +263,7 @@ fn serveWasm( | ... | @@ -263,7 +263,7 @@ fn serveWasm( |
| 263 | }); | 263 | }); |
| 264 | // std.http.Server does not have a sendfile API yet. | 264 | // std.http.Server does not have a sendfile API yet. |
| 265 | const bin_path = try wasm_base_path.join(arena, bin_name); | 265 | const bin_path = try wasm_base_path.join(arena, bin_name); |
| 266 | const file_contents = try bin_path.root_dir.handle.readFileAlloc(gpa, bin_path.sub_path, 10 * 1024 * 1024); | 266 | const file_contents = try bin_path.root_dir.handle.readFileAlloc(bin_path.sub_path, gpa, .limited(10 * 1024 * 1024)); |
| 267 | defer gpa.free(file_contents); | 267 | defer gpa.free(file_contents); |
| 268 | try request.respond(file_contents, .{ | 268 | try request.respond(file_contents, .{ |
| 269 | .extra_headers = &.{ | 269 | .extra_headers = &.{ |
lib/fuzzer.zig+1-1| ... | @@ -220,7 +220,7 @@ const Fuzzer = struct { | ... | @@ -220,7 +220,7 @@ const Fuzzer = struct { |
| 220 | const i = f.corpus.items.len; | 220 | const i = f.corpus.items.len; |
| 221 | var buf: [30]u8 = undefined; | 221 | var buf: [30]u8 = undefined; |
| 222 | const input_sub_path = std.fmt.bufPrint(&buf, "{d}", .{i}) catch unreachable; | 222 | const input_sub_path = std.fmt.bufPrint(&buf, "{d}", .{i}) catch unreachable; |
| 223 | const input = f.corpus_directory.handle.readFileAlloc(gpa, input_sub_path, 1 << 31) catch |err| switch (err) { | 223 | const input = f.corpus_directory.handle.readFileAlloc(input_sub_path, gpa, .limited(1 << 31)) catch |err| switch (err) { |
| 224 | error.FileNotFound => { | 224 | error.FileNotFound => { |
| 225 | // Make this one the next input. | 225 | // Make this one the next input. |
| 226 | const input_file = f.corpus_directory.handle.createFile(input_sub_path, .{ | 226 | const input_file = f.corpus_directory.handle.createFile(input_sub_path, .{ |
lib/std/Build/Cache.zig+1-1| ... | @@ -1056,7 +1056,7 @@ pub const Manifest = struct { | ... | @@ -1056,7 +1056,7 @@ pub const Manifest = struct { |
| 1056 | 1056 | ||
| 1057 | fn addDepFileMaybePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void { | 1057 | fn addDepFileMaybePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void { |
| 1058 | const gpa = self.cache.gpa; | 1058 | const gpa = self.cache.gpa; |
| 1059 | const dep_file_contents = try dir.readFileAlloc(gpa, dep_file_basename, manifest_file_size_max); | 1059 | const dep_file_contents = try dir.readFileAlloc(dep_file_basename, gpa, .limited(manifest_file_size_max)); |
| 1060 | defer gpa.free(dep_file_contents); | 1060 | defer gpa.free(dep_file_contents); |
| 1061 | 1061 | ||
| 1062 | var error_buf: std.ArrayListUnmanaged(u8) = .empty; | 1062 | var error_buf: std.ArrayListUnmanaged(u8) = .empty; |
lib/std/Build/Step/CheckFile.zig+1-1| ... | @@ -53,7 +53,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -53,7 +53,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 53 | try step.singleUnchangingWatchInput(check_file.source); | 53 | try step.singleUnchangingWatchInput(check_file.source); |
| 54 | 54 | ||
| 55 | const src_path = check_file.source.getPath2(b, step); | 55 | const src_path = check_file.source.getPath2(b, step); |
| 56 | const contents = fs.cwd().readFileAlloc(b.allocator, src_path, check_file.max_bytes) catch |err| { | 56 | const contents = fs.cwd().readFileAlloc(src_path, b.allocator, .limited(check_file.max_bytes)) catch |err| { |
| 57 | return step.fail("unable to read '{s}': {s}", .{ | 57 | return step.fail("unable to read '{s}': {s}", .{ |
| 58 | src_path, @errorName(err), | 58 | src_path, @errorName(err), |
| 59 | }); | 59 | }); |
lib/std/Build/Step/CheckObject.zig+4-5| ... | @@ -553,14 +553,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { | ... | @@ -553,14 +553,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 553 | 553 | ||
| 554 | const src_path = check_object.source.getPath3(b, step); | 554 | const src_path = check_object.source.getPath3(b, step); |
| 555 | const contents = src_path.root_dir.handle.readFileAllocOptions( | 555 | const contents = src_path.root_dir.handle.readFileAllocOptions( |
| 556 | gpa, | ||
| 557 | src_path.sub_path, | 556 | src_path.sub_path, |
| 558 | check_object.max_bytes, | 557 | gpa, |
| 559 | null, | 558 | .limited(check_object.max_bytes), |
| 560 | .of(u64), | 559 | .of(u64), |
| 561 | null, | 560 | null, |
| 562 | ) catch |err| return step.fail("unable to read '{f}': {s}", .{ | 561 | ) catch |err| return step.fail("unable to read '{f}': {t}", .{ |
| 563 | std.fmt.alt(src_path, .formatEscapeChar), @errorName(err), | 562 | std.fmt.alt(src_path, .formatEscapeChar), err, |
| 564 | }); | 563 | }); |
| 565 | 564 | ||
| 566 | var vars: std.StringHashMap(u64) = .init(gpa); | 565 | var vars: std.StringHashMap(u64) = .init(gpa); |
lib/std/Build/Step/ConfigHeader.zig+2-2| ... | @@ -208,7 +208,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -208,7 +208,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 208 | .autoconf_undef, .autoconf_at => |file_source| { | 208 | .autoconf_undef, .autoconf_at => |file_source| { |
| 209 | try bw.writeAll(c_generated_line); | 209 | try bw.writeAll(c_generated_line); |
| 210 | const src_path = file_source.getPath2(b, step); | 210 | const src_path = file_source.getPath2(b, step); |
| 211 | const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| { | 211 | const contents = std.fs.cwd().readFileAlloc(src_path, arena, .limited(config_header.max_bytes)) catch |err| { |
| 212 | return step.fail("unable to read autoconf input file '{s}': {s}", .{ | 212 | return step.fail("unable to read autoconf input file '{s}': {s}", .{ |
| 213 | src_path, @errorName(err), | 213 | src_path, @errorName(err), |
| 214 | }); | 214 | }); |
| ... | @@ -222,7 +222,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -222,7 +222,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 222 | .cmake => |file_source| { | 222 | .cmake => |file_source| { |
| 223 | try bw.writeAll(c_generated_line); | 223 | try bw.writeAll(c_generated_line); |
| 224 | const src_path = file_source.getPath2(b, step); | 224 | const src_path = file_source.getPath2(b, step); |
| 225 | const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| { | 225 | const contents = std.fs.cwd().readFileAlloc(src_path, arena, .limited(config_header.max_bytes)) catch |err| { |
| 226 | return step.fail("unable to read cmake input file '{s}': {s}", .{ | 226 | return step.fail("unable to read cmake input file '{s}': {s}", .{ |
| 227 | src_path, @errorName(err), | 227 | src_path, @errorName(err), |
| 228 | }); | 228 | }); |
lib/std/Build/WebServer.zig+1-1| ... | @@ -446,7 +446,7 @@ pub fn serveFile( | ... | @@ -446,7 +446,7 @@ pub fn serveFile( |
| 446 | // The desired API is actually sendfile, which will require enhancing http.Server. | 446 | // The desired API is actually sendfile, which will require enhancing http.Server. |
| 447 | // We load the file with every request so that the user can make changes to the file | 447 | // We load the file with every request so that the user can make changes to the file |
| 448 | // and refresh the HTML page without restarting this server. | 448 | // and refresh the HTML page without restarting this server. |
| 449 | const file_contents = path.root_dir.handle.readFileAlloc(gpa, path.sub_path, 10 * 1024 * 1024) catch |err| { | 449 | const file_contents = path.root_dir.handle.readFileAlloc(path.sub_path, gpa, .limited(10 * 1024 * 1024)) catch |err| { |
| 450 | log.err("failed to read '{f}': {s}", .{ path, @errorName(err) }); | 450 | log.err("failed to read '{f}': {s}", .{ path, @errorName(err) }); |
| 451 | return error.AlreadyReported; | 451 | return error.AlreadyReported; |
| 452 | }; | 452 | }; |
lib/std/Io/Reader.zig+41-9| ... | @@ -292,6 +292,23 @@ pub fn allocRemaining(r: *Reader, gpa: Allocator, limit: Limit) LimitedAllocErro | ... | @@ -292,6 +292,23 @@ pub fn allocRemaining(r: *Reader, gpa: Allocator, limit: Limit) LimitedAllocErro |
| 292 | return buffer.toOwnedSlice(gpa); | 292 | return buffer.toOwnedSlice(gpa); |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | pub fn allocRemainingAlignedSentinel( | ||
| 296 | r: *Reader, | ||
| 297 | gpa: Allocator, | ||
| 298 | limit: Limit, | ||
| 299 | comptime alignment: std.mem.Alignment, | ||
| 300 | comptime sentinel: ?u8, | ||
| 301 | ) LimitedAllocError!(if (sentinel) |s| [:s]align(alignment.toByteUnits()) u8 else []align(alignment.toByteUnits()) u8) { | ||
| 302 | var buffer: std.array_list.Aligned(u8, alignment) = .empty; | ||
| 303 | defer buffer.deinit(gpa); | ||
| 304 | try appendRemainingAligned(r, gpa, alignment, &buffer, limit); | ||
| 305 | if (sentinel) |s| { | ||
| 306 | return buffer.toOwnedSliceSentinel(gpa, s); | ||
| 307 | } else { | ||
| 308 | return buffer.toOwnedSlice(gpa); | ||
| 309 | } | ||
| 310 | } | ||
| 311 | |||
| 295 | /// Transfers all bytes from the current position to the end of the stream, up | 312 | /// Transfers all bytes from the current position to the end of the stream, up |
| 296 | /// to `limit`, appending them to `list`. | 313 | /// to `limit`, appending them to `list`. |
| 297 | /// | 314 | /// |
| ... | @@ -308,15 +325,30 @@ pub fn appendRemaining( | ... | @@ -308,15 +325,30 @@ pub fn appendRemaining( |
| 308 | list: *ArrayList(u8), | 325 | list: *ArrayList(u8), |
| 309 | limit: Limit, | 326 | limit: Limit, |
| 310 | ) LimitedAllocError!void { | 327 | ) LimitedAllocError!void { |
| 311 | var a: std.Io.Writer.Allocating = .initOwnedSlice(gpa, list.allocatedSlice()); | 328 | return appendRemainingAligned(r, gpa, .of(u8), list, limit); |
| 312 | a.writer.end = list.items.len; | 329 | } |
| 313 | list.* = .empty; | 330 | |
| 314 | defer { | 331 | /// Transfers all bytes from the current position to the end of the stream, up |
| 315 | list.* = .{ | 332 | /// to `limit`, appending them to `list`. |
| 316 | .items = a.writer.buffer[0..a.writer.end], | 333 | /// |
| 317 | .capacity = a.writer.buffer.len, | 334 | /// If `limit` is reached or exceeded, `error.StreamTooLong` is returned |
| 318 | }; | 335 | /// instead. In such case, the next byte that would be read will be the first |
| 319 | } | 336 | /// one to exceed `limit`, and all preceeding bytes have been appended to |
| 337 | /// `list`. | ||
| 338 | /// | ||
| 339 | /// See also: | ||
| 340 | /// * `appendRemaining` | ||
| 341 | /// * `allocRemainingAligned` | ||
| 342 | pub fn appendRemainingAligned( | ||
| 343 | r: *Reader, | ||
| 344 | gpa: Allocator, | ||
| 345 | comptime alignment: std.mem.Alignment, | ||
| 346 | list: *std.array_list.Aligned(u8, alignment), | ||
| 347 | limit: Limit, | ||
| 348 | ) LimitedAllocError!void { | ||
| 349 | var a = std.Io.Writer.Allocating.fromArrayListAligned(gpa, alignment, list); | ||
| 350 | defer list.* = a.toArrayListAligned(alignment); | ||
| 351 | |||
| 320 | var remaining = limit; | 352 | var remaining = limit; |
| 321 | while (remaining.nonzero()) { | 353 | while (remaining.nonzero()) { |
| 322 | const n = stream(r, &a.writer, remaining) catch |err| switch (err) { | 354 | const n = stream(r, &a.writer, remaining) catch |err| switch (err) { |
lib/std/Io/Writer.zig+118-45| ... | @@ -2531,13 +2531,14 @@ pub fn Hashing(comptime Hasher: type) type { | ... | @@ -2531,13 +2531,14 @@ pub fn Hashing(comptime Hasher: type) type { |
| 2531 | /// Maintains `Writer` state such that it writes to the unused capacity of an | 2531 | /// Maintains `Writer` state such that it writes to the unused capacity of an |
| 2532 | /// array list, filling it up completely before making a call through the | 2532 | /// array list, filling it up completely before making a call through the |
| 2533 | /// vtable, causing a resize. Consequently, the same, optimized, non-generic | 2533 | /// vtable, causing a resize. Consequently, the same, optimized, non-generic |
| 2534 | /// machine code that uses `std.Io.Reader`, such as formatted printing, takes | 2534 | /// machine code that uses `Writer`, such as formatted printing, takes |
| 2535 | /// the hot paths when using this API. | 2535 | /// the hot paths when using this API. |
| 2536 | /// | 2536 | /// |
| 2537 | /// When using this API, it is not necessary to call `flush`. | 2537 | /// When using this API, it is not necessary to call `flush`. |
| 2538 | pub const Allocating = struct { | 2538 | pub const Allocating = struct { |
| 2539 | allocator: Allocator, | 2539 | allocator: Allocator, |
| 2540 | writer: Writer, | 2540 | writer: Writer, |
| 2541 | alignment: std.mem.Alignment, | ||
| 2541 | 2542 | ||
| 2542 | pub fn init(allocator: Allocator) Allocating { | 2543 | pub fn init(allocator: Allocator) Allocating { |
| 2543 | return .{ | 2544 | return .{ |
| ... | @@ -2546,6 +2547,7 @@ pub const Allocating = struct { | ... | @@ -2546,6 +2547,7 @@ pub const Allocating = struct { |
| 2546 | .buffer = &.{}, | 2547 | .buffer = &.{}, |
| 2547 | .vtable = &vtable, | 2548 | .vtable = &vtable, |
| 2548 | }, | 2549 | }, |
| 2550 | .alignment = .of(u8), | ||
| 2549 | }; | 2551 | }; |
| 2550 | } | 2552 | } |
| 2551 | 2553 | ||
| ... | @@ -2553,24 +2555,47 @@ pub const Allocating = struct { | ... | @@ -2553,24 +2555,47 @@ pub const Allocating = struct { |
| 2553 | return .{ | 2555 | return .{ |
| 2554 | .allocator = allocator, | 2556 | .allocator = allocator, |
| 2555 | .writer = .{ | 2557 | .writer = .{ |
| 2556 | .buffer = try allocator.alloc(u8, capacity), | 2558 | .buffer = if (capacity == 0) |
| 2559 | &.{} | ||
| 2560 | else | ||
| 2561 | (allocator.rawAlloc(capacity, .of(u8), @returnAddress()) orelse | ||
| 2562 | return error.OutOfMemory)[0..capacity], | ||
| 2557 | .vtable = &vtable, | 2563 | .vtable = &vtable, |
| 2558 | }, | 2564 | }, |
| 2565 | .alignment = .of(u8), | ||
| 2559 | }; | 2566 | }; |
| 2560 | } | 2567 | } |
| 2561 | 2568 | ||
| 2562 | pub fn initOwnedSlice(allocator: Allocator, slice: []u8) Allocating { | 2569 | pub fn initOwnedSlice(allocator: Allocator, slice: []u8) Allocating { |
| 2570 | return initOwnedSliceAligned(allocator, .of(u8), slice); | ||
| 2571 | } | ||
| 2572 | |||
| 2573 | pub fn initOwnedSliceAligned( | ||
| 2574 | allocator: Allocator, | ||
| 2575 | comptime alignment: std.mem.Alignment, | ||
| 2576 | slice: []align(alignment.toByteUnits()) u8, | ||
| 2577 | ) Allocating { | ||
| 2563 | return .{ | 2578 | return .{ |
| 2564 | .allocator = allocator, | 2579 | .allocator = allocator, |
| 2565 | .writer = .{ | 2580 | .writer = .{ |
| 2566 | .buffer = slice, | 2581 | .buffer = slice, |
| 2567 | .vtable = &vtable, | 2582 | .vtable = &vtable, |
| 2568 | }, | 2583 | }, |
| 2584 | .alignment = alignment, | ||
| 2569 | }; | 2585 | }; |
| 2570 | } | 2586 | } |
| 2571 | 2587 | ||
| 2572 | /// Replaces `array_list` with empty, taking ownership of the memory. | 2588 | /// Replaces `array_list` with empty, taking ownership of the memory. |
| 2573 | pub fn fromArrayList(allocator: Allocator, array_list: *ArrayList(u8)) Allocating { | 2589 | pub fn fromArrayList(allocator: Allocator, array_list: *ArrayList(u8)) Allocating { |
| 2590 | return fromArrayListAligned(allocator, .of(u8), array_list); | ||
| 2591 | } | ||
| 2592 | |||
| 2593 | /// Replaces `array_list` with empty, taking ownership of the memory. | ||
| 2594 | pub fn fromArrayListAligned( | ||
| 2595 | allocator: Allocator, | ||
| 2596 | comptime alignment: std.mem.Alignment, | ||
| 2597 | array_list: *std.array_list.Aligned(u8, alignment), | ||
| 2598 | ) Allocating { | ||
| 2574 | defer array_list.* = .empty; | 2599 | defer array_list.* = .empty; |
| 2575 | return .{ | 2600 | return .{ |
| 2576 | .allocator = allocator, | 2601 | .allocator = allocator, |
| ... | @@ -2579,6 +2604,7 @@ pub const Allocating = struct { | ... | @@ -2579,6 +2604,7 @@ pub const Allocating = struct { |
| 2579 | .buffer = array_list.allocatedSlice(), | 2604 | .buffer = array_list.allocatedSlice(), |
| 2580 | .end = array_list.items.len, | 2605 | .end = array_list.items.len, |
| 2581 | }, | 2606 | }, |
| 2607 | .alignment = alignment, | ||
| 2582 | }; | 2608 | }; |
| 2583 | } | 2609 | } |
| 2584 | 2610 | ||
| ... | @@ -2590,15 +2616,26 @@ pub const Allocating = struct { | ... | @@ -2590,15 +2616,26 @@ pub const Allocating = struct { |
| 2590 | }; | 2616 | }; |
| 2591 | 2617 | ||
| 2592 | pub fn deinit(a: *Allocating) void { | 2618 | pub fn deinit(a: *Allocating) void { |
| 2593 | a.allocator.free(a.writer.buffer); | 2619 | if (a.writer.buffer.len == 0) return; |
| 2620 | a.allocator.rawFree(a.writer.buffer, a.alignment, @returnAddress()); | ||
| 2594 | a.* = undefined; | 2621 | a.* = undefined; |
| 2595 | } | 2622 | } |
| 2596 | 2623 | ||
| 2597 | /// Returns an array list that takes ownership of the allocated memory. | 2624 | /// Returns an array list that takes ownership of the allocated memory. |
| 2598 | /// Resets the `Allocating` to an empty state. | 2625 | /// Resets the `Allocating` to an empty state. |
| 2599 | pub fn toArrayList(a: *Allocating) ArrayList(u8) { | 2626 | pub fn toArrayList(a: *Allocating) ArrayList(u8) { |
| 2627 | return toArrayListAligned(a, .of(u8)); | ||
| 2628 | } | ||
| 2629 | |||
| 2630 | /// Returns an array list that takes ownership of the allocated memory. | ||
| 2631 | /// Resets the `Allocating` to an empty state. | ||
| 2632 | pub fn toArrayListAligned( | ||
| 2633 | a: *Allocating, | ||
| 2634 | comptime alignment: std.mem.Alignment, | ||
| 2635 | ) std.array_list.Aligned(u8, alignment) { | ||
| 2636 | assert(a.alignment == alignment); // Required for Allocator correctness. | ||
| 2600 | const w = &a.writer; | 2637 | const w = &a.writer; |
| 2601 | const result: ArrayList(u8) = .{ | 2638 | const result: std.array_list.Aligned(u8, alignment) = .{ |
| 2602 | .items = w.buffer[0..w.end], | 2639 | .items = w.buffer[0..w.end], |
| 2603 | .capacity = w.buffer.len, | 2640 | .capacity = w.buffer.len, |
| 2604 | }; | 2641 | }; |
| ... | @@ -2608,28 +2645,71 @@ pub const Allocating = struct { | ... | @@ -2608,28 +2645,71 @@ pub const Allocating = struct { |
| 2608 | } | 2645 | } |
| 2609 | 2646 | ||
| 2610 | pub fn ensureUnusedCapacity(a: *Allocating, additional_count: usize) Allocator.Error!void { | 2647 | pub fn ensureUnusedCapacity(a: *Allocating, additional_count: usize) Allocator.Error!void { |
| 2611 | var list = a.toArrayList(); | 2648 | const new_capacity = std.math.add(usize, a.writer.buffer.len, additional_count) catch return error.OutOfMemory; |
| 2612 | defer a.setArrayList(list); | 2649 | return ensureTotalCapacity(a, new_capacity); |
| 2613 | return list.ensureUnusedCapacity(a.allocator, additional_count); | ||
| 2614 | } | 2650 | } |
| 2615 | 2651 | ||
| 2616 | pub fn ensureTotalCapacity(a: *Allocating, new_capacity: usize) Allocator.Error!void { | 2652 | pub fn ensureTotalCapacity(a: *Allocating, new_capacity: usize) Allocator.Error!void { |
| 2617 | var list = a.toArrayList(); | 2653 | return ensureTotalCapacityPrecise(a, ArrayList(u8).growCapacity(a.writer.buffer.len, new_capacity)); |
| 2618 | defer a.setArrayList(list); | ||
| 2619 | return list.ensureTotalCapacity(a.allocator, new_capacity); | ||
| 2620 | } | 2654 | } |
| 2621 | 2655 | ||
| 2622 | pub fn toOwnedSlice(a: *Allocating) error{OutOfMemory}![]u8 { | 2656 | pub fn ensureTotalCapacityPrecise(a: *Allocating, new_capacity: usize) Allocator.Error!void { |
| 2623 | var list = a.toArrayList(); | 2657 | const old_memory = a.writer.buffer; |
| 2624 | defer a.setArrayList(list); | 2658 | if (old_memory.len >= new_capacity) return; |
| 2625 | return list.toOwnedSlice(a.allocator); | 2659 | assert(new_capacity != 0); |
| 2660 | const alignment = a.alignment; | ||
| 2661 | if (old_memory.len > 0) { | ||
| 2662 | if (a.allocator.rawRemap(old_memory, alignment, new_capacity, @returnAddress())) |new| { | ||
| 2663 | a.writer.buffer = new[0..new_capacity]; | ||
| 2664 | return; | ||
| 2665 | } | ||
| 2666 | } | ||
| 2667 | const new_memory = (a.allocator.rawAlloc(new_capacity, alignment, @returnAddress()) orelse | ||
| 2668 | return error.OutOfMemory)[0..new_capacity]; | ||
| 2669 | const saved = old_memory[0..a.writer.end]; | ||
| 2670 | @memcpy(new_memory[0..saved.len], saved); | ||
| 2671 | if (old_memory.len != 0) a.allocator.rawFree(old_memory, alignment, @returnAddress()); | ||
| 2672 | a.writer.buffer = new_memory; | ||
| 2673 | } | ||
| 2674 | |||
| 2675 | pub fn toOwnedSlice(a: *Allocating) Allocator.Error![]u8 { | ||
| 2676 | const old_memory = a.writer.buffer; | ||
| 2677 | const alignment = a.alignment; | ||
| 2678 | const buffered_len = a.writer.end; | ||
| 2679 | |||
| 2680 | if (old_memory.len > 0) { | ||
| 2681 | if (buffered_len == 0) { | ||
| 2682 | a.allocator.rawFree(old_memory, alignment, @returnAddress()); | ||
| 2683 | a.writer.buffer = &.{}; | ||
| 2684 | a.writer.end = 0; | ||
| 2685 | return old_memory[0..0]; | ||
| 2686 | } else if (a.allocator.rawRemap(old_memory, alignment, buffered_len, @returnAddress())) |new| { | ||
| 2687 | a.writer.buffer = &.{}; | ||
| 2688 | a.writer.end = 0; | ||
| 2689 | return new[0..buffered_len]; | ||
| 2690 | } | ||
| 2691 | } | ||
| 2692 | |||
| 2693 | if (buffered_len == 0) | ||
| 2694 | return a.writer.buffer[0..0]; | ||
| 2695 | |||
| 2696 | const new_memory = (a.allocator.rawAlloc(buffered_len, alignment, @returnAddress()) orelse | ||
| 2697 | return error.OutOfMemory)[0..buffered_len]; | ||
| 2698 | @memcpy(new_memory, old_memory[0..buffered_len]); | ||
| 2699 | if (old_memory.len != 0) a.allocator.rawFree(old_memory, alignment, @returnAddress()); | ||
| 2700 | a.writer.buffer = &.{}; | ||
| 2701 | a.writer.end = 0; | ||
| 2702 | return new_memory; | ||
| 2626 | } | 2703 | } |
| 2627 | 2704 | ||
| 2628 | pub fn toOwnedSliceSentinel(a: *Allocating, comptime sentinel: u8) error{OutOfMemory}![:sentinel]u8 { | 2705 | pub fn toOwnedSliceSentinel(a: *Allocating, comptime sentinel: u8) Allocator.Error![:sentinel]u8 { |
| 2629 | const gpa = a.allocator; | 2706 | // This addition can never overflow because `a.writer.buffer` can never occupy the whole address space. |
| 2630 | var list = @This().toArrayList(a); | 2707 | try ensureTotalCapacityPrecise(a, a.writer.end + 1); |
| 2631 | defer a.setArrayList(list); | 2708 | a.writer.buffer[a.writer.end] = sentinel; |
| 2632 | return list.toOwnedSliceSentinel(gpa, sentinel); | 2709 | a.writer.end += 1; |
| 2710 | errdefer a.writer.end -= 1; | ||
| 2711 | const result = try toOwnedSlice(a); | ||
| 2712 | return result[0 .. result.len - 1 :sentinel]; | ||
| 2633 | } | 2713 | } |
| 2634 | 2714 | ||
| 2635 | pub fn written(a: *Allocating) []u8 { | 2715 | pub fn written(a: *Allocating) []u8 { |
| ... | @@ -2646,57 +2726,50 @@ pub const Allocating = struct { | ... | @@ -2646,57 +2726,50 @@ pub const Allocating = struct { |
| 2646 | 2726 | ||
| 2647 | fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize { | 2727 | fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize { |
| 2648 | const a: *Allocating = @fieldParentPtr("writer", w); | 2728 | const a: *Allocating = @fieldParentPtr("writer", w); |
| 2649 | const gpa = a.allocator; | ||
| 2650 | const pattern = data[data.len - 1]; | 2729 | const pattern = data[data.len - 1]; |
| 2651 | const splat_len = pattern.len * splat; | 2730 | const splat_len = pattern.len * splat; |
| 2652 | var list = a.toArrayList(); | 2731 | const start_len = a.writer.end; |
| 2653 | defer setArrayList(a, list); | ||
| 2654 | const start_len = list.items.len; | ||
| 2655 | assert(data.len != 0); | 2732 | assert(data.len != 0); |
| 2656 | for (data) |bytes| { | 2733 | for (data) |bytes| { |
| 2657 | list.ensureUnusedCapacity(gpa, bytes.len + splat_len + 1) catch return error.WriteFailed; | 2734 | a.ensureUnusedCapacity(bytes.len + splat_len + 1) catch return error.WriteFailed; |
| 2658 | list.appendSliceAssumeCapacity(bytes); | 2735 | @memcpy(a.writer.buffer[a.writer.end..][0..bytes.len], bytes); |
| 2736 | a.writer.end += bytes.len; | ||
| 2659 | } | 2737 | } |
| 2660 | if (splat == 0) { | 2738 | if (splat == 0) { |
| 2661 | list.items.len -= pattern.len; | 2739 | a.writer.end -= pattern.len; |
| 2662 | } else switch (pattern.len) { | 2740 | } else switch (pattern.len) { |
| 2663 | 0 => {}, | 2741 | 0 => {}, |
| 2664 | 1 => list.appendNTimesAssumeCapacity(pattern[0], splat - 1), | 2742 | 1 => { |
| 2665 | else => for (0..splat - 1) |_| list.appendSliceAssumeCapacity(pattern), | 2743 | @memset(a.writer.buffer[a.writer.end..][0 .. splat - 1], pattern[0]); |
| 2744 | a.writer.end += splat - 1; | ||
| 2745 | }, | ||
| 2746 | else => for (0..splat - 1) |_| { | ||
| 2747 | @memcpy(a.writer.buffer[a.writer.end..][0..pattern.len], pattern); | ||
| 2748 | a.writer.end += pattern.len; | ||
| 2749 | }, | ||
| 2666 | } | 2750 | } |
| 2667 | return list.items.len - start_len; | 2751 | return a.writer.end - start_len; |
| 2668 | } | 2752 | } |
| 2669 | 2753 | ||
| 2670 | fn sendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize { | 2754 | fn sendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize { |
| 2671 | if (File.Handle == void) return error.Unimplemented; | 2755 | if (File.Handle == void) return error.Unimplemented; |
| 2672 | if (limit == .nothing) return 0; | 2756 | if (limit == .nothing) return 0; |
| 2673 | const a: *Allocating = @fieldParentPtr("writer", w); | 2757 | const a: *Allocating = @fieldParentPtr("writer", w); |
| 2674 | const gpa = a.allocator; | ||
| 2675 | var list = a.toArrayList(); | ||
| 2676 | defer setArrayList(a, list); | ||
| 2677 | const pos = file_reader.logicalPos(); | 2758 | const pos = file_reader.logicalPos(); |
| 2678 | const additional = if (file_reader.getSize()) |size| size - pos else |_| std.atomic.cache_line; | 2759 | const additional = if (file_reader.getSize()) |size| size - pos else |_| std.atomic.cache_line; |
| 2679 | if (additional == 0) return error.EndOfStream; | 2760 | if (additional == 0) return error.EndOfStream; |
| 2680 | list.ensureUnusedCapacity(gpa, limit.minInt64(additional)) catch return error.WriteFailed; | 2761 | a.ensureUnusedCapacity(limit.minInt64(additional)) catch return error.WriteFailed; |
| 2681 | const dest = limit.slice(list.unusedCapacitySlice()); | 2762 | const dest = limit.slice(a.writer.buffer[a.writer.end..]); |
| 2682 | const n = try file_reader.read(dest); | 2763 | const n = try file_reader.read(dest); |
| 2683 | list.items.len += n; | 2764 | a.writer.end += n; |
| 2684 | return n; | 2765 | return n; |
| 2685 | } | 2766 | } |
| 2686 | 2767 | ||
| 2687 | fn growingRebase(w: *Writer, preserve: usize, minimum_len: usize) Error!void { | 2768 | fn growingRebase(w: *Writer, preserve: usize, minimum_len: usize) Error!void { |
| 2688 | const a: *Allocating = @fieldParentPtr("writer", w); | 2769 | const a: *Allocating = @fieldParentPtr("writer", w); |
| 2689 | const gpa = a.allocator; | ||
| 2690 | var list = a.toArrayList(); | ||
| 2691 | defer setArrayList(a, list); | ||
| 2692 | const total = std.math.add(usize, preserve, minimum_len) catch return error.WriteFailed; | 2770 | const total = std.math.add(usize, preserve, minimum_len) catch return error.WriteFailed; |
| 2693 | list.ensureTotalCapacity(gpa, total) catch return error.WriteFailed; | 2771 | a.ensureTotalCapacity(total) catch return error.WriteFailed; |
| 2694 | list.ensureUnusedCapacity(gpa, minimum_len) catch return error.WriteFailed; | 2772 | a.ensureUnusedCapacity(minimum_len) catch return error.WriteFailed; |
| 2695 | } | ||
| 2696 | |||
| 2697 | fn setArrayList(a: *Allocating, list: ArrayList(u8)) void { | ||
| 2698 | a.writer.buffer = list.allocatedSlice(); | ||
| 2699 | a.writer.end = list.items.len; | ||
| 2700 | } | 2773 | } |
| 2701 | 2774 | ||
| 2702 | test Allocating { | 2775 | test Allocating { |
lib/std/Thread.zig+1-1| ... | @@ -282,7 +282,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co | ... | @@ -282,7 +282,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co |
| 282 | defer file.close(); | 282 | defer file.close(); |
| 283 | 283 | ||
| 284 | var file_reader = file.readerStreaming(&.{}); | 284 | var file_reader = file.readerStreaming(&.{}); |
| 285 | const data_len = file_reader.readSliceShort(buffer_ptr[0 .. max_name_len + 1]) catch |err| switch (err) { | 285 | const data_len = file_reader.interface.readSliceShort(buffer_ptr[0 .. max_name_len + 1]) catch |err| switch (err) { |
| 286 | error.ReadFailed => return file_reader.err.?, | 286 | error.ReadFailed => return file_reader.err.?, |
| 287 | }; | 287 | }; |
| 288 | return if (data_len >= 1) buffer[0 .. data_len - 1] else null; | 288 | return if (data_len >= 1) buffer[0 .. data_len - 1] else null; |
lib/std/array_list.zig+3-2| ... | @@ -664,9 +664,10 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { | ... | @@ -664,9 +664,10 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 664 | 664 | ||
| 665 | /// The caller owns the returned memory. ArrayList becomes empty. | 665 | /// The caller owns the returned memory. ArrayList becomes empty. |
| 666 | pub fn toOwnedSliceSentinel(self: *Self, gpa: Allocator, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) { | 666 | pub fn toOwnedSliceSentinel(self: *Self, gpa: Allocator, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) { |
| 667 | // This addition can never overflow because `self.items` can never occupy the whole address space | 667 | // This addition can never overflow because `self.items` can never occupy the whole address space. |
| 668 | try self.ensureTotalCapacityPrecise(gpa, self.items.len + 1); | 668 | try self.ensureTotalCapacityPrecise(gpa, self.items.len + 1); |
| 669 | self.appendAssumeCapacity(sentinel); | 669 | self.appendAssumeCapacity(sentinel); |
| 670 | errdefer self.items.len -= 1; | ||
| 670 | const result = try self.toOwnedSlice(gpa); | 671 | const result = try self.toOwnedSlice(gpa); |
| 671 | return result[0 .. result.len - 1 :sentinel]; | 672 | return result[0 .. result.len - 1 :sentinel]; |
| 672 | } | 673 | } |
| ... | @@ -1361,7 +1362,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { | ... | @@ -1361,7 +1362,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1361 | 1362 | ||
| 1362 | /// Called when memory growth is necessary. Returns a capacity larger than | 1363 | /// Called when memory growth is necessary. Returns a capacity larger than |
| 1363 | /// minimum that grows super-linearly. | 1364 | /// minimum that grows super-linearly. |
| 1364 | fn growCapacity(current: usize, minimum: usize) usize { | 1365 | pub fn growCapacity(current: usize, minimum: usize) usize { |
| 1365 | var new = current; | 1366 | var new = current; |
| 1366 | while (true) { | 1367 | while (true) { |
| 1367 | new +|= new / 2 + init_capacity; | 1368 | new +|= new / 2 + init_capacity; |
lib/std/debug/Dwarf/expression.zig+4-4| ... | @@ -851,7 +851,7 @@ pub fn Builder(comptime options: Options) type { | ... | @@ -851,7 +851,7 @@ pub fn Builder(comptime options: Options) type { |
| 851 | }, | 851 | }, |
| 852 | .signed => { | 852 | .signed => { |
| 853 | try writer.writeByte(OP.consts); | 853 | try writer.writeByte(OP.consts); |
| 854 | try leb.writeIleb128(writer, value); | 854 | try writer.writeLeb128(value); |
| 855 | }, | 855 | }, |
| 856 | }, | 856 | }, |
| 857 | } | 857 | } |
| ... | @@ -885,19 +885,19 @@ pub fn Builder(comptime options: Options) type { | ... | @@ -885,19 +885,19 @@ pub fn Builder(comptime options: Options) type { |
| 885 | // 2.5.1.2: Register Values | 885 | // 2.5.1.2: Register Values |
| 886 | pub fn writeFbreg(writer: *Writer, offset: anytype) !void { | 886 | pub fn writeFbreg(writer: *Writer, offset: anytype) !void { |
| 887 | try writer.writeByte(OP.fbreg); | 887 | try writer.writeByte(OP.fbreg); |
| 888 | try leb.writeIleb128(writer, offset); | 888 | try writer.writeSleb128(offset); |
| 889 | } | 889 | } |
| 890 | 890 | ||
| 891 | pub fn writeBreg(writer: *Writer, register: u8, offset: anytype) !void { | 891 | pub fn writeBreg(writer: *Writer, register: u8, offset: anytype) !void { |
| 892 | if (register > 31) return error.InvalidRegister; | 892 | if (register > 31) return error.InvalidRegister; |
| 893 | try writer.writeByte(OP.breg0 + register); | 893 | try writer.writeByte(OP.breg0 + register); |
| 894 | try leb.writeIleb128(writer, offset); | 894 | try writer.writeSleb128(offset); |
| 895 | } | 895 | } |
| 896 | 896 | ||
| 897 | pub fn writeBregx(writer: *Writer, register: anytype, offset: anytype) !void { | 897 | pub fn writeBregx(writer: *Writer, register: anytype, offset: anytype) !void { |
| 898 | try writer.writeByte(OP.bregx); | 898 | try writer.writeByte(OP.bregx); |
| 899 | try writer.writeUleb128(register); | 899 | try writer.writeUleb128(register); |
| 900 | try leb.writeIleb128(writer, offset); | 900 | try writer.writeSleb128(offset); |
| 901 | } | 901 | } |
| 902 | 902 | ||
| 903 | pub fn writeRegvalType(writer: *Writer, register: anytype, offset: anytype) !void { | 903 | pub fn writeRegvalType(writer: *Writer, register: anytype, offset: anytype) !void { |
lib/std/fs/Dir.zig+48-30| ... | @@ -1977,41 +1977,59 @@ pub fn readFile(self: Dir, file_path: []const u8, buffer: []u8) ![]u8 { | ... | @@ -1977,41 +1977,59 @@ pub fn readFile(self: Dir, file_path: []const u8, buffer: []u8) ![]u8 { |
| 1977 | return buffer[0..end_index]; | 1977 | return buffer[0..end_index]; |
| 1978 | } | 1978 | } |
| 1979 | 1979 | ||
| 1980 | /// On success, caller owns returned buffer. | 1980 | pub const ReadFileAllocError = File.OpenError || File.ReadError || Allocator.Error || error{ |
| 1981 | /// If the file is larger than `max_bytes`, returns `error.FileTooBig`. | 1981 | /// File size reached or exceeded the provided limit. |
| 1982 | /// On Windows, `file_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). | 1982 | StreamTooLong, |
| 1983 | /// On WASI, `file_path` should be encoded as valid UTF-8. | 1983 | }; |
| 1984 | /// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. | 1984 | |
| 1985 | pub fn readFileAlloc(self: Dir, allocator: mem.Allocator, file_path: []const u8, max_bytes: usize) ![]u8 { | 1985 | /// Reads all the bytes from the named file. On success, caller owns returned |
| 1986 | return self.readFileAllocOptions(allocator, file_path, max_bytes, null, .of(u8), null); | 1986 | /// buffer. |
| 1987 | /// | ||
| 1988 | /// If the file size is already known, a better alternative is to initialize a | ||
| 1989 | /// `File.Reader`. | ||
| 1990 | /// | ||
| 1991 | /// If the file size cannot be obtained, an error is returned. If | ||
| 1992 | /// this is a realistic possibility, a better alternative is to initialize a | ||
| 1993 | /// `File.Reader` which handles this seamlessly. | ||
| 1994 | pub fn readFileAlloc( | ||
| 1995 | dir: Dir, | ||
| 1996 | /// On Windows, should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). | ||
| 1997 | /// On WASI, should be encoded as valid UTF-8. | ||
| 1998 | /// On other platforms, an opaque sequence of bytes with no particular encoding. | ||
| 1999 | sub_path: []const u8, | ||
| 2000 | /// Used to allocate the result. | ||
| 2001 | gpa: Allocator, | ||
| 2002 | /// If reached or exceeded, `error.StreamTooLong` is returned instead. | ||
| 2003 | limit: std.Io.Limit, | ||
| 2004 | ) ReadFileAllocError![]u8 { | ||
| 2005 | return readFileAllocOptions(dir, sub_path, gpa, limit, .of(u8), null); | ||
| 1987 | } | 2006 | } |
| 1988 | 2007 | ||
| 1989 | /// On success, caller owns returned buffer. | 2008 | /// Reads all the bytes from the named file. On success, caller owns returned |
| 1990 | /// If the file is larger than `max_bytes`, returns `error.FileTooBig`. | 2009 | /// buffer. |
| 1991 | /// If `size_hint` is specified the initial buffer size is calculated using | 2010 | /// |
| 1992 | /// that value, otherwise the effective file size is used instead. | 2011 | /// If the file size is already known, a better alternative is to initialize a |
| 1993 | /// Allows specifying alignment and a sentinel value. | 2012 | /// `File.Reader`. |
| 1994 | /// On Windows, `file_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). | ||
| 1995 | /// On WASI, `file_path` should be encoded as valid UTF-8. | ||
| 1996 | /// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. | ||
| 1997 | pub fn readFileAllocOptions( | 2013 | pub fn readFileAllocOptions( |
| 1998 | self: Dir, | 2014 | dir: Dir, |
| 1999 | allocator: mem.Allocator, | 2015 | /// On Windows, should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). |
| 2000 | file_path: []const u8, | 2016 | /// On WASI, should be encoded as valid UTF-8. |
| 2001 | max_bytes: usize, | 2017 | /// On other platforms, an opaque sequence of bytes with no particular encoding. |
| 2002 | size_hint: ?usize, | 2018 | sub_path: []const u8, |
| 2019 | /// Used to allocate the result. | ||
| 2020 | gpa: Allocator, | ||
| 2021 | /// If reached or exceeded, `error.StreamTooLong` is returned instead. | ||
| 2022 | limit: std.Io.Limit, | ||
| 2003 | comptime alignment: std.mem.Alignment, | 2023 | comptime alignment: std.mem.Alignment, |
| 2004 | comptime optional_sentinel: ?u8, | 2024 | comptime sentinel: ?u8, |
| 2005 | ) !(if (optional_sentinel) |s| [:s]align(alignment.toByteUnits()) u8 else []align(alignment.toByteUnits()) u8) { | 2025 | ) ReadFileAllocError!(if (sentinel) |s| [:s]align(alignment.toByteUnits()) u8 else []align(alignment.toByteUnits()) u8) { |
| 2006 | var file = try self.openFile(file_path, .{}); | 2026 | var file = try dir.openFile(sub_path, .{}); |
| 2007 | defer file.close(); | 2027 | defer file.close(); |
| 2008 | 2028 | var file_reader = file.reader(&.{}); | |
| 2009 | // If the file size doesn't fit a usize it'll be certainly greater than | 2029 | return file_reader.interface.allocRemainingAlignedSentinel(gpa, limit, alignment, sentinel) catch |err| switch (err) { |
| 2010 | // `max_bytes` | 2030 | error.ReadFailed => return file_reader.err.?, |
| 2011 | const stat_size = size_hint orelse std.math.cast(usize, try file.getEndPos()) orelse | 2031 | error.OutOfMemory, error.StreamTooLong => |e| return e, |
| 2012 | return error.FileTooBig; | 2032 | }; |
| 2013 | |||
| 2014 | return file.readToEndAllocOptions(allocator, max_bytes, stat_size, alignment, optional_sentinel); | ||
| 2015 | } | 2033 | } |
| 2016 | 2034 | ||
| 2017 | pub const DeleteTreeError = error{ | 2035 | pub const DeleteTreeError = error{ |
lib/std/fs/test.zig+35-25| ... | @@ -676,37 +676,47 @@ test "Dir.realpath smoke test" { | ... | @@ -676,37 +676,47 @@ test "Dir.realpath smoke test" { |
| 676 | }.impl); | 676 | }.impl); |
| 677 | } | 677 | } |
| 678 | 678 | ||
| 679 | test "readAllAlloc" { | 679 | test "readFileAlloc" { |
| 680 | var tmp_dir = tmpDir(.{}); | 680 | var tmp_dir = tmpDir(.{}); |
| 681 | defer tmp_dir.cleanup(); | 681 | defer tmp_dir.cleanup(); |
| 682 | 682 | ||
| 683 | var file = try tmp_dir.dir.createFile("test_file", .{ .read = true }); | 683 | var file = try tmp_dir.dir.createFile("test_file", .{ .read = true }); |
| 684 | defer file.close(); | 684 | defer file.close(); |
| 685 | 685 | ||
| 686 | const buf1 = try file.readToEndAlloc(testing.allocator, 1024); | 686 | const buf1 = try tmp_dir.dir.readFileAlloc("test_file", testing.allocator, .limited(1024)); |
| 687 | defer testing.allocator.free(buf1); | 687 | defer testing.allocator.free(buf1); |
| 688 | try testing.expectEqual(@as(usize, 0), buf1.len); | 688 | try testing.expectEqualStrings("", buf1); |
| 689 | 689 | ||
| 690 | const write_buf: []const u8 = "this is a test.\nthis is a test.\nthis is a test.\nthis is a test.\n"; | 690 | const write_buf: []const u8 = "this is a test.\nthis is a test.\nthis is a test.\nthis is a test.\n"; |
| 691 | try file.writeAll(write_buf); | 691 | try file.writeAll(write_buf); |
| 692 | try file.seekTo(0); | 692 | |
| 693 | 693 | { | |
| 694 | // max_bytes > file_size | 694 | // max_bytes > file_size |
| 695 | const buf2 = try file.readToEndAlloc(testing.allocator, 1024); | 695 | const buf2 = try tmp_dir.dir.readFileAlloc("test_file", testing.allocator, .limited(1024)); |
| 696 | defer testing.allocator.free(buf2); | 696 | defer testing.allocator.free(buf2); |
| 697 | try testing.expectEqual(write_buf.len, buf2.len); | 697 | try testing.expectEqualStrings(write_buf, buf2); |
| 698 | try testing.expectEqualStrings(write_buf, buf2); | 698 | } |
| 699 | try file.seekTo(0); | 699 | |
| 700 | 700 | { | |
| 701 | // max_bytes == file_size | 701 | // max_bytes == file_size |
| 702 | const buf3 = try file.readToEndAlloc(testing.allocator, write_buf.len); | 702 | try testing.expectError( |
| 703 | defer testing.allocator.free(buf3); | 703 | error.StreamTooLong, |
| 704 | try testing.expectEqual(write_buf.len, buf3.len); | 704 | tmp_dir.dir.readFileAlloc("test_file", testing.allocator, .limited(write_buf.len)), |
| 705 | try testing.expectEqualStrings(write_buf, buf3); | 705 | ); |
| 706 | try file.seekTo(0); | 706 | } |
| 707 | |||
| 708 | { | ||
| 709 | // max_bytes == file_size + 1 | ||
| 710 | const buf2 = try tmp_dir.dir.readFileAlloc("test_file", testing.allocator, .limited(write_buf.len + 1)); | ||
| 711 | defer testing.allocator.free(buf2); | ||
| 712 | try testing.expectEqualStrings(write_buf, buf2); | ||
| 713 | } | ||
| 707 | 714 | ||
| 708 | // max_bytes < file_size | 715 | // max_bytes < file_size |
| 709 | try testing.expectError(error.FileTooBig, file.readToEndAlloc(testing.allocator, write_buf.len - 1)); | 716 | try testing.expectError( |
| 717 | error.StreamTooLong, | ||
| 718 | tmp_dir.dir.readFileAlloc("test_file", testing.allocator, .limited(write_buf.len - 1)), | ||
| 719 | ); | ||
| 710 | } | 720 | } |
| 711 | 721 | ||
| 712 | test "Dir.statFile" { | 722 | test "Dir.statFile" { |
| ... | @@ -778,16 +788,16 @@ test "file operations on directories" { | ... | @@ -778,16 +788,16 @@ test "file operations on directories" { |
| 778 | switch (native_os) { | 788 | switch (native_os) { |
| 779 | .dragonfly, .netbsd => { | 789 | .dragonfly, .netbsd => { |
| 780 | // no error when reading a directory. See https://github.com/ziglang/zig/issues/5732 | 790 | // no error when reading a directory. See https://github.com/ziglang/zig/issues/5732 |
| 781 | const buf = try ctx.dir.readFileAlloc(testing.allocator, test_dir_name, std.math.maxInt(usize)); | 791 | const buf = try ctx.dir.readFileAlloc(test_dir_name, testing.allocator, .unlimited); |
| 782 | testing.allocator.free(buf); | 792 | testing.allocator.free(buf); |
| 783 | }, | 793 | }, |
| 784 | .wasi => { | 794 | .wasi => { |
| 785 | // WASI return EBADF, which gets mapped to NotOpenForReading. | 795 | // WASI return EBADF, which gets mapped to NotOpenForReading. |
| 786 | // See https://github.com/bytecodealliance/wasmtime/issues/1935 | 796 | // See https://github.com/bytecodealliance/wasmtime/issues/1935 |
| 787 | try testing.expectError(error.NotOpenForReading, ctx.dir.readFileAlloc(testing.allocator, test_dir_name, std.math.maxInt(usize))); | 797 | try testing.expectError(error.NotOpenForReading, ctx.dir.readFileAlloc(test_dir_name, testing.allocator, .unlimited)); |
| 788 | }, | 798 | }, |
| 789 | else => { | 799 | else => { |
| 790 | try testing.expectError(error.IsDir, ctx.dir.readFileAlloc(testing.allocator, test_dir_name, std.math.maxInt(usize))); | 800 | try testing.expectError(error.IsDir, ctx.dir.readFileAlloc(test_dir_name, testing.allocator, .unlimited)); |
| 791 | }, | 801 | }, |
| 792 | } | 802 | } |
| 793 | 803 | ||
| ... | @@ -1564,7 +1574,7 @@ test "copyFile" { | ... | @@ -1564,7 +1574,7 @@ test "copyFile" { |
| 1564 | } | 1574 | } |
| 1565 | 1575 | ||
| 1566 | fn expectFileContents(dir: Dir, file_path: []const u8, data: []const u8) !void { | 1576 | fn expectFileContents(dir: Dir, file_path: []const u8, data: []const u8) !void { |
| 1567 | const contents = try dir.readFileAlloc(testing.allocator, file_path, 1000); | 1577 | const contents = try dir.readFileAlloc(file_path, testing.allocator, .limited(1000)); |
| 1568 | defer testing.allocator.free(contents); | 1578 | defer testing.allocator.free(contents); |
| 1569 | 1579 | ||
| 1570 | try testing.expectEqualSlices(u8, data, contents); | 1580 | try testing.expectEqualSlices(u8, data, contents); |
| ... | @@ -1587,7 +1597,7 @@ test "AtomicFile" { | ... | @@ -1587,7 +1597,7 @@ test "AtomicFile" { |
| 1587 | try af.file_writer.interface.writeAll(test_content); | 1597 | try af.file_writer.interface.writeAll(test_content); |
| 1588 | try af.finish(); | 1598 | try af.finish(); |
| 1589 | } | 1599 | } |
| 1590 | const content = try ctx.dir.readFileAlloc(allocator, test_out_file, 9999); | 1600 | const content = try ctx.dir.readFileAlloc(test_out_file, allocator, .limited(9999)); |
| 1591 | try testing.expectEqualStrings(test_content, content); | 1601 | try testing.expectEqualStrings(test_content, content); |
| 1592 | 1602 | ||
| 1593 | try ctx.dir.deleteFile(test_out_file); | 1603 | try ctx.dir.deleteFile(test_out_file); |
| ... | @@ -2004,7 +2014,7 @@ test "invalid UTF-8/WTF-8 paths" { | ... | @@ -2004,7 +2014,7 @@ test "invalid UTF-8/WTF-8 paths" { |
| 2004 | } | 2014 | } |
| 2005 | 2015 | ||
| 2006 | try testing.expectError(expected_err, ctx.dir.readFile(invalid_path, &[_]u8{})); | 2016 | try testing.expectError(expected_err, ctx.dir.readFile(invalid_path, &[_]u8{})); |
| 2007 | try testing.expectError(expected_err, ctx.dir.readFileAlloc(testing.allocator, invalid_path, 0)); | 2017 | try testing.expectError(expected_err, ctx.dir.readFileAlloc(invalid_path, testing.allocator, .limited(0))); |
| 2008 | 2018 | ||
| 2009 | try testing.expectError(expected_err, ctx.dir.deleteTree(invalid_path)); | 2019 | try testing.expectError(expected_err, ctx.dir.deleteTree(invalid_path)); |
| 2010 | try testing.expectError(expected_err, ctx.dir.deleteTreeMinStackSize(invalid_path)); | 2020 | try testing.expectError(expected_err, ctx.dir.deleteTreeMinStackSize(invalid_path)); |
lib/std/zig/LibCInstallation.zig+1-1| ... | @@ -43,7 +43,7 @@ pub fn parse( | ... | @@ -43,7 +43,7 @@ pub fn parse( |
| 43 | } | 43 | } |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | const contents = try std.fs.cwd().readFileAlloc(allocator, libc_file, std.math.maxInt(usize)); | 46 | const contents = try std.fs.cwd().readFileAlloc(libc_file, allocator, .limited(std.math.maxInt(usize))); |
| 47 | defer allocator.free(contents); | 47 | defer allocator.free(contents); |
| 48 | 48 | ||
| 49 | var it = std.mem.tokenizeScalar(u8, contents, '\n'); | 49 | var it = std.mem.tokenizeScalar(u8, contents, '\n'); |
lib/std/zig/WindowsSdk.zig+1-1| ... | @@ -766,7 +766,7 @@ const MsvcLibDir = struct { | ... | @@ -766,7 +766,7 @@ const MsvcLibDir = struct { |
| 766 | writer.writeByte(std.fs.path.sep) catch unreachable; | 766 | writer.writeByte(std.fs.path.sep) catch unreachable; |
| 767 | writer.writeAll("state.json") catch unreachable; | 767 | writer.writeAll("state.json") catch unreachable; |
| 768 | 768 | ||
| 769 | const json_contents = instances_dir.readFileAlloc(allocator, writer.buffered(), std.math.maxInt(usize)) catch continue; | 769 | const json_contents = instances_dir.readFileAlloc(writer.buffered(), allocator, .limited(std.math.maxInt(usize))) catch continue; |
| 770 | defer allocator.free(json_contents); | 770 | defer allocator.free(json_contents); |
| 771 | 771 | ||
| 772 | var parsed = std.json.parseFromSlice(std.json.Value, allocator, json_contents, .{}) catch continue; | 772 | var parsed = std.json.parseFromSlice(std.json.Value, allocator, json_contents, .{}) catch continue; |
src/Compilation.zig+1-1| ... | @@ -6576,7 +6576,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 | ... | @@ -6576,7 +6576,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 6576 | // Read depfile and update cache manifest | 6576 | // Read depfile and update cache manifest |
| 6577 | { | 6577 | { |
| 6578 | const dep_basename = fs.path.basename(out_dep_path); | 6578 | const dep_basename = fs.path.basename(out_dep_path); |
| 6579 | const dep_file_contents = try zig_cache_tmp_dir.readFileAlloc(arena, dep_basename, 50 * 1024 * 1024); | 6579 | const dep_file_contents = try zig_cache_tmp_dir.readFileAlloc(dep_basename, arena, .limited(50 * 1024 * 1024)); |
| 6580 | defer arena.free(dep_file_contents); | 6580 | defer arena.free(dep_file_contents); |
| 6581 | 6581 | ||
| 6582 | const value = try std.json.parseFromSliceLeaky(std.json.Value, arena, dep_file_contents, .{}); | 6582 | const value = try std.json.parseFromSliceLeaky(std.json.Value, arena, dep_file_contents, .{}); |
src/Package/Fetch.zig+2-3| ... | @@ -655,10 +655,9 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { | ... | @@ -655,10 +655,9 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { |
| 655 | const eb = &f.error_bundle; | 655 | const eb = &f.error_bundle; |
| 656 | const arena = f.arena.allocator(); | 656 | const arena = f.arena.allocator(); |
| 657 | const manifest_bytes = pkg_root.root_dir.handle.readFileAllocOptions( | 657 | const manifest_bytes = pkg_root.root_dir.handle.readFileAllocOptions( |
| 658 | arena, | ||
| 659 | try fs.path.join(arena, &.{ pkg_root.sub_path, Manifest.basename }), | 658 | try fs.path.join(arena, &.{ pkg_root.sub_path, Manifest.basename }), |
| 660 | Manifest.max_bytes, | 659 | arena, |
| 661 | null, | 660 | .limited(Manifest.max_bytes), |
| 662 | .@"1", | 661 | .@"1", |
| 663 | 0, | 662 | 0, |
| 664 | ) catch |err| switch (err) { | 663 | ) catch |err| switch (err) { |
src/Package/Fetch/git.zig+2-2| ... | @@ -1599,7 +1599,7 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void | ... | @@ -1599,7 +1599,7 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void |
| 1599 | const max_file_size = 8192; | 1599 | const max_file_size = 8192; |
| 1600 | 1600 | ||
| 1601 | if (!skip_checksums) { | 1601 | if (!skip_checksums) { |
| 1602 | const index_file_data = try git_dir.dir.readFileAlloc(testing.allocator, "testrepo.idx", max_file_size); | 1602 | const index_file_data = try git_dir.dir.readFileAlloc("testrepo.idx", testing.allocator, .limited(max_file_size)); |
| 1603 | defer testing.allocator.free(index_file_data); | 1603 | defer testing.allocator.free(index_file_data); |
| 1604 | // testrepo.idx is generated by Git. The index created by this file should | 1604 | // testrepo.idx is generated by Git. The index created by this file should |
| 1605 | // match it exactly. Running `git verify-pack -v testrepo.pack` can verify | 1605 | // match it exactly. Running `git verify-pack -v testrepo.pack` can verify |
| ... | @@ -1675,7 +1675,7 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void | ... | @@ -1675,7 +1675,7 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void |
| 1675 | \\revision 19 | 1675 | \\revision 19 |
| 1676 | \\ | 1676 | \\ |
| 1677 | ; | 1677 | ; |
| 1678 | const actual_file_contents = try worktree.dir.readFileAlloc(testing.allocator, "file", max_file_size); | 1678 | const actual_file_contents = try worktree.dir.readFileAlloc("file", testing.allocator, .limited(max_file_size)); |
| 1679 | defer testing.allocator.free(actual_file_contents); | 1679 | defer testing.allocator.free(actual_file_contents); |
| 1680 | try testing.expectEqualStrings(expected_file_contents, actual_file_contents); | 1680 | try testing.expectEqualStrings(expected_file_contents, actual_file_contents); |
| 1681 | } | 1681 | } |
src/link/MachO.zig+1-1| ... | @@ -4361,7 +4361,7 @@ fn inferSdkVersion(comp: *Compilation, sdk_layout: SdkLayout) ?std.SemanticVersi | ... | @@ -4361,7 +4361,7 @@ fn inferSdkVersion(comp: *Compilation, sdk_layout: SdkLayout) ?std.SemanticVersi |
| 4361 | // The file/property is also available with vendored libc. | 4361 | // The file/property is also available with vendored libc. |
| 4362 | fn readSdkVersionFromSettings(arena: Allocator, dir: []const u8) ![]const u8 { | 4362 | fn readSdkVersionFromSettings(arena: Allocator, dir: []const u8) ![]const u8 { |
| 4363 | const sdk_path = try fs.path.join(arena, &.{ dir, "SDKSettings.json" }); | 4363 | const sdk_path = try fs.path.join(arena, &.{ dir, "SDKSettings.json" }); |
| 4364 | const contents = try fs.cwd().readFileAlloc(arena, sdk_path, std.math.maxInt(u16)); | 4364 | const contents = try fs.cwd().readFileAlloc(sdk_path, arena, .limited(std.math.maxInt(u16))); |
| 4365 | const parsed = try std.json.parseFromSlice(std.json.Value, arena, contents, .{}); | 4365 | const parsed = try std.json.parseFromSlice(std.json.Value, arena, contents, .{}); |
| 4366 | if (parsed.value.object.get("MinimalDisplayName")) |ver| return ver.string; | 4366 | if (parsed.value.object.get("MinimalDisplayName")) |ver| return ver.string; |
| 4367 | return error.SdkVersionFailure; | 4367 | return error.SdkVersionFailure; |
src/link/MachO/dyld_info/bind.zig+1-1| ... | @@ -647,7 +647,7 @@ fn setDylibOrdinal(ordinal: i16, writer: *std.Io.Writer) !void { | ... | @@ -647,7 +647,7 @@ fn setDylibOrdinal(ordinal: i16, writer: *std.Io.Writer) !void { |
| 647 | fn setAddend(addend: i64, writer: *std.Io.Writer) !void { | 647 | fn setAddend(addend: i64, writer: *std.Io.Writer) !void { |
| 648 | log.debug(">>> set addend: {x}", .{addend}); | 648 | log.debug(">>> set addend: {x}", .{addend}); |
| 649 | try writer.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB); | 649 | try writer.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB); |
| 650 | try std.leb.writeIleb128(writer, addend); | 650 | try writer.writeSleb128(addend); |
| 651 | } | 651 | } |
| 652 | 652 | ||
| 653 | fn doBind(writer: *std.Io.Writer) !void { | 653 | fn doBind(writer: *std.Io.Writer) !void { |
src/main.zig+5-6| ... | @@ -5443,7 +5443,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { | ... | @@ -5443,7 +5443,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 5443 | // that are missing. | 5443 | // that are missing. |
| 5444 | const s = fs.path.sep_str; | 5444 | const s = fs.path.sep_str; |
| 5445 | const tmp_sub_path = "tmp" ++ s ++ results_tmp_file_nonce; | 5445 | const tmp_sub_path = "tmp" ++ s ++ results_tmp_file_nonce; |
| 5446 | const stdout = dirs.local_cache.handle.readFileAlloc(arena, tmp_sub_path, 50 * 1024 * 1024) catch |err| { | 5446 | const stdout = dirs.local_cache.handle.readFileAlloc(tmp_sub_path, arena, .limited(50 * 1024 * 1024)) catch |err| { |
| 5447 | fatal("unable to read results of configure phase from '{f}{s}': {s}", .{ | 5447 | fatal("unable to read results of configure phase from '{f}{s}': {s}", .{ |
| 5448 | dirs.local_cache, tmp_sub_path, @errorName(err), | 5448 | dirs.local_cache, tmp_sub_path, @errorName(err), |
| 5449 | }); | 5449 | }); |
| ... | @@ -5826,7 +5826,7 @@ const ArgIteratorResponseFile = process.ArgIteratorGeneral(.{ .comments = true, | ... | @@ -5826,7 +5826,7 @@ const ArgIteratorResponseFile = process.ArgIteratorGeneral(.{ .comments = true, |
| 5826 | /// Initialize the arguments from a Response File. "*.rsp" | 5826 | /// Initialize the arguments from a Response File. "*.rsp" |
| 5827 | fn initArgIteratorResponseFile(allocator: Allocator, resp_file_path: []const u8) !ArgIteratorResponseFile { | 5827 | fn initArgIteratorResponseFile(allocator: Allocator, resp_file_path: []const u8) !ArgIteratorResponseFile { |
| 5828 | const max_bytes = 10 * 1024 * 1024; // 10 MiB of command line arguments is a reasonable limit | 5828 | const max_bytes = 10 * 1024 * 1024; // 10 MiB of command line arguments is a reasonable limit |
| 5829 | const cmd_line = try fs.cwd().readFileAlloc(allocator, resp_file_path, max_bytes); | 5829 | const cmd_line = try fs.cwd().readFileAlloc(resp_file_path, allocator, .limited(max_bytes)); |
| 5830 | errdefer allocator.free(cmd_line); | 5830 | errdefer allocator.free(cmd_line); |
| 5831 | 5831 | ||
| 5832 | return ArgIteratorResponseFile.initTakeOwnership(allocator, cmd_line); | 5832 | return ArgIteratorResponseFile.initTakeOwnership(allocator, cmd_line); |
| ... | @@ -7350,10 +7350,9 @@ fn loadManifest( | ... | @@ -7350,10 +7350,9 @@ fn loadManifest( |
| 7350 | ) !struct { Package.Manifest, Ast } { | 7350 | ) !struct { Package.Manifest, Ast } { |
| 7351 | const manifest_bytes = while (true) { | 7351 | const manifest_bytes = while (true) { |
| 7352 | break options.dir.readFileAllocOptions( | 7352 | break options.dir.readFileAllocOptions( |
| 7353 | arena, | ||
| 7354 | Package.Manifest.basename, | 7353 | Package.Manifest.basename, |
| 7355 | Package.Manifest.max_bytes, | 7354 | arena, |
| 7356 | null, | 7355 | .limited(Package.Manifest.max_bytes), |
| 7357 | .@"1", | 7356 | .@"1", |
| 7358 | 0, | 7357 | 0, |
| 7359 | ) catch |err| switch (err) { | 7358 | ) catch |err| switch (err) { |
| ... | @@ -7435,7 +7434,7 @@ const Templates = struct { | ... | @@ -7435,7 +7434,7 @@ const Templates = struct { |
| 7435 | } | 7434 | } |
| 7436 | 7435 | ||
| 7437 | const max_bytes = 10 * 1024 * 1024; | 7436 | const max_bytes = 10 * 1024 * 1024; |
| 7438 | const contents = templates.dir.readFileAlloc(arena, template_path, max_bytes) catch |err| { | 7437 | const contents = templates.dir.readFileAlloc(template_path, arena, .limited(max_bytes)) catch |err| { |
| 7439 | fatal("unable to read template file '{s}': {s}", .{ template_path, @errorName(err) }); | 7438 | fatal("unable to read template file '{s}': {s}", .{ template_path, @errorName(err) }); |
| 7440 | }; | 7439 | }; |
| 7441 | templates.buffer.clearRetainingCapacity(); | 7440 | templates.buffer.clearRetainingCapacity(); |
src/print_targets.zig+2-2| ... | @@ -24,9 +24,9 @@ pub fn cmdTargets( | ... | @@ -24,9 +24,9 @@ pub fn cmdTargets( |
| 24 | defer allocator.free(zig_lib_directory.path.?); | 24 | defer allocator.free(zig_lib_directory.path.?); |
| 25 | 25 | ||
| 26 | const abilists_contents = zig_lib_directory.handle.readFileAlloc( | 26 | const abilists_contents = zig_lib_directory.handle.readFileAlloc( |
| 27 | allocator, | ||
| 28 | glibc.abilists_path, | 27 | glibc.abilists_path, |
| 29 | glibc.abilists_max_size, | 28 | allocator, |
| 29 | .limited(glibc.abilists_max_size), | ||
| 30 | ) catch |err| switch (err) { | 30 | ) catch |err| switch (err) { |
| 31 | error.OutOfMemory => return error.OutOfMemory, | 31 | error.OutOfMemory => return error.OutOfMemory, |
| 32 | else => fatal("unable to read " ++ glibc.abilists_path ++ ": {s}", .{@errorName(err)}), | 32 | else => fatal("unable to read " ++ glibc.abilists_path ++ ": {s}", .{@errorName(err)}), |