Merge the newlibc string into NuttX.

Signed-off-by: yangguangcai <yangguangcai@xiaomi.com>
This commit is contained in:
yangguangcai 2024-01-26 10:50:25 +08:00 committed by Xiang Xiao
parent d802912cba
commit 6e87f11083
21 changed files with 1128 additions and 9 deletions

31
LICENSE
View file

@ -8664,3 +8664,34 @@ drivers/i3c/internals.h
Author: Boris Brezillon <boris.brezillon@bootlin.com>
SPDX-License-Identifier: Apache-2.0
libs/libc/string/lib_memccpy.c
libs/libc/string/lib_memchr.c
libs/libc/string/lib_memcmp.c
libs/libc/string/lib_memcpy.c
libs/libc/string/lib_memrchr.c
libs/libc/string/lib_stpcpy.c
libs/libc/string/lib_stpncpy.c
libs/libc/string/lib_strcat.c
libs/libc/string/lib_strchr.c
libs/libc/string/lib_strchrnul.c
libs/libc/string/lib_strcmp.c
libs/libc/string/lib_strcpy.c
libs/libc/string/lib_strlen.c
libs/libc/string/lib_strncmp.c
libs/libc/string/lib_strncpy.c
libs/libc/string/lib_strrchr.c
======================
Copyright (c) 1994-2009 Red Hat, Inc. All rights reserved.
This copyrighted material is made available to anyone wishing to use,
modify, copy, or redistribute it subject to the terms and conditions
of the BSD License. This program is distributed in the hope that
it will be useful, but WITHOUT ANY WARRANTY expressed or implied,
including the implied warranties of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. A copy of this license is available at
http://www.opensource.org/licenses. Any Red Hat trademarks that are
incorporated in the source code or documentation are not subject to
the BSD License and may only be used or replicated with the express
permission of Red Hat, Inc.

View file

@ -36,6 +36,13 @@ config LIBC_STRERROR_ERRNUM
for unknown errors like "Unknown error 101". Default enabled when
LIBC_STRERROR is not selected.
config LIBC_STRING_OPTIMIZE
bool "optimized string function"
depends on ALLOW_BSD_COMPONENTS
default y
--help--
Use optimized string function implementation based on newlib.
config LIBC_PERROR_STDOUT
bool "perror() to stdout"
default n

View file

@ -28,6 +28,36 @@
#include <sys/types.h>
#include <string.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
/* Nonzero if either x or y is not aligned on a "long" boundary. */
#define UNALIGNED(x, y) \
(((long)(uintptr_t)(x) & (sizeof(long) - 1)) | ((long)(uintptr_t)(y) & (sizeof(long) - 1)))
/* How many bytes are copied each iteration of the word copy loop. */
#define LITTLEBLOCKSIZE (sizeof(long))
/* Threshhold for punting to the byte copier. */
#define TOO_SMALL(len) ((len) < LITTLEBLOCKSIZE)
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */
# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -51,6 +81,71 @@
#undef memccpy /* See mm/README.txt */
FAR void *memccpy(FAR void *s1, FAR const void *s2, int c, size_t n)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR void *ptr = NULL;
FAR unsigned char *pout = (FAR unsigned char *)s1;
FAR const unsigned char *pin = (FAR const unsigned char *)s2;
FAR long *paligned_out;
FAR const long *paligned_in;
unsigned char endchar = c & 0xff;
/* If the size is small, or either pin or pout is unaligned,
* then punt into the byte copy loop. This should be rare.
*/
if (!TOO_SMALL(n) && !UNALIGNED(pin, pout))
{
unsigned int i;
unsigned long mask = 0;
paligned_out = (FAR long *)pout;
paligned_in = (FAR long *)pin;
/* The fast code reads the ASCII one word at a time and only
* performs the bytewise search on word-sized segments if they
* contain the search character, which is detected by XORing
* the word-sized segment with a word-sized block of the search
* character and then detecting for the presence of NULL in the
* result.
*/
for (i = 0; i < LITTLEBLOCKSIZE; i++)
{
mask = (mask << 8) + endchar;
}
/* Copy one long word at a time if possible. */
while (n >= LITTLEBLOCKSIZE)
{
unsigned long buffer = (unsigned long)(*paligned_in);
buffer ^= mask;
if (DETECTNULL(buffer))
{
break; /* endchar is found, go byte by byte from here */
}
*paligned_out++ = *paligned_in++;
n -= LITTLEBLOCKSIZE;
}
/* Pick up any residual with a byte copier. */
pout = (FAR unsigned char *)paligned_out;
pin = (FAR unsigned char *)paligned_in;
}
while (n--)
{
if ((*pout++ = *pin++) == endchar)
{
ptr = pout;
break;
}
}
return ptr;
#else
FAR unsigned char *pout = (FAR unsigned char *)s1;
FAR unsigned char *pin = (FAR unsigned char *)s2;
@ -75,4 +170,5 @@ FAR void *memccpy(FAR void *s1, FAR const void *s2, int c, size_t n)
/* C was not found in the first n bytes of s2 */
return NULL;
#endif
}

