mirror of
https://github.com/apache/nuttx.git
synced 2025-12-06 09:01:15 +08:00
libc/memmem:porting open source memmem to Nuttx.
Signed-off-by: yangguangcai <yangguangcai@xiaomi.com>
This commit is contained in:
1
LICENSE
1
LICENSE
@@ -6333,6 +6333,7 @@ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
libs/libc/string/lib_memmem.c
|
||||
libs/libc/string/lib_strstr.c
|
||||
===============================
|
||||
The MIT License (MIT)
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
/****************************************************************************
|
||||
* libs/libc/string/lib_memmem.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* Copyright (c) 2014-2015 Tal Einat
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@@ -26,6 +31,14 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ALLOW_MIT_COMPONENTS
|
||||
#define LONG_INT_N_BYTES sizeof(long)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -48,6 +61,239 @@
|
||||
FAR void *memmem(FAR const void *haystack, size_t haystacklen,
|
||||
FAR const void *needle, size_t needlelen)
|
||||
{
|
||||
#ifdef CONFIG_ALLOW_MIT_COMPONENTS
|
||||
FAR const unsigned char *needle_ptr;
|
||||
FAR const unsigned char *haystack_ptr;
|
||||
int sums_diff;
|
||||
size_t compare_len;
|
||||
unsigned long last_needle_chars;
|
||||
unsigned long last_haystack_chars;
|
||||
unsigned int i;
|
||||
|
||||
switch (needlelen)
|
||||
{
|
||||
case (0):
|
||||
|
||||
/* empty needle */
|
||||
|
||||
return (FAR void *)haystack;
|
||||
break;
|
||||
case (1):
|
||||
|
||||
/* special case for single-character needles */
|
||||
|
||||
return memchr(haystack,
|
||||
*((FAR unsigned char *)needle), haystacklen);
|
||||
break;
|
||||
}
|
||||
|
||||
/* start searching through haystack only from the first occurence of
|
||||
* the first character of needle.
|
||||
*/
|
||||
|
||||
haystack_ptr = (FAR const unsigned char *)memchr(haystack,
|
||||
*((FAR const unsigned char *)needle), haystacklen);
|
||||
if (!haystack_ptr)
|
||||
{
|
||||
/* the first character of needle isn't in haystack */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
haystacklen -= (haystack_ptr - (FAR const unsigned char *)haystack);
|
||||
if (haystacklen < needlelen)
|
||||
{
|
||||
/* the remaining haystack is smaller than needle */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
haystack = (FAR void *)haystack_ptr;
|
||||
|
||||
if (needlelen > LONG_INT_N_BYTES + 1)
|
||||
{
|
||||
needle_ptr = (FAR const unsigned char *)needle;
|
||||
sums_diff = 0;
|
||||
for (i = needlelen - LONG_INT_N_BYTES; i > 0; --i)
|
||||
{
|
||||
sums_diff -= *needle_ptr++;
|
||||
sums_diff += *haystack_ptr++;
|
||||
}
|
||||
|
||||
last_needle_chars = 0;
|
||||
last_haystack_chars = 0;
|
||||
for (i = LONG_INT_N_BYTES; i > 0; --i)
|
||||
{
|
||||
last_needle_chars <<= 8;
|
||||
last_needle_chars ^= *needle_ptr;
|
||||
last_haystack_chars <<= 8;
|
||||
last_haystack_chars ^= *haystack_ptr;
|
||||
sums_diff -= *needle_ptr++;
|
||||
sums_diff += *haystack_ptr++;
|
||||
}
|
||||
|
||||
/* we will call memcmp() only once we know that the sums are equal
|
||||
* and that LONG_INT_N_BYTES last chars are equal, so it will be
|
||||
* enough to compare all but the last LONG_INT_N_BYTES + 1
|
||||
* characters.
|
||||
*/
|
||||
|
||||
compare_len = needlelen - (LONG_INT_N_BYTES + 1);
|
||||
|
||||
/* At this point:
|
||||
* needle is at least two characters long
|
||||
* haystack is at least needlelen characters long (also at least two)
|
||||
* the first characters of needle and haystack are identical
|
||||
*/
|
||||
|
||||
if (sums_diff == 0
|
||||
&& last_haystack_chars == last_needle_chars
|
||||
&& memcmp(haystack, needle, compare_len) == 0)
|
||||
{
|
||||
return (FAR void *)haystack;
|
||||
}
|
||||
|
||||
/* iterate through the remainder of haystack, updating the sums'
|
||||
* differenceand checking for identity whenever the difference
|
||||
* is zero.
|
||||
*/
|
||||
|
||||
for (i = haystacklen - needlelen; i > 0; --i)
|
||||
{
|
||||
last_haystack_chars <<= 8;
|
||||
last_haystack_chars ^= *haystack_ptr;
|
||||
sums_diff -= *(FAR const unsigned char *)haystack++;
|
||||
sums_diff += *haystack_ptr++;
|
||||
/* if sums_diff == 0, we know that the sums are equal, so it is
|
||||
* enough to compare all but the last characters.
|
||||
*/
|
||||
|
||||
if (sums_diff == 0
|
||||
&& last_haystack_chars == last_needle_chars
|
||||
&& memcmp(haystack, needle, compare_len) == 0)
|
||||
{
|
||||
return (FAR void *)haystack;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (needlelen < LONG_INT_N_BYTES)
|
||||
{
|
||||
needle_ptr = (FAR const unsigned char *)needle;
|
||||
sums_diff = 0;
|
||||
for (i = needlelen; i > 0; --i)
|
||||
{
|
||||
sums_diff -= *needle_ptr++;
|
||||
sums_diff += *haystack_ptr++;
|
||||
}
|
||||
|
||||
/* we will call memcmp() only once we know that the sums are equal,
|
||||
* so it will be enough to compare all but the last characters.
|
||||
*/
|
||||
|
||||
compare_len = needlelen - 1;
|
||||
|
||||
/* At this point:
|
||||
* needle is at least two characters long
|
||||
* haystack is at least needlelen characters long (also at least two)
|
||||
* the first characters of needle and haystack are identical
|
||||
*/
|
||||
|
||||
if (sums_diff == 0
|
||||
&& memcmp(haystack, needle, compare_len) == 0)
|
||||
{
|
||||
return (FAR void *)haystack;
|
||||
}
|
||||
|
||||
/* iterate through the remainder of haystack, updating the sums'
|
||||
* difference and checking for identity whenever the difference
|
||||
* is zero.
|
||||
*/
|
||||
|
||||
for (i = haystacklen - needlelen; i > 0; --i)
|
||||
{
|
||||
sums_diff -= *(FAR const unsigned char *)haystack++;
|
||||
sums_diff += *haystack_ptr++;
|
||||
/* if sums_diff == 0, we know that the sums are equal, so it is
|
||||
* enough to compare all but the last characters.
|
||||
*/
|
||||
|
||||
if (sums_diff == 0
|
||||
&& memcmp(haystack, needle, compare_len) == 0)
|
||||
{
|
||||
return (FAR void *)haystack;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (needlelen == LONG_INT_N_BYTES)
|
||||
{
|
||||
needle_ptr = (FAR const unsigned char *)needle;
|
||||
last_needle_chars = 0;
|
||||
last_haystack_chars = 0;
|
||||
for (i = needlelen; i > 0; --i)
|
||||
{
|
||||
last_needle_chars <<= 8;
|
||||
last_needle_chars ^= *needle_ptr++;
|
||||
last_haystack_chars <<= 8;
|
||||
last_haystack_chars ^= *haystack_ptr++;
|
||||
}
|
||||
|
||||
if (last_haystack_chars == last_needle_chars)
|
||||
{
|
||||
return (FAR void *)haystack;
|
||||
}
|
||||
|
||||
/* iterate through the remainder of haystack, updating the last char
|
||||
* data and checking for equality.
|
||||
*/
|
||||
|
||||
for (i = haystacklen - needlelen; i > 0; --i)
|
||||
{
|
||||
last_haystack_chars <<= 8;
|
||||
last_haystack_chars ^= *haystack_ptr++;
|
||||
if (last_haystack_chars == last_needle_chars)
|
||||
{
|
||||
return (FAR void *)(haystack_ptr - needlelen);
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* needlelen == LONG_INT_N_BYTES + 1 */
|
||||
{
|
||||
needle_ptr = (FAR const unsigned char *)needle;
|
||||
last_needle_chars = 0;
|
||||
last_haystack_chars = 0;
|
||||
for (i = LONG_INT_N_BYTES; i > 0; --i)
|
||||
{
|
||||
last_needle_chars <<= 8;
|
||||
last_needle_chars ^= *needle_ptr++;
|
||||
last_haystack_chars <<= 8;
|
||||
last_haystack_chars ^= *haystack_ptr++;
|
||||
}
|
||||
|
||||
unsigned char last_needle_char =
|
||||
*(((FAR const unsigned char *)needle) + LONG_INT_N_BYTES);
|
||||
|
||||
if (last_haystack_chars == last_needle_chars
|
||||
&& *haystack_ptr == last_needle_char)
|
||||
{
|
||||
return (FAR void *)haystack;
|
||||
}
|
||||
|
||||
/* iterate through the remainder of haystack, updating the last char
|
||||
* data and checking for equality.
|
||||
*/
|
||||
|
||||
for (i = haystacklen - needlelen; i > 0; --i)
|
||||
{
|
||||
last_haystack_chars <<= 8;
|
||||
last_haystack_chars ^= *haystack_ptr++;
|
||||
if (last_haystack_chars == last_needle_chars
|
||||
&& *haystack_ptr == last_needle_char)
|
||||
{
|
||||
return (FAR void *)(haystack_ptr - (needlelen - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
FAR const unsigned char *h = haystack;
|
||||
FAR const unsigned char *n = needle;
|
||||
size_t i;
|
||||
@@ -74,6 +320,7 @@ FAR void *memmem(FAR const void *haystack, size_t haystacklen,
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,9 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ALLOW_MIT_COMPONENTS
|
||||
#define LONG_INT_N_BYTES sizeof(long)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -53,6 +55,7 @@
|
||||
#undef strstr /* See mm/README.txt */
|
||||
FAR char *strstr(FAR const char *haystack, FAR const char *needle)
|
||||
{
|
||||
#ifdef CONFIG_ALLOW_MIT_COMPONENTS
|
||||
FAR const unsigned char *needle_cmp_end;
|
||||
FAR const unsigned char *i_haystack;
|
||||
const char needle_first = *needle;
|
||||
@@ -226,6 +229,57 @@ FAR char *strstr(FAR const char *haystack, FAR const char *needle)
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
FAR const char *candidate; /* Candidate in haystack with matching start character */
|
||||
char ch; /* First character of the substring */
|
||||
size_t len; /* The length of the substring */
|
||||
|
||||
/* Special case the empty substring */
|
||||
|
||||
len = strlen(needle);
|
||||
ch = *needle;
|
||||
|
||||
if (!ch)
|
||||
{
|
||||
/* We'll say that an empty substring matches at the beginning of
|
||||
* the string
|
||||
*/
|
||||
|
||||
return (FAR char *)haystack;
|
||||
}
|
||||
|
||||
/* Search for the substring */
|
||||
|
||||
candidate = haystack;
|
||||
for (; ; )
|
||||
{
|
||||
/* strchr() will return a pointer to the next occurrence of the
|
||||
* character ch in the string
|
||||
*/
|
||||
|
||||
candidate = strchr(candidate, ch);
|
||||
if (!candidate || strlen(candidate) < len)
|
||||
{
|
||||
/* First character of the substring does not appear in the string
|
||||
* or the remainder of the string is not long enough to contain the
|
||||
* substring.
|
||||
*/
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if this is the beginning of a matching substring */
|
||||
|
||||
if (strncmp(candidate, needle, len) == 0)
|
||||
{
|
||||
return (FAR char *)candidate;
|
||||
}
|
||||
|
||||
/* No, find the next candidate after this one */
|
||||
|
||||
candidate++;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user