Skip to content

Commit 6e87f11

Browse files
yangguangcai1xiaoxiang781216
authored andcommitted
Merge the newlibc string into NuttX.
Signed-off-by: yangguangcai <yangguangcai@xiaomi.com>
1 parent d802912 commit 6e87f11

21 files changed

+1128
-9
lines changed

LICENSE

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8664,3 +8664,34 @@ drivers/i3c/internals.h
86648664
Author: Boris Brezillon <boris.brezillon@bootlin.com>
86658665

86668666
SPDX-License-Identifier: Apache-2.0
8667+
8668+
libs/libc/string/lib_memccpy.c
8669+
libs/libc/string/lib_memchr.c
8670+
libs/libc/string/lib_memcmp.c
8671+
libs/libc/string/lib_memcpy.c
8672+
libs/libc/string/lib_memrchr.c
8673+
libs/libc/string/lib_stpcpy.c
8674+
libs/libc/string/lib_stpncpy.c
8675+
libs/libc/string/lib_strcat.c
8676+
libs/libc/string/lib_strchr.c
8677+
libs/libc/string/lib_strchrnul.c
8678+
libs/libc/string/lib_strcmp.c
8679+
libs/libc/string/lib_strcpy.c
8680+
libs/libc/string/lib_strlen.c
8681+
libs/libc/string/lib_strncmp.c
8682+
libs/libc/string/lib_strncpy.c
8683+
libs/libc/string/lib_strrchr.c
8684+
======================
8685+
8686+
Copyright (c) 1994-2009 Red Hat, Inc. All rights reserved.
8687+
8688+
This copyrighted material is made available to anyone wishing to use,
8689+
modify, copy, or redistribute it subject to the terms and conditions
8690+
of the BSD License. This program is distributed in the hope that
8691+
it will be useful, but WITHOUT ANY WARRANTY expressed or implied,
8692+
including the implied warranties of MERCHANTABILITY or FITNESS FOR
8693+
A PARTICULAR PURPOSE. A copy of this license is available at
8694+
http://www.opensource.org/licenses. Any Red Hat trademarks that are
8695+
incorporated in the source code or documentation are not subject to
8696+
the BSD License and may only be used or replicated with the express
8697+
permission of Red Hat, Inc.

libs/libc/string/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ config LIBC_STRERROR_ERRNUM
3636
for unknown errors like "Unknown error 101". Default enabled when
3737
LIBC_STRERROR is not selected.
3838

39+
config LIBC_STRING_OPTIMIZE
40+
bool "optimized string function"
41+
depends on ALLOW_BSD_COMPONENTS
42+
default y
43+
--help--
44+
Use optimized string function implementation based on newlib.
45+
3946
config LIBC_PERROR_STDOUT
4047
bool "perror() to stdout"
4148
default n

libs/libc/string/lib_memccpy.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,36 @@
2828
#include <sys/types.h>
2929
#include <string.h>
3030