View file

@ -30,6 +30,38 @@
#include "libc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
#define UNALIGNED(x) ((long)(uintptr_t)(x) & (sizeof(long) - 1))
/* How many bytes are loaded each iteration of the word copy loop. */
#define LBLOCKSIZE (sizeof(long))
/* Threshhold for punting to the bytewise iterator. */
#define TOO_SMALL(len) ((len) < LBLOCKSIZE)
#if LONG_MAX == 2147483647
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */
# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif
/* DETECTCHAR returns nonzero if (long)x contains the byte used
* to fill (long)mask.
*/
#define DETECTCHAR(x, mask) (DETECTNULL((x) ^ (mask)))
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -52,6 +84,76 @@
#undef memchr /* See mm/README.txt */
FAR void *memchr(FAR const void *s, int c, size_t n)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR const unsigned char *p = (FAR const unsigned char *)s;
FAR unsigned long *asrc;
unsigned char d = c;
unsigned long mask;
unsigned int i;
while (UNALIGNED(p))
{
if (!n--)
{
return NULL;
}
if (*p == d)
{
return (FAR void *)p;
}
p++;
}
if (!TOO_SMALL(n))
{
/* If we get this far, we know that n is large and p is
* word-aligned.
* The fast code reads the source one word at a time and only
* performs the bytewise search on word-sized segments if they
* contain the search character, which is detected by XORing
* the word-sized segment with a word-sized block of the search
* character and then detecting for the presence of NUL in the
* result.
*/
asrc = (FAR unsigned long *)p;
mask = d << 8 | d;
mask = mask << 16 | mask;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
{
mask = (mask << i) | mask;
}
while (n >= LBLOCKSIZE)
{
if (DETECTCHAR(*asrc, mask))
{
break;
}
n -= LBLOCKSIZE;
asrc++;
}
/* If there are fewer than LBLOCKSIZE characters left,
* then we resort to the bytewise loop.
*/
p = (FAR unsigned char *)asrc;
}
while (n--)
{
if (*p == d)
{
return (FAR void *)p;
}
p++;
}
#else
FAR const unsigned char *p = (FAR const unsigned char *)s;
while (n--)
@ -63,6 +165,7 @@ FAR void *memchr(FAR const void *s, int c, size_t n)
p++;
}
#endif
return NULL;
}

View file

@ -30,6 +30,26 @@
#include "libc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
/* Nonzero if either x or y is not aligned on a "long" boundary. */
#define UNALIGNED(x, y) \
(((long)(uintptr_t)(x) & (sizeof(long) - 1)) | ((long)(uintptr_t)(y) & (sizeof(long) - 1)))
/* How many bytes are copied each iteration of the word copy loop. */
#define LBLOCKSIZE (sizeof(long))
/* Threshhold for punting to the byte copier. */
#define TOO_SMALL(len) ((len) < LBLOCKSIZE)
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -39,6 +59,54 @@
no_builtin("memcmp")
int memcmp(FAR const void *s1, FAR const void *s2, size_t n)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR unsigned char *p1 = (FAR unsigned char *)s1;
FAR unsigned char *p2 = (FAR unsigned char *)s2;
FAR unsigned long *a1;
FAR unsigned long *a2;
/* If the size is too small, or either pointer is unaligned,
* then we punt to the byte compare loop. Hopefully this will
* not turn up in inner loops.
*/
if (!TOO_SMALL(n) && !UNALIGNED(p1, p2))
{
/* Otherwise, load and compare the blocks of memory one
* word at a time.
*/
a1 = (FAR unsigned long *)p1;
a2 = (FAR unsigned long *)p2;
while (n >= LBLOCKSIZE)
{
if (*a1 != *a2)
{
break;
}
a1++;
a2++;
n -= LBLOCKSIZE;
}
/* check s mod LBLOCKSIZE remaining characters */
p1 = (FAR unsigned char *)a1;
p2 = (FAR unsigned char *)a2;
}
while (n--)
{
if (*p1 != *p2)
{
return *p1 - *p2;
}
p1++;
p2++;
}
#else
FAR unsigned char *p1 = (FAR unsigned char *)s1;
FAR unsigned char *p2 = (FAR unsigned char *)s2;
@ -56,6 +124,7 @@ int memcmp(FAR const void *s1, FAR const void *s2, size_t n)
p1++;
p2++;
}
#endif
return 0;
}

View file

@ -30,6 +30,30 @@
#include "libc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
/* Nonzero if either x or y is not aligned on a "long" boundary. */
#define UNALIGNED(x, y) \
(((long)(uintptr_t)(x) & (sizeof(long) - 1)) | ((long)(uintptr_t)(y) & (sizeof(long) - 1)))
/* How many bytes are copied each iteration of the 4X unrolled loop. */
#define BIGBLOCKSIZE (sizeof(long) << 2)
/* How many bytes are copied each iteration of the word copy loop. */
#define LITTLEBLOCKSIZE (sizeof(long))
/* Threshhold for punting to the byte copier. */
#define TOO_SMALL(len) ((len) < BIGBLOCKSIZE)
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -43,12 +67,58 @@
no_builtin("memcpy")
FAR void *memcpy(FAR void *dest, FAR const void *src, size_t n)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR char *pout = dest;
FAR const char *pin = src;
FAR long *paligned_out;
FAR const long *paligned_in;
/* If the size is small, or either pin or pout is unaligned,
* then punt into the byte copy loop. This should be rare.
*/
if (!TOO_SMALL(n) && !UNALIGNED(pin, pout))
{
paligned_out = (FAR long *)pout;
paligned_in = (FAR long *)pin;
/* Copy 4X long words at a time if possible. */
while (n >= BIGBLOCKSIZE)
{
*paligned_out++ = *paligned_in++;
*paligned_out++ = *paligned_in++;
*paligned_out++ = *paligned_in++;
*paligned_out++ = *paligned_in++;
n -= BIGBLOCKSIZE;
}
/* Copy one long word at a time if possible. */
while (n >= LITTLEBLOCKSIZE)
{
*paligned_out++ = *paligned_in++;
n -= LITTLEBLOCKSIZE;
}
/* Pick up any residual with a byte copier. */
pout = (FAR char *)paligned_out;
pin = (FAR char *)paligned_in;
}
while (n--)
{
*pout++ = *pin++;
}
#else
FAR unsigned char *pout = (FAR unsigned char *)dest;
FAR unsigned char *pin = (FAR unsigned char *)src;
while (n-- > 0)
{
*pout++ = *pin++;
}
#endif
return dest;
}

View file

@ -44,13 +44,7 @@ FAR void *memmove(FAR void *dest, FAR const void *src, size_t count)
if (dest <= src)
{
tmp = (FAR char *) dest;
s = (FAR char *) src;
while (count--)
{
*tmp++ = *s++;
}
memcpy(dest, src, count);
}
else
{

View file

@ -28,6 +28,37 @@
#include <string.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
/* Nonzero if x is not aligned on a "long" boundary. */
#define UNALIGNED(x) ((long)(uintptr_t)((x) + 1) & (sizeof(long) - 1))
/* How many bytes are loaded each iteration of the word copy loop. */
#define LBLOCKSIZE (sizeof(long))
/* Threshhold for punting to the bytewise iterator. */
#define TOO_SMALL(len) ((len) < LBLOCKSIZE)
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */
# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif
#define DETECTCHAR(x, mask) (DETECTNULL((x) ^ (mask)))
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -49,6 +80,77 @@
#undef memrchr /* See mm/README.txt */
FAR void *memrchr(FAR const void *s, int c, size_t n)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR const unsigned char *src0 =
(FAR const unsigned char *)s + n - 1;
FAR unsigned long *asrc;
unsigned char d = c;
unsigned long mask;
unsigned int i;
while (UNALIGNED(src0))
{
if (!n--)
{
return NULL;
}
if (*src0 == d)
{
return (FAR void *)src0;
}
src0--;
}
if (!TOO_SMALL(n))
{
/* If we get this far, we know that n is large and src0 is
* word-aligned.
* The fast code reads the source one word at a time and only
* performs the bytewise search on word-sized segments if they
* contain the search character, which is detected by XORing
* the word-sized segment with a word-sized block of the search
* character and then detecting for the presence of NUL in the
* result.
*/
asrc = (FAR unsigned long *)(src0 - LBLOCKSIZE + 1);
mask = d << 8 | d;
mask = mask << 16 | mask;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
{
mask = (mask << i) | mask;
}
while (n >= LBLOCKSIZE)
{
if (DETECTCHAR(*asrc, mask))
{
break;
}
n -= LBLOCKSIZE;
asrc--;
}
/* If there are fewer than LBLOCKSIZE characters left,
* then we resort to the bytewise loop.
*/
src0 = (FAR unsigned char *)asrc + LBLOCKSIZE - 1;
}
while (n--)
{
if (*src0 == d)
{
return (FAR void *)src0;
}
src0--;
}
#else
FAR const unsigned char *p = (FAR const unsigned char *)s + n;
while (n--)
@ -58,6 +160,7 @@ FAR void *memrchr(FAR const void *s, int c, size_t n)
return (FAR void *)p;
}
}
#endif
return NULL;
}

View file

@ -28,6 +28,28 @@
#include <string.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
/* Nonzero if either x or y is not aligned on a "long" boundary. */
#define UNALIGNED(x, y) \
(((long)(uintptr_t)(x) & (sizeof(long) - 1)) | ((long)(uintptr_t)(y) & (sizeof(long) - 1)))
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */
# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -49,7 +71,33 @@
#undef stpcpy /* See mm/README.txt */
FAR char *stpcpy(FAR char *dest, FAR const char *src)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR long *aligned_dst;
FAR const long *aligned_src;
/* If src or dest is unaligned, then copy bytes. */
if (!UNALIGNED(src, dest))
{
aligned_dst = (FAR long *)dest;
aligned_src = (FAR long *)src;
/* src and dest are both "long int" aligned, try to do "long int"
* sized copies.
*/
while (!DETECTNULL(*aligned_src))
{
*aligned_dst++ = *aligned_src++;
}
dest = (FAR char *)aligned_dst;
src = (FAR char *)aligned_src;
}
#endif
while ((*dest++ = *src++) != '\0');
return --dest;
}
#endif

View file

@ -28,6 +28,34 @@
#include <sys/types.h>
#include <string.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
/* Nonzero if either x or y is not aligned on a "long" boundary. */
#define UNALIGNED(x, y) \
(((long)(uintptr_t)(x) & (sizeof(long) - 1)) | ((long)(uintptr_t)(y) & (sizeof(long) - 1)))
/* How many bytes are loaded each iteration of the word copy loop. */
#define LBLOCKSIZE (sizeof(long))
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647
#define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */
#define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif
#define TOO_SMALL(len) ((len) < sizeof(long))
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -59,6 +87,49 @@
#undef stpncpy /* See mm/README.txt */
FAR char *stpncpy(FAR char *dest, FAR const char *src, size_t n)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR char *ret = NULL;
FAR long *aligned_dst;
FAR const long *aligned_src;
/* If src and dest is aligned and n large enough, then copy words. */
if (!UNALIGNED(src, dest) && !TOO_SMALL(n))
{
aligned_dst = (FAR long *)dest;
aligned_src = (FAR long *)src;
/* src and dest are both "long int" aligned, try to do "long int"
* sized copies.
*/
while (n >= LBLOCKSIZE && !DETECTNULL(*aligned_src))
{
n -= LBLOCKSIZE;
*aligned_dst++ = *aligned_src++;
}
dest = (FAR char *)aligned_dst;
src = (FAR char *)aligned_src;
}
while (n > 0)
{
--n;
if ((*dest++ = *src++) == '\0')
{
ret = dest - 1;
break;
}
}
while (n-- > 0)
{
*dest++ = '\0';
}
return ret ? ret : dest;
#else
FAR char *end = dest + n; /* End of dest buffer + 1 byte */
FAR char *ret; /* Value to be returned */
@ -91,5 +162,6 @@ FAR char *stpncpy(FAR char *dest, FAR const char *src, size_t n)
}
return ret;
#endif
}
#endif

