mirror of
https://github.com/ziglang/zig.git
synced 2026-01-24 16:25:25 +00:00
fixes
writeFile should be split into two
This commit is contained in:
parent
35824e4822
commit
1d0495678d
@ -1611,18 +1611,38 @@ const interface = struct {
|
||||
|
||||
fn writeSplat(context: *anyopaque, data: []const []const u8, splat: usize) anyerror!usize {
|
||||
const file = opaqueToHandle(context);
|
||||
var splat_buffer: [256]u8 = undefined;
|
||||
if (is_windows) {
|
||||
if (data.len == 1 and splat == 0) return 0;
|
||||
return windows.WriteFile(file, data[0], null);
|
||||
}
|
||||
var iovecs_buffer: [max_buffers_len]std.posix.iovec_const = undefined;
|
||||
const iovecs = iovecs_buffer[0..@min(iovecs_buffer.len, data.len)];
|
||||
for (iovecs, data[0..iovecs.len]) |*v, d| v.* = .{
|
||||
var iovecs: [max_buffers_len]std.posix.iovec_const = undefined;
|
||||
var len: usize = @min(iovecs.len, data.len);
|
||||
for (iovecs[0..len], data[0..len]) |*v, d| v.* = .{
|
||||
.base = if (d.len == 0) "" else d.ptr, // OS sadly checks ptr addr before length.
|
||||
.len = d.len,
|
||||
};
|
||||
const send_iovecs = if (splat == 0) iovecs[0 .. iovecs.len - 1] else iovecs;
|
||||
return std.posix.writev(file, send_iovecs);
|
||||
switch (splat) {
|
||||
0 => return std.posix.writev(file, iovecs[0 .. len - 1]),
|
||||
1 => return std.posix.writev(file, iovecs[0..len]),
|
||||
else => {
|
||||
const pattern = data[data.len - 1];
|
||||
if (pattern.len == 1) {
|
||||
const memset_len = @min(splat_buffer.len, splat);
|
||||
const buf = splat_buffer[0..memset_len];
|
||||
@memset(buf, pattern[0]);
|
||||
iovecs[len - 1] = .{ .base = buf.ptr, .len = buf.len };
|
||||
var remaining_splat = splat - buf.len;
|
||||
while (remaining_splat > 0 and len < iovecs.len) {
|
||||
iovecs[len] = .{ .base = &splat_buffer, .len = splat_buffer.len };
|
||||
remaining_splat -= splat_buffer.len;
|
||||
len += 1;
|
||||
}
|
||||
return std.posix.writev(file, iovecs[0..len]);
|
||||
}
|
||||
},
|
||||
}
|
||||
return std.posix.writev(file, iovecs[0..len]);
|
||||
}
|
||||
|
||||
fn writeFile(
|
||||
|
||||
@ -76,7 +76,7 @@ pub fn flush(bw: *BufferedWriter) anyerror!void {
|
||||
|
||||
/// The `data` parameter is mutable because this function needs to mutate the
|
||||
/// fields in order to handle partial writes from `Writer.VTable.writev`.
|
||||
pub fn writevAll(bw: *BufferedWriter, data: []const []const u8) anyerror!void {
|
||||
pub fn writevAll(bw: *BufferedWriter, data: [][]const u8) anyerror!void {
|
||||
var i: usize = 0;
|
||||
while (true) {
|
||||
var n = try passthru_writeSplat(bw, data[i..], 1);
|
||||
@ -164,7 +164,7 @@ fn passthru_writeSplat(context: *anyopaque, data: []const []const u8, splat: usi
|
||||
@branchHint(.likely);
|
||||
@memset(buffer[end..new_end], pattern[0]);
|
||||
bw.end = new_end;
|
||||
return end - start_end;
|
||||
return new_end - start_end;
|
||||
}
|
||||
buffers[0] = buffer[0..end];
|
||||
buffers[1] = pattern;
|
||||
@ -186,8 +186,8 @@ fn passthru_writeSplat(context: *anyopaque, data: []const []const u8, splat: usi
|
||||
while (end < new_end) : (end += pattern.len) {
|
||||
@memcpy(buffer[end..][0..pattern.len], pattern);
|
||||
}
|
||||
bw.end = end;
|
||||
return end - start_end;
|
||||
bw.end = new_end;
|
||||
return new_end - start_end;
|
||||
}
|
||||
buffers[0] = buffer[0..end];
|
||||
buffers[1] = pattern;
|
||||
@ -471,32 +471,55 @@ pub const WriteFileOptions = struct {
|
||||
pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOptions) anyerror!void {
|
||||
const headers_and_trailers = options.headers_and_trailers;
|
||||
const headers = headers_and_trailers[0..options.headers_len];
|
||||
var len = options.len;
|
||||
var i: usize = 0;
|
||||
var offset = options.offset;
|
||||
if (len == .zero) return writevAll(bw, headers_and_trailers[i..]);
|
||||
while (i < headers_and_trailers.len) {
|
||||
var n = try writeFile(bw, file, offset, len, headers_and_trailers[i..], headers.len - i);
|
||||
while (i < headers.len and n >= headers[i].len) {
|
||||
n -= headers[i].len;
|
||||
i += 1;
|
||||
}
|
||||
if (i < headers.len) {
|
||||
headers[i] = headers[i][n..];
|
||||
continue;
|
||||
}
|
||||
if (n >= len.int()) {
|
||||
n -= len.int();
|
||||
while (n >= headers_and_trailers[i].len) {
|
||||
n -= headers_and_trailers[i].len;
|
||||
if (options.len == .zero) return writevAll(bw, headers_and_trailers);
|
||||
if (options.len == .entire_file) {
|
||||
// When reading the whole file, we cannot include the trailers in the
|
||||
// call that reads from the file handle, because we have no way to
|
||||
// determine whether a partial write is past the end of the file or
|
||||
// not.
|
||||
var i: usize = 0;
|
||||
var offset = options.offset;
|
||||
while (true) {
|
||||
var n = try writeFile(bw, file, offset, .entire_file, headers[i..], headers.len - i);
|
||||
while (i < headers.len and n >= headers[i].len) {
|
||||
n -= headers[i].len;
|
||||
i += 1;
|
||||
if (i >= headers_and_trailers.len) return;
|
||||
}
|
||||
headers_and_trailers[i] = headers_and_trailers[i][n..];
|
||||
return writevAll(bw, headers_and_trailers[i..]);
|
||||
if (i < headers.len) {
|
||||
headers[i] = headers[i][n..];
|
||||
continue;
|
||||
}
|
||||
if (n == 0) break;
|
||||
offset += n;
|
||||
}
|
||||
} else {
|
||||
var len = options.len.int();
|
||||
var i: usize = 0;
|
||||
var offset = options.offset;
|
||||
while (true) {
|
||||
var n = try writeFile(bw, file, offset, .init(len), headers_and_trailers[i..], headers.len - i);
|
||||
while (i < headers.len and n >= headers[i].len) {
|
||||
n -= headers[i].len;
|
||||
i += 1;
|
||||
}
|
||||
if (i < headers.len) {
|
||||
headers[i] = headers[i][n..];
|
||||
continue;
|
||||
}
|
||||
if (n >= len) {
|
||||
n -= len;
|
||||
if (i >= headers_and_trailers.len) return;
|
||||
while (n >= headers_and_trailers[i].len) {
|
||||
n -= headers_and_trailers[i].len;
|
||||
i += 1;
|
||||
if (i >= headers_and_trailers.len) return;
|
||||
}
|
||||
headers_and_trailers[i] = headers_and_trailers[i][n..];
|
||||
return writevAll(bw, headers_and_trailers[i..]);
|
||||
}
|
||||
offset += n;
|
||||
len -= n;
|
||||
}
|
||||
offset += n;
|
||||
len = if (len == .entire_file) .entire_file else .init(len.int() - n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ pub const VTable = struct {
|
||||
|
||||
pub fn init(integer: u64) FileLen {
|
||||
const result: FileLen = @enumFromInt(integer);
|
||||
assert(result != .none);
|
||||
assert(result != .entire_file);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user