eqlBytes
std.mem.eql heavily optimized for slices of bytes.
Function parameters
Parameters
- a:[]const u8
- b:[]const u8
Type definitions in this namespace
Types
- Alignment
- Stored as a power-of-two.
Detects and asserts if the std.mem.Allocator interface is violated by the caller
Functions
- ValidationAllocator
- Detects and asserts if the std.mem.Allocator interface is violated by the caller
- copyForwards
- Copy all of source into dest at position 0.
- copyBackwards
- Copy all of source into dest at position 0.
- zeroes
- Generally, Zig users are encouraged to explicitly initialize all fields of a struct explicitly rather than using this function.
- zeroInit
- Initializes all fields of the struct with their default value, or zero values if no default value is present.
- sortContext
- TODO: currently this just calls `insertionSortContext`.
- order
- Compares two slices of numbers lexicographically.
- orderZ
- Compares two many-item pointers with NUL-termination lexicographically.
- lessThan
- Returns true if lhs < rhs, false otherwise
- eql
- Returns true if and only if the slices have the same length and all elements
- indexOfDiff
- Compares two slices and returns the index of the first inequality.
- span
- Takes a sentinel-terminated pointer and returns a slice, iterating over the
- sliceTo
- Takes a pointer to an array, a sentinel-terminated pointer, or a slice and iterates searching for
- len
- Takes a sentinel-terminated pointer and iterates over the memory to find the
- allEqual
- Returns true if all elements in a slice are equal to the scalar value provided
- trimStart
- Remove a set of values from the beginning of a slice.
- trimLeft
- Deprecated: use `trimStart` instead.
- trimEnd
- Remove a set of values from the end of a slice.
- trimRight
- Deprecated: use `trimEnd` instead.
- trim
- Remove a set of values from the beginning and end of a slice.
- indexOfScalar
- Linear search for the index of a scalar value inside a slice.
- lastIndexOfScalar
- Linear search for the last index of a scalar value inside a slice.
- indexOfNone
- Find the first item in `slice` which is not contained in `values`.
- lastIndexOfNone
- Find the last item in `slice` which is not contained in `values`.
- indexOfNonePos
- Find the first item in `slice[start_index..]` which is not contained in `values`.
- lastIndexOfLinear
- Find the index in a slice of a sub-slice, searching from the end backwards.
- indexOfPosLinear
- Consider using `indexOfPos` instead of this, which will automatically use a
- lastIndexOf
- Find the index in a slice of a sub-slice, searching from the end backwards.
- indexOfPos
- Uses Boyer-Moore-Horspool algorithm on large inputs; `indexOfPosLinear` on small inputs.
- count
- Returns the number of needles inside the haystack
- containsAtLeast
- Returns true if the haystack contains expected_count or more needles
- containsAtLeastScalar
- Returns true if the haystack contains expected_count or more needles
- readVarInt
- Reads an integer from memory with size equal to bytes.len.
- readVarPackedInt
- Loads an integer from packed memory with provided bit_count, bit_offset, and signedness.
- readInt
- Reads an integer from memory with bit count specified by T.
- readPackedInt
- Loads an integer from packed memory.
- writeInt
- Writes an integer to memory, storing it in twos-complement.
- writePackedInt
- Stores an integer to packed memory.
- writeVarPackedInt
- Stores an integer to packed memory with provided bit_offset, bit_count, and signedness.
- byteSwapAllFields
- Swap the byte order of all the members of the fields of a struct
- tokenizeAny
- Returns an iterator that iterates over the slices of `buffer` that are not
- tokenizeSequence
- Returns an iterator that iterates over the slices of `buffer` that are not
- tokenizeScalar
- Returns an iterator that iterates over the slices of `buffer` that are not
- splitSequence
- Returns an iterator that iterates over the slices of `buffer` that
- splitAny
- Returns an iterator that iterates over the slices of `buffer` that
- splitScalar
- Returns an iterator that iterates over the slices of `buffer` that
- splitBackwardsSequence
- Returns an iterator that iterates backwards over the slices of `buffer` that
- splitBackwardsAny
- Returns an iterator that iterates backwards over the slices of `buffer` that
- splitBackwardsScalar
- Returns an iterator that iterates backwards over the slices of `buffer` that
- window
- Returns an iterator with a sliding window of slices for `buffer`.
- join
- Naively combines a series of slices with a separator.
- joinZ
- Naively combines a series of slices with a separator and null terminator.
- concat
- Copies each T from slices into a new slice that exactly holds all the elements.
- concatWithSentinel
- Copies each T from slices into a new slice that exactly holds all the elements.
- concatMaybeSentinel
- Copies each T from slices into a new slice that exactly holds all the elements as well as the sentinel.
- min
- Returns the smallest number in a slice.
- max
- Returns the largest number in a slice.
- minMax
- Finds the smallest and largest number in a slice.
- indexOfMin
- Returns the index of the smallest number in a slice.
- indexOfMax
- Returns the index of the largest number in a slice.
- indexOfMinMax
- Finds the indices of the smallest and largest number in a slice.
- reverse
- In-place order reversal of a slice
- reverseIterator
- Iterates over a slice in reverse.
- rotate
- In-place rotation of the values in an array ([0 1 2 3] becomes [1 2 3 0] if we rotate by 1)
- replace
- Replace needle with replacement as many times as possible, writing to an output buffer which is assumed to be of
- replaceScalar
- Replace all occurrences of `match` with `replacement`.
- collapseRepeatsLen
- Collapse consecutive duplicate elements into one entry.
- collapseRepeats
- Collapse consecutive duplicate elements into one entry.
- replacementSize
- Calculate the size needed in an output buffer to perform a replacement.
- replaceOwned
- Perform a replacement on an allocated buffer of pre-determined size.
- littleToNative
- Converts a little-endian integer to host endianness.
- bigToNative
- Converts a big-endian integer to host endianness.
- toNative
- Converts an integer from specified endianness to host endianness.
- nativeTo
- Converts an integer which has host endianness to the desired endianness.
- nativeToLittle
- Converts an integer which has host endianness to little endian.
- nativeToBig
- Converts an integer which has host endianness to big endian.
- alignPointerOffset
- Returns the number of elements that, if added to the given pointer, align it
- alignPointer
- Aligns a given pointer value to a specified alignment factor.
- asBytes
- Given a pointer to a single item, returns a slice of the underlying bytes, preserving pointer attributes.
- toBytes
- Given any value, returns a copy of its bytes in an array.
- bytesAsValue
- Given a pointer to an array of bytes, returns a pointer to a value of the specified type
- bytesToValue
- Given a pointer to an array of bytes, returns a value of the specified type backed by a
- bytesAsSlice
- Given a slice of bytes, returns a slice of the specified type
- sliceAsBytes
- Given a slice, returns a slice of the underlying bytes, preserving pointer attributes.
- alignForwardAnyAlign
- Round an address down to the next (or current) aligned address.
- alignForward
- Round an address up to the next (or current) aligned address.
- doNotOptimizeAway
- Force an evaluation of the expression; this tries to prevent
- alignBackwardAnyAlign
- Round an address down to the previous (or current) aligned address.
- alignBackward
- Round an address down to the previous (or current) aligned address.
- isValidAlign
- Returns whether `alignment` is a valid alignment, meaning it is
- isValidAlignGeneric
- Returns whether `alignment` is a valid alignment, meaning it is
- isAligned
- Given an address and an alignment, return true if the address is a multiple of the alignment
- alignInBytes
- Returns the largest slice in the given bytes that conforms to the new alignment,
- alignInSlice
- Returns the largest sub-slice within the given slice that conforms to the new alignment,
The standard library currently thoroughly depends on byte size
Values
- byte_size_in_bits
- The standard library currently thoroughly depends on byte size
- readPackedIntNative
- = switch (native_endian) { .little => readPackedIntLittle, .big => readPackedIntBig, }
- readPackedIntForeign
- = switch (native_endian) { .little => readPackedIntBig, .big => readPackedIntLittle, }
- writePackedIntNative
- = switch (native_endian) { .little => writePackedIntLittle, .big => writePackedIntBig, }
- writePackedIntForeign
- = switch (native_endian) { .little => writePackedIntBig, .big => writePackedIntLittle, }
Source
Implementation
fn eqlBytes(a: []const u8, b: []const u8) bool {
comptime assert(use_vectors_for_comparison);
if (a.len != b.len) return false;
if (a.len == 0 or a.ptr == b.ptr) return true;
if (a.len <= 16) {
if (a.len < 4) {
const x = (a[0] ^ b[0]) | (a[a.len - 1] ^ b[a.len - 1]) | (a[a.len / 2] ^ b[a.len / 2]);
return x == 0;
}
var x: u32 = 0;
for ([_]usize{ 0, a.len - 4, (a.len / 8) * 4, a.len - 4 - ((a.len / 8) * 4) }) |n| {
x |= @as(u32, @bitCast(a[n..][0..4].*)) ^ @as(u32, @bitCast(b[n..][0..4].*));
}
return x == 0;
}
// Figure out the fastest way to scan through the input in chunks.
// Uses vectors when supported and falls back to usize/words when not.
const Scan = if (std.simd.suggestVectorLength(u8)) |vec_size|
struct {
pub const size = vec_size;
pub const Chunk = @Vector(size, u8);
pub inline fn isNotEqual(chunk_a: Chunk, chunk_b: Chunk) bool {
return @reduce(.Or, chunk_a != chunk_b);
}
}
else
struct {
pub const size = @sizeOf(usize);
pub const Chunk = usize;
pub inline fn isNotEqual(chunk_a: Chunk, chunk_b: Chunk) bool {
return chunk_a != chunk_b;
}
};
inline for (1..6) |s| {
const n = 16 << s;
if (n <= Scan.size and a.len <= n) {
const V = @Vector(n / 2, u8);
var x = @as(V, a[0 .. n / 2].*) ^ @as(V, b[0 .. n / 2].*);
x |= @as(V, a[a.len - n / 2 ..][0 .. n / 2].*) ^ @as(V, b[a.len - n / 2 ..][0 .. n / 2].*);
const zero: V = @splat(0);
return !@reduce(.Or, x != zero);
}
}
// Compare inputs in chunks at a time (excluding the last chunk).
for (0..(a.len - 1) / Scan.size) |i| {
const a_chunk: Scan.Chunk = @bitCast(a[i * Scan.size ..][0..Scan.size].*);
const b_chunk: Scan.Chunk = @bitCast(b[i * Scan.size ..][0..Scan.size].*);
if (Scan.isNotEqual(a_chunk, b_chunk)) return false;
}
// Compare the last chunk using an overlapping read (similar to the previous size strategies).
const last_a_chunk: Scan.Chunk = @bitCast(a[a.len - Scan.size ..][0..Scan.size].*);
const last_b_chunk: Scan.Chunk = @bitCast(b[a.len - Scan.size ..][0..Scan.size].*);
return !Scan.isNotEqual(last_a_chunk, last_b_chunk);
}