View file

@ -30,6 +30,27 @@
#include "libc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
#define ALIGNED(x) \
(((long)(uintptr_t)(x) & (sizeof(long) - 1)) == 0)
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */
# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -38,6 +59,37 @@
#undef strcat /* See mm/README.txt */
FAR char *strcat(FAR char *dest, FAR const char *src)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR char *ret = dest;
/* Skip over the data in dest as quickly as possible. */
if (ALIGNED(dest))
{
FAR unsigned long *aligned_s1 = (FAR unsigned long *)dest;
while (!DETECTNULL(*aligned_s1))
{
aligned_s1++;
}
dest = (FAR char *)aligned_s1;
}
while (*dest)
{
dest++;
}
/* dest now points to the its trailing null character, we can
* just use strcpy to do the work for us now.
* ?!? We might want to just include strcpy here.
* Also, this will cause many more unaligned string copies because
* dest is much less likely to be aligned. I don't know if its worth
* tweaking strcpy to handle this better.
*/
strcpy(dest, src);
#else
FAR char *ret = dest;
dest += strlen(dest);
@ -47,6 +99,7 @@ FAR char *strcat(FAR char *dest, FAR const char *src)
}
*dest = '\0';
#endif
return ret;
}

View file

@ -30,6 +30,32 @@
#include "libc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
#define UNALIGNED(x) ((long)(uintptr_t)(x) & (sizeof(long) - 1))
/* How many bytes are loaded each iteration of the word copy loop. */
#define LBLOCKSIZE (sizeof(long))
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */
# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif
#define DETECTCHAR(x, mask) (DETECTNULL((x) ^ (mask)))
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -52,6 +78,92 @@
#undef strchr /* See mm/README.txt */
FAR char *strchr(FAR const char *s, int c)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR const unsigned char *s1 = (FAR const unsigned char *)s;
FAR unsigned long *aligned_addr;
unsigned char i = c;
unsigned long mask;
unsigned long j;
/* Special case for finding 0. */
if (!i)
{
while (UNALIGNED(s1))
{
if (!*s1)
{
return (FAR char *)s1;
}
s1++;
}
/* Operate a word at a time. */
aligned_addr = (FAR unsigned long *)s1;
while (!DETECTNULL(*aligned_addr))
{
aligned_addr++;
}
/* Found the end of string. */
s1 = (FAR const unsigned char *)aligned_addr;
while (*s1)
{
s1++;
}
return (FAR char *)s1;
}
/* All other bytes. Align the pointer, then search a long at a time. */
while (UNALIGNED(s1))
{
if (!*s1)
{
return NULL;
}
if (*s1 == i)
{
return (FAR char *)s1;
}
s1++;
}
mask = i;
for (j = 8; j < LBLOCKSIZE * 8; j <<= 1)
{
mask = (mask << j) | mask;
}
aligned_addr = (FAR unsigned long *)s1;
while (!DETECTNULL(*aligned_addr) && !DETECTCHAR(*aligned_addr, mask))
{
aligned_addr++;
}
/* The block of bytes currently pointed to by aligned_addr
* contains either a null or the target char, or both. We
* catch it using the bytewise search.
*/
s1 = (FAR unsigned char *)aligned_addr;
while (*s1 && *s1 != i)
{
s1++;
}
if (*s1 == i)
{
return (FAR char *)s1;
}
#else
for (; ; s++)
{
if (*s == c)
@ -64,6 +176,7 @@ FAR char *strchr(FAR const char *s, int c)
break;
}
}
#endif
return NULL;
}

View file

@ -52,6 +52,11 @@
#undef strchrnul /* See mm/README.txt */
FAR char *strchrnul(FAR const char *s, int c)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR char *s1 = strchr(s, c);
return s1 ? s1 : (FAR char *)s + strlen(s);
#else
if (s)
{
while (*s != '\0' && *s != c)
@ -61,5 +66,6 @@ FAR char *strchrnul(FAR const char *s, int c)
}
return (FAR char *)s;
#endif
}
#endif

View file

