Blame lib/memmem.c

Packit Service a2489d
/* Copyright (C) 1991-1994, 1996-1998, 2000, 2004, 2007-2018 Free Software
Packit Service a2489d
   Foundation, Inc.
Packit Service a2489d
   This file is part of the GNU C Library.
Packit Service a2489d
Packit Service a2489d
   This program is free software; you can redistribute it and/or modify
Packit Service a2489d
   it under the terms of the GNU General Public License as published by
Packit Service a2489d
   the Free Software Foundation; either version 3, or (at your option)
Packit Service a2489d
   any later version.
Packit Service a2489d
Packit Service a2489d
   This program is distributed in the hope that it will be useful,
Packit Service a2489d
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service a2489d
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service a2489d
   GNU General Public License for more details.
Packit Service a2489d
Packit Service a2489d
   You should have received a copy of the GNU General Public License along
Packit Service a2489d
   with this program; if not, see <https://www.gnu.org/licenses/>.  */
Packit Service a2489d
Packit Service a2489d
/* This particular implementation was written by Eric Blake, 2008.  */
Packit Service a2489d
Packit Service a2489d
#ifndef _LIBC
Packit Service a2489d
# include <config.h>
Packit Service a2489d
#endif
Packit Service a2489d
Packit Service a2489d
/* Specification of memmem.  */
Packit Service a2489d
#include <string.h>
Packit Service a2489d
Packit Service a2489d
#define RETURN_TYPE void *
Packit Service a2489d
#define AVAILABLE(h, h_l, j, n_l) ((j) <= (h_l) - (n_l))
Packit Service a2489d
#include "str-two-way.h"
Packit Service a2489d
Packit Service a2489d
/* Return the first occurrence of NEEDLE in HAYSTACK.  Return HAYSTACK
Packit Service a2489d
   if NEEDLE_LEN is 0, otherwise NULL if NEEDLE is not found in
Packit Service a2489d
   HAYSTACK.  */
Packit Service a2489d
void *
Packit Service a2489d
memmem (const void *haystack_start, size_t haystack_len,
Packit Service a2489d
        const void *needle_start, size_t needle_len)
Packit Service a2489d
{
Packit Service a2489d
  /* Abstract memory is considered to be an array of 'unsigned char' values,
Packit Service a2489d
     not an array of 'char' values.  See ISO C 99 section 6.2.6.1.  */
Packit Service a2489d
  const unsigned char *haystack = (const unsigned char *) haystack_start;
Packit Service a2489d
  const unsigned char *needle = (const unsigned char *) needle_start;
Packit Service a2489d
Packit Service a2489d
  if (needle_len == 0)
Packit Service a2489d
    /* The first occurrence of the empty string is deemed to occur at
Packit Service a2489d
       the beginning of the string.  */
Packit Service a2489d
    return (void *) haystack;
Packit Service a2489d
Packit Service a2489d
  /* Sanity check, otherwise the loop might search through the whole
Packit Service a2489d
     memory.  */
Packit Service a2489d
  if (__builtin_expect (haystack_len < needle_len, 0))
Packit Service a2489d
    return NULL;
Packit Service a2489d
Packit Service a2489d
  /* Use optimizations in memchr when possible, to reduce the search
Packit Service a2489d
     size of haystack using a linear algorithm with a smaller
Packit Service a2489d
     coefficient.  However, avoid memchr for long needles, since we
Packit Service a2489d
     can often achieve sublinear performance.  */
Packit Service a2489d
  if (needle_len < LONG_NEEDLE_THRESHOLD)
Packit Service a2489d
    {
Packit Service a2489d
      haystack = memchr (haystack, *needle, haystack_len);
Packit Service a2489d
      if (!haystack || __builtin_expect (needle_len == 1, 0))
Packit Service a2489d
        return (void *) haystack;
Packit Service a2489d
      haystack_len -= haystack - (const unsigned char *) haystack_start;
Packit Service a2489d
      if (haystack_len < needle_len)
Packit Service a2489d
        return NULL;
Packit Service a2489d
      return two_way_short_needle (haystack, haystack_len, needle, needle_len);
Packit Service a2489d
    }
Packit Service a2489d
  else
Packit Service a2489d
    return two_way_long_needle (haystack, haystack_len, needle, needle_len);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
#undef LONG_NEEDLE_THRESHOLD