31+
/****************************************************************************
32+
* Pre-processor Definitions
33+
****************************************************************************/
34+
35+
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
36+
/* Nonzero if either x or y is not aligned on a "long" boundary. */
37+
38+
#define UNALIGNED(x, y) \
39+
(((long)(uintptr_t)(x) & (sizeof(long) - 1)) | ((long)(uintptr_t)(y) & (sizeof(long) - 1)))
40+
41+
/* How many bytes are copied each iteration of the word copy loop. */
42+
43+
#define LITTLEBLOCKSIZE (sizeof(long))
44+
45+
/* Threshhold for punting to the byte copier. */
46+
47+
#define TOO_SMALL(len) ((len) < LITTLEBLOCKSIZE)
48+
49+
/* Macros for detecting endchar */
50+
51+
#if LONG_MAX == 2147483647
52+
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
53+
#elif LONG_MAX == 9223372036854775807
54+
/* Nonzero if x (a long int) contains a NULL byte. */
55+
56+
# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
57+
#endif
58+
59+
#endif
60+
3161
/****************************************************************************
3262
* Public Functions
3363
****************************************************************************/
@@ -51,6 +81,71 @@
5181
#undef memccpy /* See mm/README.txt */
5282
FAR void *memccpy(FAR void *s1, FAR const void *s2, int c, size_t n)
5383
{
84+
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
85+
FAR void *ptr = NULL;
86+
FAR unsigned char *pout = (FAR unsigned char *)s1;
87+
FAR const unsigned char *pin = (FAR const unsigned char *)s2;
88+
FAR long *paligned_out;
89+
FAR const long *paligned_in;
90+
unsigned char endchar = c & 0xff;
91+
92+
/* If the size is small, or either pin or pout is unaligned,
93+
* then punt into the byte copy loop. This should be rare.
94+
*/
95+
96+
if (!TOO_SMALL(n) && !UNALIGNED(pin, pout))
97+
{
98+
unsigned int i;
99+
unsigned long mask = 0;
100+
101+
paligned_out = (FAR long *)pout;
102+
paligned_in = (FAR long *)pin;
103+
104+
/* The fast code reads the ASCII one word at a time and only
105+
* performs the bytewise search on word-sized segments if they
106+
* contain the search character, which is detected by XORing
107+
* the word-sized segment with a word-sized block of the search
108+
* character and then detecting for the presence of NULL in the
109+
* result.
110+
*/
111+
112+
for (i = 0; i < LITTLEBLOCKSIZE; i++)
113+
{
114+
mask = (mask << 8) + endchar;
115+
}
116+
117+
/* Copy one long word at a time if possible. */
118+
119+
while (n >= LITTLEBLOCKSIZE)
120+
{
121+
unsigned long buffer = (unsigned long)(*paligned_in);
122+
buffer ^= mask;
123+
if (DETECTNULL(buffer))
124+
{
125+
break; /* endchar is found, go byte by byte from here */
126+
}
127+
128+
*paligned_out++ = *paligned_in++;
129+
n -= LITTLEBLOCKSIZE;
130+
}
131+
132+
/* Pick up any residual with a byte copier. */
133+
134+
pout = (FAR unsigned char *)paligned_out;
135+
pin = (FAR unsigned char *)paligned_in;
136+
}
137+
138+
while (n--)
139+
{
140+
if ((*pout++ = *pin++) == endchar)
141+
{
142+
ptr = pout;
143+
break;
144+
}
145+
}
146+
147+
return ptr;
148+
#else
54149
FAR unsigned char *pout = (FAR unsigned char *)s1;
55150
FAR unsigned char *pin = (FAR unsigned char *)s2;
56151

@@ -75,4 +170,5 @@ FAR void *memccpy(FAR void *s1, FAR const void *s2, int c, size_t n)
75170
/* C was not found in the first n bytes of s2 */
76171

77172
return NULL;
173+
#endif
78174
}

libs/libc/string/lib_memchr.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,38 @@
3030

3131
#include "libc.h"
3232

33+
/****************************************************************************
34+
* Pre-processor Definitions
35+
****************************************************************************/
36+
37+
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
38+
39+
#define UNALIGNED(x) ((long)(uintptr_t)(x) & (sizeof(long) - 1))
40+
41+
/* How many bytes are loaded each iteration of the word copy loop. */
42+
43+
#define LBLOCKSIZE (sizeof(long))
44+
45+
/* Threshhold for punting to the bytewise iterator. */
46+
47+
#define TOO_SMALL(len) ((len) < LBLOCKSIZE)
48+
49+
#if LONG_MAX == 2147483647
50+
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
51+
#elif LONG_MAX == 9223372036854775807
52+
/* Nonzero if x (a long int) contains a NULL byte. */
53+
54+
# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
55+
#endif
56+
57+
/* DETECTCHAR returns nonzero if (long)x contains the byte used
58+
* to fill (long)mask.
59+
*/
60+
61+
#define DETECTCHAR(x, mask) (DETECTNULL((x) ^ (mask)))
62+
63+
#endif
64+
3365
/****************************************************************************
3466
* Public Functions
3567
****************************************************************************/
@@ -52,6 +84,76 @@
5284
#undef memchr /* See mm/README.txt */
5385
FAR void *memchr(FAR const void *s, int c, size_t n)
5486
{
87+
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
88+
FAR const unsigned char *p = (FAR const unsigned char *)s;
89+
FAR unsigned long *asrc;
90+
unsigned char d = c;
91+
unsigned long mask;
92+
unsigned int i;
93+
94+
while (UNALIGNED(p))
95+
{
96+
if (!n--)
97+
{
98+
return NULL;
99+
}
100+
101+
if (*p == d)
102+
{
103+
return (FAR void *)p;
104+
}
105+
106+
p++;
107+
}
108+
109+
if (!TOO_SMALL(n))
110+
{
111+
/* If we get this far, we know that n is large and p is
112+
* word-aligned.
113+
* The fast code reads the source one word at a time and only
114+
* performs the bytewise search on word-sized segments if they
115+
* contain the search character, which is detected by XORing
116+
* the word-sized segment with a word-sized block of the search
117+
* character and then detecting for the presence of NUL in the
118+
* result.
119+
*/
120+
121+
asrc = (FAR unsigned long *)p;
122+
mask = d << 8 | d;
123+
mask = mask << 16 | mask;
124+
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
125+
{
126+
mask = (mask << i) | mask;
127+
}
128+
129+
while (n >= LBLOCKSIZE)
130+
{
131+
if (DETECTCHAR(*asrc, mask))
132+
{
133+
break;
134+
}
135+
136+
n -= LBLOCKSIZE;
137+
asrc++;
138+
}
139+
140+
/* If there are fewer than LBLOCKSIZE characters left,
141+
* then we resort to the bytewise loop.
142+
*/
143+
144+
p = (FAR unsigned char *)asrc;
145+
}
146+
147+
while (n--)
148+
{
149+
if (*p == d)
150+
{
151+
return (FAR void *)p;
152+
}
153+
154+
p++;
155+
}
156+
#else
55157
FAR const unsigned char *p = (FAR const unsigned char *)s;
56158

57159
while (n--)
@@ -63,6 +165,7 @@ FAR void *memchr(FAR const void *s, int c, size_t n)
63165

64166
p++;
65167
}
168+
#endif
66169