@ -30,6 +30,28 @@
#include "libc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
/* Nonzero if either x or y is not aligned on a "long" boundary. */
#define UNALIGNED(x, y) \
(((long)(uintptr_t)(x) & (sizeof(long) - 1)) | ((long)(uintptr_t)(y) & (sizeof(long) - 1)))
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */
# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -38,6 +60,49 @@
#undef strcmp /* See mm/README.txt */
int strcmp(FAR const char *cs, FAR const char *ct)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR unsigned long *a1;
FAR unsigned long *a2;
/* If cs or ct are unaligned, then compare bytes. */
if (!UNALIGNED(cs, ct))
{
/* If cs and ct are word-aligned, compare them a word at a time. */
a1 = (FAR unsigned long *)cs;
a2 = (FAR unsigned long *)ct;
while (*a1 == *a2)
{
/* To get here, *a1 == *a2, thus if we find a null in *a1,
* then the strings must be equal, so return zero.
*/
if (DETECTNULL(*a1))
{
return 0;
}
a1++;
a2++;
}
/* A difference was detected in last few bytes of cs,
* so search bytewise.
*/
cs = (FAR char *)a1;
ct = (FAR char *)a2;
}
while (*cs != '\0' && *cs == *ct)
{
cs++;
ct++;
}
return (*(FAR unsigned char *)cs) - (*(FAR unsigned char *)ct);
#else
register int result;
for (; ; )
{
@ -49,5 +114,6 @@ int strcmp(FAR const char *cs, FAR const char *ct)
}
return result;
#endif
}
#endif

View file

@ -52,7 +52,7 @@
*
****************************************************************************/
int strcoll(const char *a, const char *b)
int strcoll(FAR const char *a, FAR const char *b)
{
return strcmp(a, b);
}

View file

@ -30,6 +30,28 @@
#include "libc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
/* Nonzero if either x or y is not aligned on a "long" boundary. */
#define UNALIGNED(x, y) \
(((long)(uintptr_t)(x) & (sizeof(long) - 1)) | ((long)(uintptr_t)(y) & (sizeof(long) - 1)))
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */
# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -50,8 +72,39 @@
#undef strcpy /* See mm/README.txt */
FAR char *strcpy(FAR char *dest, FAR const char *src)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR char *dst0 = dest;
FAR const char *src0 = src;
FAR long *aligned_dst;
FAR const long *aligned_src;
/* If SRC or DEST is unaligned, then copy bytes. */
if (!UNALIGNED(src0, dst0))
{
aligned_dst = (FAR long *)dst0;
aligned_src = (FAR long *)src0;
/* SRC and DEST are both "long int" aligned, try to do "long int"
* sized copies.
*/
while (!DETECTNULL(*aligned_src))
{
*aligned_dst++ = *aligned_src++;
}
dst0 = (FAR char *)aligned_dst;
src0 = (FAR char *)aligned_src;
}
while ((*dst0++ = *src0++) != '\0');
return dest;
#else
FAR char *tmp = dest;
while ((*dest++ = *src++) != '\0');
return tmp;
#endif
}
#endif

View file

@ -42,7 +42,7 @@ FAR char *strdup(FAR const char *s)
if (news)
{
strlcpy(news, s, size);
memcpy(news, s, size);
}
return news;

View file

@ -30,6 +30,27 @@
#include "libc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
#define LBLOCKSIZE (sizeof(long))
#define UNALIGNED(x) ((long)(uintptr_t)(x) & (LBLOCKSIZE - 1))
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */
# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -38,8 +59,47 @@
#undef strlen /* See mm/README.txt */
size_t strlen(FAR const char *s)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR const char *start = s;
FAR unsigned long *aligned_addr;
/* Align the pointer, so we can search a word at a time. */
while (UNALIGNED(s))
{
if (!*s)
{
return s - start;
}
s++;
}
/* If the string is word-aligned, we can check for the presence of
* a null in each word-sized block.
*/
aligned_addr = (FAR unsigned long *)s;
while (!DETECTNULL(*aligned_addr))
{
aligned_addr++;
}
/* Once a null is detected, we check each byte in that block for a
* precise position of the null.
*/
s = (FAR char *)aligned_addr;
while (*s)
{
s++;
}
return s - start;
#else
FAR const char *sc;
for (sc = s; *sc != '\0'; ++sc);
return sc - s;
#endif
}
#endif

