mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Merge 7099274cb8 into d3e20e71be
This commit is contained in:
commit
eb86a155c4
2 changed files with 60 additions and 9 deletions
|
|
@ -4722,6 +4722,59 @@ test "sliceAsBytes preserves pointer attributes" {
|
|||
try testing.expectEqual(in.alignment, out.alignment);
|
||||
}
|
||||
|
||||
fn AbsorbSentinelReturnType(comptime Slice: type) type {
|
||||
const info = @typeInfo(Slice).pointer;
|
||||
assert(info.size == .slice);
|
||||
return @Type(.{
|
||||
.pointer = .{
|
||||
.size = info.size,
|
||||
.is_const = info.is_const,
|
||||
.is_volatile = info.is_volatile,
|
||||
.is_allowzero = info.is_allowzero,
|
||||
.alignment = info.alignment,
|
||||
.address_space = info.address_space,
|
||||
.child = info.child,
|
||||
.sentinel_ptr = null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/// If the provided slice is not sentinel terminated, do nothing and return that slice.
|
||||
/// If it is sentinel-terminated, return a non-sentinel-terminated slice with the
|
||||
/// length increased by one to include the absorbed sentinel element.
|
||||
pub fn absorbSentinel(slice: anytype) AbsorbSentinelReturnType(@TypeOf(slice)) {
|
||||
const info = @typeInfo(@TypeOf(slice)).pointer;
|
||||
assert(info.size == .slice);
|
||||
if (info.sentinel_ptr == null) {
|
||||
return slice;
|
||||
} else {
|
||||
return slice.ptr[0 .. slice.len + 1];
|
||||
}
|
||||
}
|
||||
|
||||
test absorbSentinel {
|
||||
{
|
||||
var buffer: [3:0]u8 = .{ 1, 2, 3 };
|
||||
const foo: [:0]const u8 = &buffer;
|
||||
const bar: []const u8 = &buffer;
|
||||
try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(foo)));
|
||||
try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(bar)));
|
||||
try testing.expectEqualSlices(u8, &.{ 1, 2, 3, 0 }, absorbSentinel(foo));
|
||||
try testing.expectEqualSlices(u8, &.{ 1, 2, 3 }, absorbSentinel(bar));
|
||||
}
|
||||
{
|
||||
var buffer: [3:0]u8 = .{ 1, 2, 3 };
|
||||
const foo: [:0]u8 = &buffer;
|
||||
const bar: []u8 = &buffer;
|
||||
try testing.expectEqual([]u8, @TypeOf(absorbSentinel(foo)));
|
||||
try testing.expectEqual([]u8, @TypeOf(absorbSentinel(bar)));
|
||||
var expected_foo = [_]u8{ 1, 2, 3, 0 };
|
||||
try testing.expectEqualSlices(u8, &expected_foo, absorbSentinel(foo));
|
||||
var expected_bar = [_]u8{ 1, 2, 3 };
|
||||
try testing.expectEqualSlices(u8, &expected_bar, absorbSentinel(bar));
|
||||
}
|
||||
}
|
||||
|
||||
/// Round an address down to the next (or current) aligned address.
|
||||
/// Unlike `alignForward`, `alignment` can be any positive number, not just a power of 2.
|
||||
pub fn alignForwardAnyAlign(comptime T: type, addr: T, alignment: T) T {
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
|
|||
if (allocation.len == 0) {
|
||||
return false;
|
||||
}
|
||||
const old_memory = mem.sliceAsBytes(allocation);
|
||||
const old_memory: []u8 = @constCast(@ptrCast(mem.absorbSentinel(allocation)));
|
||||
// I would like to use saturating multiplication here, but LLVM cannot lower it
|
||||
// on WebAssembly: https://github.com/ziglang/zig/issues/9660
|
||||
//const new_len_bytes = new_len *| @sizeOf(T);
|
||||
|
|
@ -362,7 +362,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: {
|
|||
new_memory.len = new_len;
|
||||
return new_memory;
|
||||
}
|
||||
const old_memory = mem.sliceAsBytes(allocation);
|
||||
const old_memory: []u8 = @constCast(@ptrCast(mem.absorbSentinel(allocation)));
|
||||
// I would like to use saturating multiplication here, but LLVM cannot lower it
|
||||
// on WebAssembly: https://github.com/ziglang/zig/issues/9660
|
||||
//const new_len_bytes = new_len *| @sizeOf(T);
|
||||
|
|
@ -413,7 +413,7 @@ pub fn reallocAdvanced(
|
|||
return @as([*]align(Slice.alignment) T, @ptrFromInt(ptr))[0..0];
|
||||
}
|
||||
|
||||
const old_byte_slice = mem.sliceAsBytes(old_mem);
|
||||
const old_byte_slice: []u8 = @constCast(@ptrCast(mem.absorbSentinel(old_mem)));
|
||||
const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory;
|
||||
// Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure
|
||||
if (self.rawRemap(old_byte_slice, .fromByteUnits(Slice.alignment), byte_count, return_address)) |p| {
|
||||
|
|
@ -437,12 +437,10 @@ pub fn reallocAdvanced(
|
|||
/// To free a single item, see `destroy`.
|
||||
pub fn free(self: Allocator, memory: anytype) void {
|
||||
const Slice = @typeInfo(@TypeOf(memory)).pointer;
|
||||
const bytes = mem.sliceAsBytes(memory);
|
||||
const bytes_len = bytes.len + if (Slice.sentinel() != null) @sizeOf(Slice.child) else 0;
|
||||
if (bytes_len == 0) return;
|
||||
const non_const_ptr = @constCast(bytes.ptr);
|
||||
@memset(non_const_ptr[0..bytes_len], undefined);
|
||||
self.rawFree(non_const_ptr[0..bytes_len], .fromByteUnits(Slice.alignment), @returnAddress());
|
||||
const bytes: []u8 = @constCast(@ptrCast(mem.absorbSentinel(memory)));
|
||||
if (bytes.len == 0) return;
|
||||
@memset(bytes, undefined);
|
||||
self.rawFree(bytes, .fromByteUnits(Slice.alignment), @returnAddress());
|
||||
}
|
||||
|
||||
/// Copies `m` to newly allocated memory. Caller owns the memory.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue