mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 02:48:37 +08:00
Merge the newlibc string into NuttX.
Signed-off-by: yangguangcai <yangguangcai@xiaomi.com>
This commit is contained in:
parent
d802912cba
commit
6e87f11083
21 changed files with 1128 additions and 9 deletions
31
LICENSE
31
LICENSE
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -42,7 +42,7 @@ FAR char *strdup(FAR const char *s)
|
|||
|
||||
if (news)
|
||||
{
|
||||
strlcpy(news, s, size);
|
||||
memcpy(news, s, size);
|
||||
}
|
||||
|
||||
return news;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue