in sdk/src/azure/core/az_span.c [405:478]
AZ_NODISCARD int32_t az_span_find(az_span source, az_span target)
{
/* This function implements the Naive string-search algorithm.
* The rationale to use this algorithm instead of other potentially more
* performing ones (Rabin-Karp, e.g.) is due to no additional space needed.
* The logic:
* 1. The function will look into each position of `source` if it contains the same value as the
* first position of `target`.
* 2. If it does, it could be that the next bytes in `source` are a perfect match of the remaining
* bytes of `target`.
* 3. Being so, it loops through the remaining bytes of `target` and see if they match exactly the
* next bytes of `source`.
* 4. If the loop gets to the end (all bytes of `target` are evaluated), it means `target` indeed
* occurs in that position of `source`.
* 5. If the loop gets interrupted before cruising through the entire `target`, the function must
* go back to step 1. from the next position in `source`.
* The loop in 5. gets interrupted if
* - a byte in `target` is different than `source`, in the expected corresponding position;
* - the loop has reached the end of `source` (and there are still remaining bytes of `target`
* to be checked).
*/
int32_t source_size = az_span_size(source);
int32_t target_size = az_span_size(target);
const int32_t target_not_found = -1;
if (target_size == 0)
{
return 0;
}
if (source_size < target_size)
{
return target_not_found;
}
uint8_t* source_ptr = az_span_ptr(source);
uint8_t* target_ptr = az_span_ptr(target);
// This loop traverses `source` position by position (step 1.)
for (int32_t i = 0; i < (source_size - target_size + 1); i++)
{
// This is the check done in step 1. above.
if (source_ptr[i] == target_ptr[0])
{
// The condition in step 2. has been satisfied.
int32_t j = 1;
// This is the loop defined in step 3.
// The loop must be broken if it reaches the ends of `target` (step 3.) OR `source`
// (step 5.).
for (; j < target_size && (i + j) < source_size; j++)
{
// Condition defined in step 5.
if (source_ptr[i + j] != target_ptr[j])
{
break;
}
}
if (j == target_size)
{
// All bytes in `target` have been checked and matched the corresponding bytes in `source`
// (from the start point `i`), so this is indeed an instance of `target` in that position
// of `source` (step 4.).
return i;
}
}
}
// If the function hasn't returned before, all positions
// of `source` have been evaluated but `target` could not be found.
return target_not_found;
}