mirror of
https://github.com/apache/nuttx.git
synced 2026-05-27 19:36:35 +08:00
Merge the newlibc string into NuttX.
Signed-off-by: yangguangcai <yangguangcai@xiaomi.com>
This commit is contained in:
@@ -8664,3 +8664,34 @@ drivers/i3c/internals.h
|
|||||||
Author: Boris Brezillon <boris.brezillon@bootlin.com>
|
Author: Boris Brezillon <boris.brezillon@bootlin.com>
|
||||||
|
|
||||||
SPDX-License-Identifier: Apache-2.0
|
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
|
for unknown errors like "Unknown error 101". Default enabled when
|
||||||
LIBC_STRERROR is not selected.
|
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
|
config LIBC_PERROR_STDOUT
|
||||||
bool "perror() to stdout"
|
bool "perror() to stdout"
|
||||||
default n
|
default n
|
||||||
|
|||||||
@@ -28,6 +28,36 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <string.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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -51,6 +81,71 @@
|
|||||||
#undef memccpy /* See mm/README.txt */
|
#undef memccpy /* See mm/README.txt */
|
||||||
FAR void *memccpy(FAR void *s1, FAR const void *s2, int c, size_t n)
|
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 *pout = (FAR unsigned char *)s1;
|
||||||
FAR unsigned char *pin = (FAR unsigned char *)s2;
|
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 */
|
/* C was not found in the first n bytes of s2 */
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,38 @@
|
|||||||
|
|
||||||
#include "libc.h"
|
#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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -52,6 +84,76 @@
|
|||||||
#undef memchr /* See mm/README.txt */
|
#undef memchr /* See mm/README.txt */
|
||||||
FAR void *memchr(FAR const void *s, int c, size_t n)
|
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;
|
FAR const unsigned char *p = (FAR const unsigned char *)s;
|
||||||
|
|
||||||
while (n--)
|
while (n--)
|
||||||
@@ -63,6 +165,7 @@ FAR void *memchr(FAR const void *s, int c, size_t n)
|
|||||||
|
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,26 @@
|
|||||||
|
|
||||||
#include "libc.h"
|
#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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -39,6 +59,54 @@
|
|||||||
no_builtin("memcmp")
|
no_builtin("memcmp")
|
||||||
int memcmp(FAR const void *s1, FAR const void *s2, size_t n)
|
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 *p1 = (FAR unsigned char *)s1;
|
||||||
FAR unsigned char *p2 = (FAR unsigned char *)s2;
|
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++;
|
p1++;
|
||||||
p2++;
|
p2++;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,30 @@
|
|||||||
|
|
||||||
#include "libc.h"
|
#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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -43,12 +67,58 @@
|
|||||||
no_builtin("memcpy")
|
no_builtin("memcpy")
|
||||||
FAR void *memcpy(FAR void *dest, FAR const void *src, size_t n)
|
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 *pout = (FAR unsigned char *)dest;
|
||||||
FAR unsigned char *pin = (FAR unsigned char *)src;
|
FAR unsigned char *pin = (FAR unsigned char *)src;
|
||||||
while (n-- > 0)
|
while (n-- > 0)
|
||||||
{
|
{
|
||||||
*pout++ = *pin++;
|
*pout++ = *pin++;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,13 +44,7 @@ FAR void *memmove(FAR void *dest, FAR const void *src, size_t count)
|
|||||||
|
|
||||||
if (dest <= src)
|
if (dest <= src)
|
||||||
{
|
{
|
||||||
tmp = (FAR char *) dest;
|
memcpy(dest, src, count);
|
||||||
s = (FAR char *) src;
|
|
||||||
|
|
||||||
while (count--)
|
|
||||||
{
|
|
||||||
*tmp++ = *s++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,6 +28,37 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -49,6 +80,77 @@
|
|||||||
#undef memrchr /* See mm/README.txt */
|
#undef memrchr /* See mm/README.txt */
|
||||||
FAR void *memrchr(FAR const void *s, int c, size_t n)
|
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;
|
FAR const unsigned char *p = (FAR const unsigned char *)s + n;
|
||||||
|
|
||||||
while (n--)
|
while (n--)
|
||||||
@@ -58,6 +160,7 @@ FAR void *memrchr(FAR const void *s, int c, size_t n)
|
|||||||
return (FAR void *)p;
|
return (FAR void *)p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,28 @@
|
|||||||
|
|
||||||
#include <string.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)))
|
||||||
|
|
||||||
|
/* 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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -49,7 +71,33 @@
|
|||||||
#undef stpcpy /* See mm/README.txt */
|
#undef stpcpy /* See mm/README.txt */
|
||||||
FAR char *stpcpy(FAR char *dest, FAR const char *src)
|
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');
|
while ((*dest++ = *src++) != '\0');
|
||||||
|
|
||||||
return --dest;
|
return --dest;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -28,6 +28,34 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <string.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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -59,6 +87,49 @@
|
|||||||
#undef stpncpy /* See mm/README.txt */
|
#undef stpncpy /* See mm/README.txt */
|
||||||
FAR char *stpncpy(FAR char *dest, FAR const char *src, size_t n)
|
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 *end = dest + n; /* End of dest buffer + 1 byte */
|
||||||
FAR char *ret; /* Value to be returned */
|
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;
|
return ret;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -30,6 +30,27 @@
|
|||||||
|
|
||||||
#include "libc.h"
|
#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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -38,6 +59,37 @@
|
|||||||
#undef strcat /* See mm/README.txt */
|
#undef strcat /* See mm/README.txt */
|
||||||
FAR char *strcat(FAR char *dest, FAR const char *src)
|
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;
|
FAR char *ret = dest;
|
||||||
|
|
||||||
dest += strlen(dest);
|
dest += strlen(dest);
|
||||||
@@ -47,6 +99,7 @@ FAR char *strcat(FAR char *dest, FAR const char *src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
*dest = '\0';
|
*dest = '\0';
|
||||||
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,32 @@
|
|||||||
|
|
||||||
#include "libc.h"
|
#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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -52,6 +78,92 @@
|
|||||||
#undef strchr /* See mm/README.txt */
|
#undef strchr /* See mm/README.txt */
|
||||||
FAR char *strchr(FAR const char *s, int c)
|
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++)
|
for (; ; s++)
|
||||||
{
|
{
|
||||||
if (*s == c)
|
if (*s == c)
|
||||||
@@ -64,6 +176,7 @@ FAR char *strchr(FAR const char *s, int c)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,11 @@
|
|||||||
#undef strchrnul /* See mm/README.txt */
|
#undef strchrnul /* See mm/README.txt */
|
||||||
FAR char *strchrnul(FAR const char *s, int c)
|
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)
|
if (s)
|
||||||
{
|
{
|
||||||
while (*s != '\0' && *s != c)
|
while (*s != '\0' && *s != c)
|
||||||
@@ -61,5 +66,6 @@ FAR char *strchrnul(FAR const char *s, int c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (FAR char *)s;
|
return (FAR char *)s;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -30,6 +30,28 @@
|
|||||||
|
|
||||||
#include "libc.h"
|
#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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -38,6 +60,49 @@
|
|||||||
#undef strcmp /* See mm/README.txt */
|
#undef strcmp /* See mm/README.txt */
|
||||||
int strcmp(FAR const char *cs, FAR const char *ct)
|
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;
|
register int result;
|
||||||
for (; ; )
|
for (; ; )
|
||||||
{
|
{
|
||||||
@@ -49,5 +114,6 @@ int strcmp(FAR const char *cs, FAR const char *ct)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#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);
|
return strcmp(a, b);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,28 @@
|
|||||||
|
|
||||||
#include "libc.h"
|
#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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -50,8 +72,39 @@
|
|||||||
#undef strcpy /* See mm/README.txt */
|
#undef strcpy /* See mm/README.txt */
|
||||||
FAR char *strcpy(FAR char *dest, FAR const char *src)
|
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;
|
FAR char *tmp = dest;
|
||||||
while ((*dest++ = *src++) != '\0');
|
while ((*dest++ = *src++) != '\0');
|
||||||
return tmp;
|
return tmp;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ FAR char *strdup(FAR const char *s)
|
|||||||
|
|
||||||
if (news)
|
if (news)
|
||||||
{
|
{
|
||||||
strlcpy(news, s, size);
|
memcpy(news, s, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return news;
|
return news;
|
||||||
|
|||||||
@@ -30,6 +30,27 @@
|
|||||||
|
|
||||||
#include "libc.h"
|
#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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -38,8 +59,47 @@
|
|||||||
#undef strlen /* See mm/README.txt */
|
#undef strlen /* See mm/README.txt */
|
||||||
size_t strlen(FAR const char *s)
|
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;
|
FAR const char *sc;
|
||||||
for (sc = s; *sc != '\0'; ++sc);
|
for (sc = s; *sc != '\0'; ++sc);
|
||||||
return sc - s;
|
return sc - s;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -30,6 +30,31 @@
|
|||||||
|
|
||||||
#include "libc.h"
|
#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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -38,6 +63,65 @@
|
|||||||
#undef strncmp /* See mm/README.txt */
|
#undef strncmp /* See mm/README.txt */
|
||||||
int strncmp(FAR const char *cs, FAR const char *ct, size_t nb)
|
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;
|
register int result = 0;
|
||||||
for (; nb > 0; nb--)
|
for (; nb > 0; nb--)
|
||||||
{
|
{
|
||||||
@@ -49,5 +133,6 @@ int strncmp(FAR const char *cs, FAR const char *ct, size_t nb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -30,6 +30,33 @@
|
|||||||
|
|
||||||
#include "libc.h"
|
#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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -59,6 +86,49 @@
|
|||||||
#undef strncpy /* See mm/README.txt */
|
#undef strncpy /* See mm/README.txt */
|
||||||
FAR char *strncpy(FAR char *dest, FAR const char *src, size_t n)
|
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 *ret = dest; /* Value to be returned */
|
||||||
FAR char *end = dest + n; /* End of dest buffer + 1 byte */
|
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;
|
return ret;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -42,6 +42,24 @@
|
|||||||
#undef strrchr /* See mm/README.txt */
|
#undef strrchr /* See mm/README.txt */
|
||||||
FAR char *strrchr(FAR const char *s, int c)
|
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;
|
FAR const char *r = NULL;
|
||||||
|
|
||||||
do
|
do
|
||||||
@@ -54,5 +72,6 @@ FAR char *strrchr(FAR const char *s, int c)
|
|||||||
while (*s++ != '\0');
|
while (*s++ != '\0');
|
||||||
|
|
||||||
return (FAR char *)r;
|
return (FAR char *)r;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user