diff options
Diffstat (limited to 'lib/std/fs/File.zig')
| -rw-r--r-- | lib/std/fs/File.zig | 209 |
1 files changed, 105 insertions, 104 deletions
diff --git a/lib/std/fs/File.zig b/lib/std/fs/File.zig index 99dda27885..169f3f5222 100644 --- a/lib/std/fs/File.zig +++ b/lib/std/fs/File.zig @@ -60,7 +60,7 @@ pub const OpenError = error{ /// WASI-only; file paths must be valid UTF-8. InvalidUtf8, /// Windows-only; file paths provided by the user must be valid WTF-8. - /// https://simonsapin.github.io/wtf-8/ + /// https://wtf-8.codeberg.page/ InvalidWtf8, /// On Windows, file paths cannot contain these characters: /// '/', '*', '?', '"', '<', '>', '|' @@ -1189,7 +1189,7 @@ pub const Reader = struct { pub fn seekBy(r: *Reader, offset: i64) Reader.SeekError!void { switch (r.mode) { .positional, .positional_reading => { - setPosAdjustingBuffer(r, @intCast(@as(i64, @intCast(r.pos)) + offset)); + setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset)); }, .streaming, .streaming_reading => { if (posix.SEEK == void) { @@ -1198,7 +1198,7 @@ pub const Reader = struct { } const seek_err = r.seek_err orelse e: { if (posix.lseek_CUR(r.file.handle, offset)) |_| { - setPosAdjustingBuffer(r, @intCast(@as(i64, @intCast(r.pos)) + offset)); + setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset)); return; } else |err| { r.seek_err = err; @@ -1222,16 +1222,17 @@ pub const Reader = struct { pub fn seekTo(r: *Reader, offset: u64) Reader.SeekError!void { switch (r.mode) { .positional, .positional_reading => { - setPosAdjustingBuffer(r, offset); + setLogicalPos(r, offset); }, .streaming, .streaming_reading => { - if (offset >= r.pos) return Reader.seekBy(r, @intCast(offset - r.pos)); + const logical_pos = logicalPos(r); + if (offset >= logical_pos) return Reader.seekBy(r, @intCast(offset - logical_pos)); if (r.seek_err) |err| return err; posix.lseek_SET(r.file.handle, offset) catch |err| { r.seek_err = err; return err; }; - setPosAdjustingBuffer(r, offset); + setLogicalPos(r, offset); }, .failure => return r.seek_err.?, } @@ -1241,7 +1242,7 @@ pub const Reader = struct { return r.pos - r.interface.bufferedLen(); } - fn setPosAdjustingBuffer(r: *Reader, offset: u64) void { + fn setLogicalPos(r: *Reader, offset: u64) void { const logical_pos = logicalPos(r); if (offset < logical_pos or offset >= r.pos) { r.interface.seek = 0; @@ -1269,13 +1270,15 @@ pub const Reader = struct { }, .positional_reading => { const dest = limit.slice(try w.writableSliceGreedy(1)); - const n = try readPositional(r, dest); + var data: [1][]u8 = .{dest}; + const n = try readVecPositional(r, &data); w.advance(n); return n; }, .streaming_reading => { const dest = limit.slice(try w.writableSliceGreedy(1)); - const n = try readStreaming(r, dest); + var data: [1][]u8 = .{dest}; + const n = try readVecStreaming(r, &data); w.advance(n); return n; }, @@ -1286,92 +1289,98 @@ pub const Reader = struct { fn readVec(io_reader: *std.Io.Reader, data: [][]u8) std.Io.Reader.Error!usize { const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader)); switch (r.mode) { - .positional, .positional_reading => { - if (is_windows) { - // Unfortunately, `ReadFileScatter` cannot be used since it - // requires page alignment. - if (io_reader.seek == io_reader.end) { - io_reader.seek = 0; - io_reader.end = 0; - } - const first = data[0]; - if (first.len >= io_reader.buffer.len - io_reader.end) { - return readPositional(r, first); - } else { - io_reader.end += try readPositional(r, io_reader.buffer[io_reader.end..]); - return 0; - } - } - var iovecs_buffer: [max_buffers_len]posix.iovec = undefined; - const dest_n, const data_size = try io_reader.writableVectorPosix(&iovecs_buffer, data); - const dest = iovecs_buffer[0..dest_n]; - assert(dest[0].len > 0); - const n = posix.preadv(r.file.handle, dest, r.pos) catch |err| switch (err) { - error.Unseekable => { - r.mode = r.mode.toStreaming(); - const pos = r.pos; - if (pos != 0) { - r.pos = 0; - r.seekBy(@intCast(pos)) catch { - r.mode = .failure; - return error.ReadFailed; - }; - } - return 0; - }, - else => |e| { - r.err = e; + .positional, .positional_reading => return readVecPositional(r, data), + .streaming, .streaming_reading => return readVecStreaming(r, data), + .failure => return error.ReadFailed, + } + } + + fn readVecPositional(r: *Reader, data: [][]u8) std.Io.Reader.Error!usize { + const io_reader = &r.interface; + if (is_windows) { + // Unfortunately, `ReadFileScatter` cannot be used since it + // requires page alignment. + if (io_reader.seek == io_reader.end) { + io_reader.seek = 0; + io_reader.end = 0; + } + const first = data[0]; + if (first.len >= io_reader.buffer.len - io_reader.end) { + return readPositional(r, first); + } else { + io_reader.end += try readPositional(r, io_reader.buffer[io_reader.end..]); + return 0; + } + } + var iovecs_buffer: [max_buffers_len]posix.iovec = undefined; + const dest_n, const data_size = try io_reader.writableVectorPosix(&iovecs_buffer, data); + const dest = iovecs_buffer[0..dest_n]; + assert(dest[0].len > 0); + const n = posix.preadv(r.file.handle, dest, r.pos) catch |err| switch (err) { + error.Unseekable => { + r.mode = r.mode.toStreaming(); + const pos = r.pos; + if (pos != 0) { + r.pos = 0; + r.seekBy(@intCast(pos)) catch { + r.mode = .failure; return error.ReadFailed; - }, - }; - if (n == 0) { - r.size = r.pos; - return error.EndOfStream; - } - r.pos += n; - if (n > data_size) { - io_reader.end += n - data_size; - return data_size; + }; } - return n; + return 0; }, - .streaming, .streaming_reading => { - if (is_windows) { - // Unfortunately, `ReadFileScatter` cannot be used since it - // requires page alignment. - if (io_reader.seek == io_reader.end) { - io_reader.seek = 0; - io_reader.end = 0; - } - const first = data[0]; - if (first.len >= io_reader.buffer.len - io_reader.end) { - return readStreaming(r, first); - } else { - io_reader.end += try readStreaming(r, io_reader.buffer[io_reader.end..]); - return 0; - } - } - var iovecs_buffer: [max_buffers_len]posix.iovec = undefined; - const dest_n, const data_size = try io_reader.writableVectorPosix(&iovecs_buffer, data); - const dest = iovecs_buffer[0..dest_n]; - assert(dest[0].len > 0); - const n = posix.readv(r.file.handle, dest) catch |err| { - r.err = err; - return error.ReadFailed; - }; - if (n == 0) { - r.size = r.pos; - return error.EndOfStream; - } - r.pos += n; - if (n > data_size) { - io_reader.end += n - data_size; - return data_size; - } - return n; + else => |e| { + r.err = e; + return error.ReadFailed; }, - .failure => return error.ReadFailed, + }; + if (n == 0) { + r.size = r.pos; + return error.EndOfStream; + } + r.pos += n; + if (n > data_size) { + io_reader.end += n - data_size; + return data_size; } + return n; + } + + fn readVecStreaming(r: *Reader, data: [][]u8) std.Io.Reader.Error!usize { + const io_reader = &r.interface; + if (is_windows) { + // Unfortunately, `ReadFileScatter` cannot be used since it + // requires page alignment. + if (io_reader.seek == io_reader.end) { + io_reader.seek = 0; + io_reader.end = 0; + } + const first = data[0]; + if (first.len >= io_reader.buffer.len - io_reader.end) { + return readStreaming(r, first); + } else { + io_reader.end += try readStreaming(r, io_reader.buffer[io_reader.end..]); + return 0; + } + } + var iovecs_buffer: [max_buffers_len]posix.iovec = undefined; + const dest_n, const data_size = try io_reader.writableVectorPosix(&iovecs_buffer, data); + const dest = iovecs_buffer[0..dest_n]; + assert(dest[0].len > 0); + const n = posix.readv(r.file.handle, dest) catch |err| { + r.err = err; + return error.ReadFailed; + }; + if (n == 0) { + r.size = r.pos; + return error.EndOfStream; + } + r.pos += n; + if (n > data_size) { + io_reader.end += n - data_size; + return data_size; + } + return n; } fn discard(io_reader: *std.Io.Reader, limit: std.Io.Limit) std.Io.Reader.Error!usize { @@ -1440,7 +1449,7 @@ pub const Reader = struct { } } - pub fn readPositional(r: *Reader, dest: []u8) std.Io.Reader.Error!usize { + fn readPositional(r: *Reader, dest: []u8) std.Io.Reader.Error!usize { const n = r.file.pread(dest, r.pos) catch |err| switch (err) { error.Unseekable => { r.mode = r.mode.toStreaming(); @@ -1467,7 +1476,7 @@ pub const Reader = struct { return n; } - pub fn readStreaming(r: *Reader, dest: []u8) std.Io.Reader.Error!usize { + fn readStreaming(r: *Reader, dest: []u8) std.Io.Reader.Error!usize { const n = r.file.read(dest) catch |err| { r.err = err; return error.ReadFailed; @@ -1480,14 +1489,6 @@ pub const Reader = struct { return n; } - pub fn read(r: *Reader, dest: []u8) std.Io.Reader.Error!usize { - switch (r.mode) { - .positional, .positional_reading => return readPositional(r, dest), - .streaming, .streaming_reading => return readStreaming(r, dest), - .failure => return error.ReadFailed, - } - } - pub fn atEnd(r: *Reader) bool { // Even if stat fails, size is set when end is encountered. const size = r.size orelse return false; @@ -1732,7 +1733,7 @@ pub const Writer = struct { ) std.Io.Writer.FileError!usize { const reader_buffered = file_reader.interface.buffered(); if (reader_buffered.len >= @intFromEnum(limit)) - return sendFileBuffered(io_w, file_reader, reader_buffered); + return sendFileBuffered(io_w, file_reader, limit.slice(reader_buffered)); const writer_buffered = io_w.buffered(); const file_limit = @intFromEnum(limit) - reader_buffered.len; const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w)); @@ -1804,7 +1805,7 @@ pub const Writer = struct { return error.EndOfStream; } const consumed = io_w.consume(@intCast(sbytes)); - file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed; + file_reader.seekBy(@intCast(consumed)) catch return error.ReadFailed; return consumed; } @@ -1865,7 +1866,7 @@ pub const Writer = struct { return error.EndOfStream; } const consumed = io_w.consume(@bitCast(len)); - file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed; + file_reader.seekBy(@intCast(consumed)) catch return error.ReadFailed; return consumed; } @@ -1998,7 +1999,7 @@ pub const Writer = struct { reader_buffered: []const u8, ) std.Io.Writer.FileError!usize { const n = try drain(io_w, &.{reader_buffered}, 1); - file_reader.seekTo(file_reader.pos + n) catch return error.ReadFailed; + file_reader.seekBy(@intCast(n)) catch return error.ReadFailed; return n; } |