View file

@ -30,6 +30,31 @@
#include "libc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
#define LBLOCKSIZE (sizeof(long))
/* Nonzero if either x or y is not aligned on a "long" boundary. */
#define UNALIGNED(x, y) \
(((long)(uintptr_t)(x) & (sizeof(long) - 1)) | ((long)(uintptr_t)(y) & (sizeof(long) - 1)))
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */
# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -38,6 +63,65 @@
#undef strncmp /* See mm/README.txt */
int strncmp(FAR const char *cs, FAR const char *ct, size_t nb)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR unsigned long *a1;
FAR unsigned long *a2;
if (nb == 0)
{
return 0;
}
/* If cs or ct are unaligned, then compare bytes. */
if (!UNALIGNED(cs, ct))
{
/* If cs and ct are word-aligned, compare them a word at a time. */
a1 = (FAR unsigned long *)cs;
a2 = (FAR unsigned long *)ct;
while (nb >= LBLOCKSIZE && *a1 == *a2)
{
nb -= LBLOCKSIZE;
/* If we've run out of bytes or hit a null, return zero
* since we already know *a1 == *a2.
*/
if (nb == 0 || DETECTNULL(*a1))
{
return 0;
}
a1++;
a2++;
}
/* A difference was detected in last few bytes of cs, so search
* bytewise.
*/
cs = (FAR char *)a1;
ct = (FAR char *)a2;
}
while (nb-- > 0 && *cs == *ct)
{
/* If we've run out of bytes or hit a null, return zero
* since we already know *cs == *ct.
*/
if (nb == 0 || *cs == '\0')
{
return 0;
}
cs++;
ct++;
}
return *cs - *ct;
#else
register int result = 0;
for (; nb > 0; nb--)
{
@ -49,5 +133,6 @@ int strncmp(FAR const char *cs, FAR const char *ct, size_t nb)
}
return result;
#endif
}
#endif

View file

@ -30,6 +30,33 @@
#include "libc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
#define LBLOCKSIZE (sizeof(long))
/* Nonzero if either x or y is not aligned on a "long" boundary. */
#define UNALIGNED(x, y) \
(((long)(uintptr_t)(x) & (sizeof(long) - 1)) | ((long)(uintptr_t)(y) & (sizeof(long) - 1)))
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */
# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif
#define TOO_SMALL(len) ((len) < sizeof(long))
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -59,6 +86,49 @@
#undef strncpy /* See mm/README.txt */
FAR char *strncpy(FAR char *dest, FAR const char *src, size_t n)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR char *dst0 = dest;
FAR const char *src0 = src;
FAR long *aligned_dst;
FAR const long *aligned_src;
/* If src and dest is aligned and n large enough, then copy words. */
if (!UNALIGNED(src0, dst0) && !TOO_SMALL(n))
{
aligned_dst = (FAR long *)dst0;
aligned_src = (FAR long *)src0;
/* src and dest are both "long int" aligned, try to do "long int"
* sized copies.
*/
while (n >= LBLOCKSIZE && !DETECTNULL(*aligned_src))
{
n -= LBLOCKSIZE;
*aligned_dst++ = *aligned_src++;
}
dst0 = (FAR char *)aligned_dst;
src0 = (FAR char *)aligned_src;
}
while (n > 0)
{
--n;
if ((*dst0++ = *src0++) == '\0')
{
break;
}
}
while (n-- > 0)
{
*dst0++ = '\0';
}
return dest;
#else
FAR char *ret = dest; /* Value to be returned */
FAR char *end = dest + n; /* End of dest buffer + 1 byte */
@ -80,5 +150,6 @@ FAR char *strncpy(FAR char *dest, FAR const char *src, size_t n)
}
return ret;
#endif
}
#endif

View file

@ -42,6 +42,24 @@
#undef strrchr /* See mm/README.txt */
FAR char *strrchr(FAR const char *s, int c)
{
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
FAR const char *last = NULL;
if (c)
{
while ((s = strchr(s, c)))
{
last = s;
s++;
}
}
else
{
last = strchr(s, c);
}
return (FAR char *)last;
#else
FAR const char *r = NULL;
do
@ -54,5 +72,6 @@ FAR char *strrchr(FAR const char *s, int c)
while (*s++ != '\0');
return (FAR char *)r;
#endif
}
#endif