authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2025-09-07 03:55:57+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-09-06 18:55:57-07:00
log02396f8d5c5ca32c1d2ab2e2f04afba4588f5944
treef7c777b9ecec5547c8c179e6175629957f654f3e
parentcc6d9fdbf40cc23d2ec47d2f7db74a84fbefd1ac
signaturebadge-check Signed by PGP key B5690EEEBB952194

Document std.mem.* functions (#25168)

* Document std.mem.* functions Functions in std.mem are essential for virtually all applications, yet many of them lacked documentation. Co-authored-by: Andrew Kelley <andrew@ziglang.org>

1 files changed, 58 insertions(+), 0 deletions(-)

lib/std/mem.zig+58
......@@ -166,6 +166,8 @@ pub fn ValidationAllocator(comptime T: type) type {
166166 };
167167}
168168
169/// Wraps an allocator with basic validation checks.
170/// Asserts that allocation sizes are greater than zero and returned pointers have correct alignment.
169171pub fn validationWrap(allocator: anytype) ValidationAllocator(@TypeOf(allocator)) {
170172 return ValidationAllocator(@TypeOf(allocator)).init(allocator);
171173}
......@@ -597,6 +599,12 @@ test zeroInit {
597599 }, nested_baz);
598600}
599601
602/// Sorts a slice in-place using a stable algorithm (maintains relative order of equal elements).
603/// Average time complexity: O(n log n), worst case: O(n log n)
604/// Space complexity: O(log n) for recursive calls
605///
606/// For slice of primitives with default ordering, consider using `std.sort.block` directly.
607/// For unstable but potentially faster sorting, see `sortUnstable`.
600608pub fn sort(
601609 comptime T: type,
602610 items: []T,
......@@ -606,6 +614,12 @@ pub fn sort(
606614 std.sort.block(T, items, context, lessThanFn);
607615}
608616
617/// Sorts a slice in-place using an unstable algorithm (does not preserve relative order of equal elements).
618/// Time complexity: O(n) best case, O(n log n) worst case and average case.
619/// Generally faster than stable sort but order of equal elements is undefined.
620///
621/// Uses pattern-defeating quicksort (PDQ) algorithm which performs well on many data patterns.
622/// For stable sorting that preserves equal element order, use `sort`.
609623pub fn sortUnstable(
610624 comptime T: type,
611625 items: []T,
......@@ -621,6 +635,12 @@ pub fn sortContext(a: usize, b: usize, context: anytype) void {
621635 std.sort.insertionContext(a, b, context);
622636}
623637
638/// Sorts a range [a, b) using an unstable algorithm with custom context.
639/// This is a lower-level interface for sorting that works with indices instead of slices.
640/// Does not preserve relative order of equal elements.
641///
642/// The context must provide lessThan(a_idx, b_idx) and swap(a_idx, b_idx) methods.
643/// Uses pattern-defeating quicksort (PDQ) algorithm.
624644pub fn sortUnstableContext(a: usize, b: usize, context: anytype) void {
625645 std.sort.pdqContext(a, b, context);
626646}
......@@ -1089,6 +1109,8 @@ test len {
10891109 try testing.expect(len(c_ptr) == 2);
10901110}
10911111
1112/// Returns the index of the sentinel value in a sentinel-terminated pointer.
1113/// Linear search through memory until the sentinel is found.
10921114pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]const T) usize {
10931115 var i: usize = 0;
10941116
......@@ -1255,6 +1277,8 @@ pub fn lastIndexOfScalar(comptime T: type, slice: []const T, value: T) ?usize {
12551277 return null;
12561278}
12571279
1280/// Linear search for the index of a scalar value inside a slice, starting from a given position.
1281/// Returns null if the value is not found.
12581282pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize {
12591283 if (start_index >= slice.len) return null;
12601284
......@@ -1331,10 +1355,14 @@ test indexOfScalarPos {
13311355 }
13321356}
13331357
1358/// Linear search for the index of any value in the provided list inside a slice.
1359/// Returns null if no values are found.
13341360pub fn indexOfAny(comptime T: type, slice: []const T, values: []const T) ?usize {
13351361 return indexOfAnyPos(T, slice, 0, values);
13361362}
13371363
1364/// Linear search for the last index of any value in the provided list inside a slice.
1365/// Returns null if no values are found.
13381366pub fn lastIndexOfAny(comptime T: type, slice: []const T, values: []const T) ?usize {
13391367 var i: usize = slice.len;
13401368 while (i != 0) {
......@@ -1346,6 +1374,8 @@ pub fn lastIndexOfAny(comptime T: type, slice: []const T, values: []const T) ?us
13461374 return null;
13471375}
13481376
1377/// Linear search for the index of any value in the provided list inside a slice, starting from a given position.
1378/// Returns null if no values are found.
13491379pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, values: []const T) ?usize {
13501380 if (start_index >= slice.len) return null;
13511381 for (slice[start_index..], start_index..) |c, i| {
......@@ -1404,6 +1434,9 @@ test indexOfNone {
14041434 try testing.expect(indexOfNonePos(u8, "abc123", 3, "321") == null);
14051435}
14061436
1437/// Search for needle in haystack and return the index of the first occurrence.
1438/// Uses Boyer-Moore-Horspool algorithm on large inputs; linear search on small inputs.
1439/// Returns null if needle is not found.
14071440pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize {
14081441 return indexOfPos(T, haystack, 0, needle);
14091442}
......@@ -2241,6 +2274,9 @@ test byteSwapAllFields {
22412274 }, k);
22422275}
22432276
2277/// Reverses the byte order of all elements in a slice.
2278/// Handles structs, unions, arrays, enums, floats, and integers recursively.
2279/// Useful for converting between little-endian and big-endian representations.
22442280pub fn byteSwapAllElements(comptime Elem: type, slice: []Elem) void {
22452281 for (slice) |*elem| {
22462282 switch (@typeInfo(@TypeOf(elem.*))) {
......@@ -2980,6 +3016,7 @@ test window {
29803016 }
29813017}
29823018
3019/// Iterator type returned by the `window` function for sliding window operations.
29833020pub fn WindowIterator(comptime T: type) type {
29843021 return struct {
29853022 buffer: []const T,
......@@ -3020,6 +3057,8 @@ pub fn WindowIterator(comptime T: type) type {
30203057 };
30213058}
30223059
3060/// Returns true if haystack starts with needle.
3061/// Time complexity: O(needle.len)
30233062pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
30243063 return if (needle.len > haystack.len) false else eql(T, haystack[0..needle.len], needle);
30253064}
......@@ -3029,6 +3068,8 @@ test startsWith {
30293068 try testing.expect(!startsWith(u8, "Needle in haystack", "haystack"));
30303069}
30313070
3071/// Returns true if haystack ends with needle.
3072/// Time complexity: O(needle.len)
30323073pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
30333074 return if (needle.len > haystack.len) false else eql(T, haystack[haystack.len - needle.len ..], needle);
30343075}
......@@ -3038,8 +3079,10 @@ test endsWith {
30383079 try testing.expect(!endsWith(u8, "Bob", "Bo"));
30393080}
30403081
3082/// Delimiter type for tokenization and splitting operations.
30413083pub const DelimiterType = enum { sequence, any, scalar };
30423084
3085/// Iterator type for tokenization operations, skipping empty sequences and delimiter sequences.
30433086pub fn TokenIterator(comptime T: type, comptime delimiter_type: DelimiterType) type {
30443087 return struct {
30453088 buffer: []const T,
......@@ -3113,6 +3156,7 @@ pub fn TokenIterator(comptime T: type, comptime delimiter_type: DelimiterType) t
31133156 };
31143157}
31153158
3159/// Iterator type for splitting operations, including empty sequences between delimiters.
31163160pub fn SplitIterator(comptime T: type, comptime delimiter_type: DelimiterType) type {
31173161 return struct {
31183162 buffer: []const T,
......@@ -3178,6 +3222,7 @@ pub fn SplitIterator(comptime T: type, comptime delimiter_type: DelimiterType) t
31783222 };
31793223}
31803224
3225/// Iterator type for splitting operations from the end backwards, including empty sequences.
31813226pub fn SplitBackwardsIterator(comptime T: type, comptime delimiter_type: DelimiterType) type {
31823227 return struct {
31833228 buffer: []const T,
......@@ -3587,6 +3632,7 @@ test indexOfMinMax {
35873632 try testing.expectEqual(.{ 0, 0 }, indexOfMinMax(u8, "a"));
35883633}
35893634
3635/// Exchanges contents of two memory locations.
35903636pub fn swap(comptime T: type, a: *T, b: *T) void {
35913637 const tmp = a.*;
35923638 a.* = b.*;
......@@ -4452,6 +4498,9 @@ pub fn alignForward(comptime T: type, addr: T, alignment: T) T {
44524498 return alignBackward(T, addr + (alignment - 1), alignment);
44534499}
44544500
4501/// Rounds an address up to the next alignment boundary using log2 representation.
4502/// Equivalent to alignForward with alignment = 1 << log2_alignment.
4503/// More efficient when alignment is known to be a power of 2.
44554504pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize {
44564505 const alignment = @as(usize, 1) << @as(math.Log2Int(usize), @intCast(log2_alignment));
44574506 return alignForward(usize, addr, alignment);
......@@ -4591,6 +4640,9 @@ pub fn isValidAlignGeneric(comptime T: type, alignment: T) bool {
45914640 return alignment > 0 and std.math.isPowerOfTwo(alignment);
45924641}
45934642
4643/// Returns true if i is aligned to the given alignment.
4644/// Works with any positive alignment value, not just powers of 2.
4645/// For power-of-2 alignments, `isAligned` is more efficient.
45944646pub fn isAlignedAnyAlign(i: usize, alignment: usize) bool {
45954647 if (isValidAlign(alignment))
45964648 return isAligned(i, alignment);
......@@ -4598,6 +4650,9 @@ pub fn isAlignedAnyAlign(i: usize, alignment: usize) bool {
45984650 return 0 == @mod(i, alignment);
45994651}
46004652
4653/// Returns true if addr is aligned to 2^log2_alignment.
4654/// More efficient than `isAligned` when alignment is known to be a power of 2.
4655/// log2_alignment must be < @bitSizeOf(usize).
46014656pub fn isAlignedLog2(addr: usize, log2_alignment: u8) bool {
46024657 return @ctz(addr) >= log2_alignment;
46034658}
......@@ -4608,6 +4663,9 @@ pub fn isAligned(addr: usize, alignment: usize) bool {
46084663 return isAlignedGeneric(u64, addr, alignment);
46094664}
46104665
4666/// Generic version of `isAligned` that works with any integer type.
4667/// Returns true if addr is aligned to the given alignment.
4668/// Alignment must be a power of 2 and greater than 0.
46114669pub fn isAlignedGeneric(comptime T: type, addr: T, alignment: T) bool {
46124670 return alignBackward(T, addr, alignment) == addr;
46134671}