[][src]Macro safe_arch::string_search_for_index

macro_rules! string_search_for_index {
    ([$needle:expr, $needle_len:expr], [$haystack:expr, $haystack_len:expr], $char_type:tt, $search_op:tt, $index_end:tt) => { ... };
    ($needle:expr, $haystack:expr, $char_type:tt, $search_op:tt, $index_end:tt) => { ... };
    (@_char_type u8) => { ... };
    (@_char_type u16) => { ... };
    (@_char_type i8) => { ... };
    (@_char_type i16) => { ... };
    (@_char_type $unknown:tt) => { ... };
    (@_search_op EqAny) => { ... };
    (@_search_op CmpRanges) => { ... };
    (@_search_op CmpEqEach) => { ... };
    (@_search_op CmpEqOrdered) => { ... };
    (@_search_op $unknown:tt) => { ... };
    (@_index_end FirstMatch) => { ... };
    (@_index_end LastMatch) => { ... };
    (@_index_end $unknown:tt) => { ... };
    (@_raw_explicit_len $needle:expr, $needle_len:expr, $haystack:expr, $haystack_len:expr, $imm:expr) => { ... };
    (@_raw_implicit_len $needle:expr, $haystack:expr, $imm:expr) => { ... };
}
This is supported with target feature sse4.2 only.

Looks for $needle in $haystack and gives the index of the either the first or last match.

This is a fairly flexible operation, and so I apologize in advance.

  • The "needle" is the string you're looking for.
  • The "haystack" is the string you're looking inside of.
  • The lengths of each string can be "explicit" or "implicit".
    • "explicit" is specified with [str, len] pairs.
    • "implicit" just ends at the first \0.
    • Either way a string doesn't go past the end of the register.
  • You need to pick a "char type", which can be any of u8, i8, u16, i16. These operations always operate on m128i registers, but the interpretation of the data is configurable.
  • You need to pick the search operation, which determines how the needle is compared to the haystack:
    • EqAny: Matches when any haystack character equals any needle character, regardless of position.
    • CmpRanges: Interprets consecutive pairs of characters in the needle as (low..=high) ranges to compare each haystack character to.
    • CmpEqEach: Matches when a character position in the needle is equal to the character at the same position in the haystack.
    • CmpEqOrdered: Matches when the complete needle string is a substring somewhere in the haystack.
  • Finally, you need to specify if you're looking for the FirstMatch or LastMatch.
    • If no match is found the output will be the length of the haystack.

It's a lot to take in. Hopefully the examples below can help clarify how things work. They all use u8 since Rust string literals are UTF-8, but it's the same with the other character types.

EqAny

let hay: m128i = m128i::from(*b"some test words.");

// explicit needle length
let needle: m128i = m128i::from(*b"e_______________");
let i: ::core::primitive::i32 =
  string_search_for_index!([needle, 1], [hay, 16], u8, EqAny, FirstMatch);
assert_eq!(i, 3);
let i: ::core::primitive::i32 =
  string_search_for_index!([needle, 1], [hay, 16], u8, EqAny, LastMatch);
assert_eq!(i, 6);

// implicit needle length
let needle: m128i = m128i::from(*b"e\0______________");
let i: ::core::primitive::i32 =
  string_search_for_index!(needle, hay, u8, EqAny, FirstMatch);
assert_eq!(i, 3);
let i: ::core::primitive::i32 =
  string_search_for_index!(needle, hay, u8, EqAny, LastMatch);
assert_eq!(i, 6);

// more than one needle character will match any of them, though we
// don't get info about _which_ needle character matched.
let needle: m128i = m128i::from(*b"et\0_____________");
let i: ::core::primitive::i32 =
  string_search_for_index!(needle, hay, u8, EqAny, FirstMatch);
assert_eq!(i, 3);
let i: ::core::primitive::i32 =
  string_search_for_index!(needle, hay, u8, EqAny, LastMatch);
assert_eq!(i, 8);

CmpRanges

let hay: m128i = m128i::from(*b"some test words.");
let needle: m128i = m128i::from(*b"vz\0_____________");
let i: ::core::primitive::i32 =
  string_search_for_index!(needle, hay, u8, CmpRanges, FirstMatch);
assert_eq!(i, 10); // matches the 'w'

CmpEqEach

let hay: m128i = m128i::from(*b"some test words.");
let needle: m128i = m128i::from(*b"_____test_______");
let i: ::core::primitive::i32 =
  string_search_for_index!(needle, hay, u8, CmpEqEach, FirstMatch);
assert_eq!(i, 5); // start of "test"
let i: ::core::primitive::i32 =
  string_search_for_index!(needle, hay, u8, CmpEqEach, LastMatch);
assert_eq!(i, 8); // end of "test"

CmpEqOrdered

let hay: m128i = m128i::from(*b"some test words.");
let needle: m128i = m128i::from(*b"words\0__________");
let i: ::core::primitive::i32 =
  string_search_for_index!(needle, hay, u8, CmpEqOrdered, FirstMatch);
assert_eq!(i, 10); // This is where the "words" substring begins