diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-01-11 17:48:33 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-01-11 17:48:33 -0700 |
| commit | 56c03881ebd8617e6506bfad01bf9cfdd4d3df7e (patch) | |
| tree | 25da58e774494f28c44463921ba2f2387d8e3ae3 /lib/std/mem.zig | |
| parent | fc10c9c4ce40570d0abeda764f1bd76b3e79af61 (diff) | |
| parent | c96272f6186a5e843c0586513e87ffd771c5b00c (diff) | |
| download | zig-56c03881ebd8617e6506bfad01bf9cfdd4d3df7e.tar.gz zig-56c03881ebd8617e6506bfad01bf9cfdd4d3df7e.zip | |
Merge branch 'rohlem-fix-GetFinalPathNameByHandle-before-win10_rs4'
Merges #7379
Diffstat (limited to 'lib/std/mem.zig')
| -rw-r--r-- | lib/std/mem.zig | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 2726dc9d3e..98a37e3d2b 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -2436,3 +2436,46 @@ test "freeing empty string with null-terminated sentinel" { const empty_string = try dupeZ(testing.allocator, u8, ""); testing.allocator.free(empty_string); } + +/// Returns a slice with the given new alignment, +/// all other pointer attributes copied from `AttributeSource`. +fn AlignedSlice(comptime AttributeSource: type, comptime new_alignment: u29) type { + const info = @typeInfo(AttributeSource).Pointer; + return @Type(.{ + .Pointer = .{ + .size = .Slice, + .is_const = info.is_const, + .is_volatile = info.is_volatile, + .is_allowzero = info.is_allowzero, + .alignment = new_alignment, + .child = info.child, + .sentinel = null, + }, + }); +} + +/// Returns the largest slice in the given bytes that conforms to the new alignment, +/// or `null` if the given bytes contain no conforming address. +pub fn alignInBytes(bytes: []u8, comptime new_alignment: usize) ?[]align(new_alignment) u8 { + const begin_address = @ptrToInt(bytes.ptr); + const end_address = begin_address + bytes.len; + + const begin_address_aligned = mem.alignForward(begin_address, new_alignment); + const new_length = std.math.sub(usize, end_address, begin_address_aligned) catch |e| switch (e) { + error.Overflow => return null, + }; + const alignment_offset = begin_address_aligned - begin_address; + return @alignCast(new_alignment, bytes[alignment_offset .. alignment_offset + new_length]); +} + +/// Returns the largest sub-slice within the given slice that conforms to the new alignment, +/// or `null` if the given slice contains no conforming address. +pub fn alignInSlice(slice: anytype, comptime new_alignment: usize) ?AlignedSlice(@TypeOf(slice), new_alignment) { + const bytes = sliceAsBytes(slice); + const aligned_bytes = alignInBytes(bytes, new_alignment) orelse return null; + + const Element = @TypeOf(slice[0]); + const slice_length_bytes = aligned_bytes.len - (aligned_bytes.len % @sizeOf(Element)); + const aligned_slice = bytesAsSlice(Element, aligned_bytes[0..slice_length_bytes]); + return @alignCast(new_alignment, aligned_slice); +} |