67170
return NULL;
68171
}

libs/libc/string/lib_memcmp.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,26 @@
3030

3131
#include "libc.h"
3232

33+
/****************************************************************************
34+
* Pre-processor Definitions
35+
****************************************************************************/
36+
37+
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
38+
/* Nonzero if either x or y is not aligned on a "long" boundary. */
39+
40+
#define UNALIGNED(x, y) \
41+
(((long)(uintptr_t)(x) & (sizeof(long) - 1)) | ((long)(uintptr_t)(y) & (sizeof(long) - 1)))
42+
43+
/* How many bytes are copied each iteration of the word copy loop. */
44+
45+
#define LBLOCKSIZE (sizeof(long))
46+
47+
/* Threshhold for punting to the byte copier. */
48+
49+
#define TOO_SMALL(len) ((len) < LBLOCKSIZE)
50+
51+
#endif
52+
3353
/****************************************************************************
3454
* Public Functions
3555
****************************************************************************/
@@ -39,6 +59,54 @@
3959
no_builtin("memcmp")
4060
int memcmp(FAR const void *s1, FAR const void *s2, size_t n)
4161
{
62+
#ifdef CONFIG_LIBC_STRING_OPTIMIZE
63+
FAR unsigned char *p1 = (FAR unsigned char *)s1;
64+
FAR unsigned char *p2 = (FAR unsigned char *)s2;
65+
FAR unsigned long *a1;
66+
FAR unsigned long *a2;
67+
68+
/* If the size is too small, or either pointer is unaligned,
69+
* then we punt to the byte compare loop. Hopefully this will
70+
* not turn up in inner loops.
71+
*/
72+
73+
if (!TOO_SMALL(n) && !UNALIGNED(p1, p2))
74+
{
75+
/* Otherwise, load and compare the blocks of memory one
76+
* word at a time.
77+
*/
78+
79+
a1 = (FAR unsigned long *)p1;
80+
a2 = (FAR unsigned long *)p2;
81+
while (n >= LBLOCKSIZE)
82+
{
83+
if (*a1 != *a2)
84+
{
85+
break;
86+
}
87+
88+
a1++;
89+
a2++;
90+
n -= LBLOCKSIZE;
91+
}
92+
93+
/* check s mod LBLOCKSIZE remaining characters */
94+
95+
p1 = (FAR unsigned char *)a1;
96+
p2 = (FAR unsigned char *)a2;
97+
}
98+
99+
while (n--)
100+
{
101+
if (*p1 != *p2)
102+
{
103+
return *p1 - *p2;
104+
}
105+
106+
p1++;
107+
p2++;
108+
}
109+
#else
42110
FAR unsigned char *p1 = (FAR unsigned char *)s1;
43111
FAR unsigned char *p2 = (FAR unsigned char *)s2;
44112

@@ -56,6 +124,7 @@ int memcmp(FAR const void *s1, FAR const void *s2, size_t n)
56124
p1++;
57125
p2++;
58126
}
127+
#endif
59128

60129
return 0;
61130
}

0 commit comments

Comments
 (0)