mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
std.fs.File.Reader: fix seek position logic
This commit is contained in:
parent
fe10c66d66
commit
b35c55e237
@ -1135,7 +1135,7 @@ pub const Reader = struct {
|
||||
err: ?ReadError = null,
|
||||
mode: Reader.Mode = .positional,
|
||||
/// Tracks the true seek position in the file. To obtain the logical
|
||||
/// position, subtract the buffer size from this value.
|
||||
/// position, use `logicalPos`.
|
||||
pos: u64 = 0,
|
||||
size: ?u64 = null,
|
||||
size_err: ?GetEndPosError = null,
|
||||
@ -1274,14 +1274,20 @@ pub const Reader = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn logicalPos(r: *const Reader) u64 {
|
||||
return r.pos - r.interface.bufferedLen();
|
||||
}
|
||||
|
||||
fn setPosAdjustingBuffer(r: *Reader, offset: u64) void {
|
||||
if (offset < r.pos or offset >= r.pos + r.interface.bufferedLen()) {
|
||||
const logical_pos = logicalPos(r);
|
||||
if (offset < logical_pos or offset >= r.pos) {
|
||||
r.interface.seek = 0;
|
||||
r.interface.end = 0;
|
||||
r.pos = offset;
|
||||
} else {
|
||||
r.interface.seek += @intCast(offset - r.pos);
|
||||
const logical_delta: usize = @intCast(offset - logical_pos);
|
||||
r.interface.seek += logical_delta;
|
||||
}
|
||||
r.pos = offset;
|
||||
}
|
||||
|
||||
/// Number of slices to store on the stack, when trying to send as many byte
|
||||
|
||||
@ -2060,7 +2060,7 @@ test "invalid UTF-8/WTF-8 paths" {
|
||||
}
|
||||
|
||||
test "read file non vectored" {
|
||||
var tmp_dir = std.testing.tmpDir(.{});
|
||||
var tmp_dir = testing.tmpDir(.{});
|
||||
defer tmp_dir.cleanup();
|
||||
|
||||
const contents = "hello, world!\n";
|
||||
@ -2085,6 +2085,47 @@ test "read file non vectored" {
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
try std.testing.expectEqualStrings(contents, w.buffered());
|
||||
try std.testing.expectEqual(contents.len, i);
|
||||
try testing.expectEqualStrings(contents, w.buffered());
|
||||
try testing.expectEqual(contents.len, i);
|
||||
}
|
||||
|
||||
test "seek keeping partial buffer" {
|
||||
var tmp_dir = testing.tmpDir(.{});
|
||||
defer tmp_dir.cleanup();
|
||||
|
||||
const contents = "0123456789";
|
||||
|
||||
const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true });
|
||||
defer file.close();
|
||||
{
|
||||
var file_writer: std.fs.File.Writer = .init(file, &.{});
|
||||
try file_writer.interface.writeAll(contents);
|
||||
try file_writer.interface.flush();
|
||||
}
|
||||
|
||||
var read_buffer: [3]u8 = undefined;
|
||||
var file_reader: std.fs.File.Reader = .init(file, &read_buffer);
|
||||
|
||||
try testing.expectEqual(0, file_reader.logicalPos());
|
||||
|
||||
var buf: [4]u8 = undefined;
|
||||
try file_reader.interface.readSliceAll(&buf);
|
||||
|
||||
if (file_reader.interface.bufferedLen() != 3) {
|
||||
// Pass the test if the OS doesn't give us vectored reads.
|
||||
return;
|
||||
}
|
||||
|
||||
try testing.expectEqual(4, file_reader.logicalPos());
|
||||
try testing.expectEqual(7, file_reader.pos);
|
||||
try file_reader.seekTo(6);
|
||||
try testing.expectEqual(6, file_reader.logicalPos());
|
||||
try testing.expectEqual(7, file_reader.pos);
|
||||
|
||||
try testing.expectEqualStrings("0123", &buf);
|
||||
|
||||
const n = try file_reader.interface.readSliceShort(&buf);
|
||||
try testing.expectEqual(4, n);
|
||||
|
||||
try testing.expectEqualStrings("6789", &buf);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user