aboutsummaryrefslogtreecommitdiff
path: root/lib/std/mem.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-01-11 17:48:33 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-01-11 17:48:33 -0700
commit56c03881ebd8617e6506bfad01bf9cfdd4d3df7e (patch)
tree25da58e774494f28c44463921ba2f2387d8e3ae3 /lib/std/mem.zig
parentfc10c9c4ce40570d0abeda764f1bd76b3e79af61 (diff)
parentc96272f6186a5e843c0586513e87ffd771c5b00c (diff)
downloadzig-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.zig43
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);
+}