public inbox for newlib@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] newlib: libc: Optimize the string functions
@ 2022-08-12 21:09 Seija Kijin
  0 siblings, 0 replies; 4+ messages in thread
From: Seija Kijin @ 2022-08-12 21:09 UTC (permalink / raw)
  To: newlib

From 8a20796312219dbf625d27fd256c8c78d1f7f015 Mon Sep 17 00:00:00 2001

The code is well written, however, there is some room for improvement
in terms of performance. This is an attempt to make the string
functions more consistent and performant.

Most of the changes were simple refactorings, with some code changed
to better match that of other files in the same directory.

Pointers to unsigned variables in memory sometimes cause some older
compilers to generate better code than if they were signed, hence
those changes as well.
---
newlib/libc/machine/microblaze/strcmp.c | 2 +-
newlib/libc/machine/microblaze/strcpy.c | 2 +-
newlib/libc/string/memccpy.c | 49 ++++++++++++-----------
newlib/libc/string/memchr.c | 9 +++--
newlib/libc/string/memcmp.c | 32 +++++++--------
newlib/libc/string/memcpy.c | 34 +++++++---------
newlib/libc/string/memmem.c | 18 ++++-----
newlib/libc/string/memmove.c | 34 ++++++++--------
newlib/libc/string/mempcpy.c | 30 +++++++-------
newlib/libc/string/memrchr.c | 17 ++++----
newlib/libc/string/memset.c | 19 +++++----
newlib/libc/string/rawmemchr.c | 19 ++++-----
newlib/libc/string/stpcpy.c | 12 +++---
newlib/libc/string/stpncpy.c | 13 ++++---
newlib/libc/string/strcasestr.c | 30 +++++++-------
newlib/libc/string/strcat.c | 6 +--
newlib/libc/string/strchr.c | 20 +++++-----
newlib/libc/string/strcmp.c | 18 ++++-----
newlib/libc/string/strcpy.c | 16 ++++----
newlib/libc/string/strcspn.c | 9 ++---
newlib/libc/string/strlen.c | 8 ++--
newlib/libc/string/strncmp.c | 28 ++++++-------
newlib/libc/string/strncpy.c | 10 ++---
newlib/libc/string/strnlen.c | 2 +-
newlib/libc/string/strnstr.c | 2 +-
newlib/libc/string/strrchr.c | 7 ++--
newlib/libc/string/strspn.c | 5 +--
newlib/libc/string/strstr.c | 52 ++++++++++++-------------
newlib/libc/string/strxfrm.c | 12 +++---
newlib/libc/string/swab.c | 8 ++--
30 files changed, 254 insertions(+), 269 deletions(-)

diff --git a/newlib/libc/machine/microblaze/strcmp.c
b/newlib/libc/machine/microblaze/strcmp.c
index 434195e2c..050437149 100644
--- a/newlib/libc/machine/microblaze/strcmp.c
+++ b/newlib/libc/machine/microblaze/strcmp.c
@@ -63,7 +63,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* DETECTNULL returns nonzero if (long)X contains a NULL byte. */
#if LONG_MAX == 2147483647L
diff --git a/newlib/libc/machine/microblaze/strcpy.c
b/newlib/libc/machine/microblaze/strcpy.c
index 62072fa28..b4e45e6a2 100644
--- a/newlib/libc/machine/microblaze/strcpy.c
+++ b/newlib/libc/machine/microblaze/strcpy.c
@@ -63,7 +63,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
diff --git a/newlib/libc/string/memccpy.c b/newlib/libc/string/memccpy.c
index 1f5f55c50..6e352f57e 100644
--- a/newlib/libc/string/memccpy.c
+++ b/newlib/libc/string/memccpy.c
@@ -34,16 +34,17 @@ PORTABILITY
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the word copy loop. */
-#define LITTLEBLOCKSIZE (sizeof (long))
+#define LITTLEBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the byte copier. */
#define TOO_SMALL(LEN) ((LEN) < LITTLEBLOCKSIZE)
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647L
+#define MAGIC
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
#else
#if LONG_MAX == 9223372036854775807L
@@ -64,11 +65,11 @@ memccpy (void *__restrict dst0,
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
void *ptr = NULL;
- char *dst = (char *) dst0;
- char *src = (char *) src0;
- char endchar = endchar0 & 0xff;
+ unsigned char *dst = (unsigned char *) dst0;
+ const unsigned char *src = (const unsigned char *) src0;
+ const unsigned char endchar = (unsigned char) endchar0;
- while (len0--)
+ for (; len0; len0--)
{
if ((*dst++ = *src++) == endchar)
{
@@ -80,21 +81,21 @@ memccpy (void *__restrict dst0,
return ptr;
#else
void *ptr = NULL;
- char *dst = dst0;
- const char *src = src0;
- long *aligned_dst;
- const long *aligned_src;
- char endchar = endchar0 & 0xff;
+ unsigned char *dst = (unsigned char *) dst0;
+ const unsigned char *src = (const unsigned char *) src0;
+ unsigned long *aligned_dst;
+ const unsigned long *aligned_src;
+ const unsigned char endchar = (unsigned char) endchar0;
/* If the size is small, or either SRC or DST is unaligned,
then punt into the byte copy loop. This should be rare. */
if (!TOO_SMALL(len0) && !UNALIGNED (src, dst))
{
unsigned int i;
- unsigned long mask = 0;
+ unsigned long mask;
- aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_dst = (unsigned long*)dst;
+ aligned_src = (const unsigned long*)src;
/* The fast code reads the ASCII one word at a time and only
performs the bytewise search on word-sized segments if they
@@ -102,27 +103,29 @@ memccpy (void *__restrict dst0,
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;
+
+ mask = endchar << 8 | endchar;
+ mask = mask << 16 | mask;
+ for (i = 32; i < LITTLEBLOCKSIZE * 8; i <<= 1)
+ mask = (mask << i) | mask;
/* Copy one long word at a time if possible. */
- while (len0 >= LITTLEBLOCKSIZE)
+ do
{
- unsigned long buffer = (unsigned long)(*aligned_src);
- buffer ^= mask;
+ unsigned long buffer = *aligned_src ^ mask;
if (DETECTNULL (buffer))
break; /* endchar is found, go byte by byte from here */
*aligned_dst++ = *aligned_src++;
len0 -= LITTLEBLOCKSIZE;
- }
+ } while (len0 >= LITTLEBLOCKSIZE);
/* Pick up any residual with a byte copier. */
- dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ dst = (unsigned char*)aligned_dst;
+ src = (const unsigned char*)aligned_src;
}
- while (len0--)
+ for (; len0; len0--)
{
if ((*dst++ = *src++) == endchar)
{
diff --git a/newlib/libc/string/memchr.c b/newlib/libc/string/memchr.c
index 21bc4d879..614af2bfc 100644
--- a/newlib/libc/string/memchr.c
+++ b/newlib/libc/string/memchr.c
@@ -37,7 +37,7 @@ QUICKREF
#define UNALIGNED(X) ((long)X & (sizeof (long) - 1))
/* How many bytes are loaded each iteration of the word copy loop. */
-#define LBLOCKSIZE (sizeof (long))
+#define LBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the bytewise iterator. */
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
@@ -67,7 +67,7 @@ memchr (const void *src_void,
size_t length)
{
const unsigned char *src = (const unsigned char *) src_void;
- unsigned char d = c;
+ const unsigned char d = (unsigned char) c;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
unsigned long *asrc;
@@ -76,11 +76,12 @@ memchr (const void *src_void,
while (UNALIGNED (src))
{
- if (!length--)
+ if (!length)
return NULL;
if (*src == d)
return (void *) src;
src++;
+ length--;
}
if (!TOO_SMALL (length))
@@ -93,7 +94,7 @@ memchr (const void *src_void,
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 = (unsigned long *) src;
+ asrc = (const unsigned long *) src;
mask = d << 8 | d;
mask = mask << 16 | mask;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
diff --git a/newlib/libc/string/memcmp.c b/newlib/libc/string/memcmp.c
index 342fb9fbc..4f186777d 100644
--- a/newlib/libc/string/memcmp.c
+++ b/newlib/libc/string/memcmp.c
@@ -34,10 +34,10 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the word copy loop. */
-#define LBLOCKSIZE (sizeof (long))
+#define LBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the byte copier. */
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
@@ -48,22 +48,20 @@ memcmp (const void *m1,
size_t n)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- unsigned char *s1 = (unsigned char *) m1;
- unsigned char *s2 = (unsigned char *) m2;
+ const unsigned char *s1 = (const unsigned char *) m1;
+ const unsigned char *s2 = (const unsigned char *) m2;
- while (n--)
+ for (; n; n--)
{
if (*s1 != *s2)
- {
return *s1 - *s2;
- }
s1++;
s2++;
}
return 0;
#else
- unsigned char *s1 = (unsigned char *) m1;
- unsigned char *s2 = (unsigned char *) m2;
+ const unsigned char *s1 = (const unsigned char *) m1;
+ const unsigned char *s2 = (const unsigned char *) m2;
unsigned long *a1;
unsigned long *a2;
@@ -74,24 +72,24 @@ memcmp (const void *m1,
{
/* Otherwise, load and compare the blocks of memory one
word at a time. */
- a1 = (unsigned long*) s1;
- a2 = (unsigned long*) s2;
- while (n >= LBLOCKSIZE)
+ a1 = (const unsigned long*) s1;
+ a2 = (const unsigned long*) s2;
+ while (*a1 == *a2)
{
- if (*a1 != *a2)
- break;
a1++;
a2++;
n -= LBLOCKSIZE;
+ if (TOO_SMALL(n))
+ break;
}
/* check m mod LBLOCKSIZE remaining characters */
- s1 = (unsigned char*)a1;
- s2 = (unsigned char*)a2;
+ s1 = (const unsigned char*)a1;
+ s2 = (const unsigned char*)a2;
}
- while (n--)
+ for (; n; n--)
{
if (*s1 != *s2)
return *s1 - *s2;
diff --git a/newlib/libc/string/memcpy.c b/newlib/libc/string/memcpy.c
index 52f716b92..96cacd99e 100644
--- a/newlib/libc/string/memcpy.c
+++ b/newlib/libc/string/memcpy.c
@@ -33,7 +33,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the 4X unrolled loop. */
#define BIGBLOCKSIZE (sizeof (long) << 2)
@@ -51,29 +51,25 @@ memcpy (void *__restrict dst0,
size_t len0)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- char *dst = (char *) dst0;
- char *src = (char *) src0;
+ unsigned char *dst = (unsigned char *) dst0;
+ const unsigned char *src = (const unsigned char *) src0;
- void *save = dst0;
-
- while (len0--)
- {
+ for (; len0; len0--)
*dst++ = *src++;
- }
- return save;
+ return dst0;
#else
- char *dst = dst0;
- const char *src = src0;
- long *aligned_dst;
- const long *aligned_src;
+ unsigned char *dst = dst0;
+ const unsigned char *src = src0;
+ unsigned long *aligned_dst;
+ const unsigned long *aligned_src;
/* If the size is small, or either SRC or DST is unaligned,
then punt into the byte copy loop. This should be rare. */
if (!TOO_SMALL(len0) && !UNALIGNED (src, dst))
{
- aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_dst = (unsigned long*)dst;
+ aligned_src = (const unsigned long*)src;
/* Copy 4X long words at a time if possible. */
while (len0 >= BIGBLOCKSIZE)
@@ -93,12 +89,12 @@ memcpy (void *__restrict dst0,
}
/* Pick up any residual with a byte copier. */
- dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ dst = (unsigned char*)aligned_dst;
+ src = (const unsigned char*)aligned_src;
}
- while (len0--)
- *dst++ = *src++;
+ for (; len0; len0--)
+ *dst++ = *src++;
return dst0;
#endif /* not PREFER_SIZE_OVER_SPEED */
diff --git a/newlib/libc/string/memmem.c b/newlib/libc/string/memmem.c
index 65267b9c5..c074a295c 100644
--- a/newlib/libc/string/memmem.c
+++ b/newlib/libc/string/memmem.c
@@ -68,14 +68,14 @@ QUICKREF
void *
memmem (const void *haystack, size_t hs_len, const void *needle, size_t ne_len)
{
- const char *hs = haystack;
- const char *ne = needle;
+ const unsigned char *hs = haystack;
+ const unsigned char *ne = needle;
if (ne_len == 0)
return (void *)hs;
- int i;
- int c = ne[0];
- const char *end = hs + hs_len - ne_len;
+ size_t i;
+ const unsigned char c = ne[0];
+ const unsigned char *end = hs + hs_len - ne_len;
for ( ; hs <= end; hs++)
{
@@ -143,7 +143,7 @@ memmem (const void *haystack, size_t hs_len, const
void *needle, size_t ne_len)
size_t tmp, shift1;
size_t m1 = ne_len - 1;
size_t offset = 0;
- int i;
+ size_t i;
/* Initialize bad character shift hash table. */
memset (shift, 0, sizeof (shift));
@@ -152,7 +152,7 @@ memmem (const void *haystack, size_t hs_len, const
void *needle, size_t ne_len)
shift1 = m1 - shift[hash2 (ne + m1)];
shift[hash2 (ne + m1)] = m1;
- for ( ; hs <= end; )
+ while (hs <= end)
{
/* Skip past character pairs not in the needle. */
do
@@ -170,13 +170,13 @@ memmem (const void *haystack, size_t hs_len,
const void *needle, size_t ne_len)
/* The last 2 characters match. If the needle is long, check a
fixed number of characters first to quickly filter out mismatches. */
- if (m1 <= 15 || memcmp (hs + offset, ne + offset, sizeof (long)) == 0)
+ if (m1 <= 15 || memcmp (hs + offset, ne + offset, sizeof (unsigned
long)) == 0)
{
if (memcmp (hs, ne, m1) == 0)
return (void *) hs;
/* Adjust filter offset when it doesn't find the mismatch. */
- offset = (offset >= sizeof (long) ? offset : m1) - sizeof (long);
+ offset = (offset >= sizeof (unsigned long) ? offset : m1) - sizeof
(unsigned long);
}
/* Skip based on matching the last 2 characters. */
diff --git a/newlib/libc/string/memmove.c b/newlib/libc/string/memmove.c
index da5dfdbdd..17334c37a 100644
--- a/newlib/libc/string/memmove.c
+++ b/newlib/libc/string/memmove.c
@@ -36,7 +36,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the 4X unrolled loop. */
#define BIGBLOCKSIZE (sizeof (long) << 2)
@@ -55,22 +55,22 @@ memmove (void *dst_void,
size_t length)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- char *dst = dst_void;
- const char *src = src_void;
+ unsigned char *dst = dst_void;
+ const unsigned char *src = src_void;
- if (src < dst && dst < src + length)
+ if (dst - src < length) /* Unsigned compare means underflow is
accounted for */
{
/* Have to copy backwards */
src += length;
dst += length;
- while (length--)
+ for (; length; length--)
{
*--dst = *--src;
}
}
else
{
- while (length--)
+ for (; length; length--)
{
*dst++ = *src++;
}
@@ -78,17 +78,17 @@ memmove (void *dst_void,
return dst_void;
#else
- char *dst = dst_void;
- const char *src = src_void;
- long *aligned_dst;
- const long *aligned_src;
+ unsigned char *dst = dst_void;
+ const unsigned char *src = src_void;
+ unsigned long *aligned_dst;
+ const unsigned long *aligned_src;
- if (src < dst && dst < src + length)
+ if (dst - src < length) /* Unsigned compare means underflow is
accounted for */
{
/* Destructive overlap...have to copy backwards */
src += length;
dst += length;
- while (length--)
+ for (; length; --length)
{
*--dst = *--src;
}
@@ -100,8 +100,8 @@ memmove (void *dst_void,
then punt into the byte copy loop. This should be rare. */
if (!TOO_SMALL(length) && !UNALIGNED (src, dst))
{
- aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_dst = (unsigned long*)dst;
+ aligned_src = (const unsigned long*)src;
/* Copy 4X long words at a time if possible. */
while (length >= BIGBLOCKSIZE)
@@ -121,11 +121,11 @@ memmove (void *dst_void,
}
/* Pick up any residual with a byte copier. */
- dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ dst = (unsigned char*)aligned_dst;
+ src = (const unsigned char*)aligned_src;
}
- while (length--)
+ for (; length; length--)
{
*dst++ = *src++;
}
diff --git a/newlib/libc/string/mempcpy.c b/newlib/libc/string/mempcpy.c
index 129165603..b13af2dc5 100644
--- a/newlib/libc/string/mempcpy.c
+++ b/newlib/libc/string/mempcpy.c
@@ -31,7 +31,7 @@ PORTABILITY
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the 4X unrolled loop. */
#define BIGBLOCKSIZE (sizeof (long) << 2)
@@ -48,27 +48,25 @@ mempcpy (void *dst0,
size_t len0)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- char *dst = (char *) dst0;
- char *src = (char *) src0;
+ unsigned char *dst = (unsigned char *) dst0;
+ const unsigned char *src = (const unsigned char *) src0;
- while (len0--)
- {
+ for (; len0; len0--)
*dst++ = *src++;
- }
return dst;
#else
- char *dst = dst0;
- const char *src = src0;
- long *aligned_dst;
- const long *aligned_src;
+ unsigned char *dst = dst0;
+ const unsigned char *src = src0;
+ unsigned long *aligned_dst;
+ const unsigned long *aligned_src;
/* If the size is small, or either SRC or DST is unaligned,
then punt into the byte copy loop. This should be rare. */
if (!TOO_SMALL(len0) && !UNALIGNED (src, dst))
{
- aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_dst = (unsigned long*)dst;
+ aligned_src = (const unsigned long*)src;
/* Copy 4X long words at a time if possible. */
while (len0 >= BIGBLOCKSIZE)
@@ -88,12 +86,12 @@ mempcpy (void *dst0,
}
/* Pick up any residual with a byte copier. */
- dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ dst = (unsigned char*)aligned_dst;
+ src = (const unsigned char*)aligned_src;
}
- while (len0--)
- *dst++ = *src++;
+ for (; len0; len0--)
+ *dst++ = *src++;
return dst;
#endif /* not PREFER_SIZE_OVER_SPEED */
diff --git a/newlib/libc/string/memrchr.c b/newlib/libc/string/memrchr.c
index 652efb359..b5aa1e0d2 100644
--- a/newlib/libc/string/memrchr.c
+++ b/newlib/libc/string/memrchr.c
@@ -37,7 +37,7 @@ QUICKREF
#define UNALIGNED(X) ((long)(X + 1) & (sizeof (long) - 1))
/* How many bytes are loaded each iteration of the word copy loop. */
-#define LBLOCKSIZE (sizeof (long))
+#define LBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the bytewise iterator. */
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
@@ -67,7 +67,7 @@ memrchr (const void *src_void,
size_t length)
{
const unsigned char *src = (const unsigned char *) src_void + length - 1;
- unsigned char d = c;
+ const unsigned char d = (unsigned char) c;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
unsigned long *asrc;
@@ -76,10 +76,11 @@ memrchr (const void *src_void,
while (UNALIGNED (src))
{
- if (!length--)
+ if (!length)
return NULL;
if (*src == d)
return (void *) src;
+ length--;
src--;
}
@@ -93,15 +94,15 @@ memrchr (const void *src_void,
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 = (unsigned long *) (src - LBLOCKSIZE + 1);
+ asrc = (const unsigned long *) (src - LBLOCKSIZE + 1);
mask = d << 8 | d;
mask = mask << 16 | mask;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
mask = (mask << i) | mask;
- while (length >= LBLOCKSIZE)
+ while (!DETECTCHAR (*asrc, mask))
{
- if (DETECTCHAR (*asrc, mask))
+ if (TOO_SMALL (length))
break;
length -= LBLOCKSIZE;
asrc--;
@@ -110,12 +111,12 @@ memrchr (const void *src_void,
/* If there are fewer than LBLOCKSIZE characters left,
then we resort to the bytewise loop. */
- src = (unsigned char *) asrc + LBLOCKSIZE - 1;
+ src = (const unsigned char *) asrc + LBLOCKSIZE - 1;
}
#endif /* not PREFER_SIZE_OVER_SPEED */
- while (length--)
+ for (; length; length--)
{
if (*src == d)
return (void *) src;
diff --git a/newlib/libc/string/memset.c b/newlib/libc/string/memset.c
index e8e667a24..0c8f8012a 100644
--- a/newlib/libc/string/memset.c
+++ b/newlib/libc/string/memset.c
@@ -39,21 +39,20 @@ memset (void *m,
int c,
size_t n)
{
- char *s = (char *) m;
+ unsigned char *s = (unsigned char *) m;
+ const unsigned char d = (unsigned char) c;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
unsigned int i;
unsigned long buffer;
unsigned long *aligned_addr;
- unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an
- unsigned variable. */
while (UNALIGNED (s))
{
- if (n--)
- *s++ = (char) c;
- else
+ if (!n)
return m;
+ *s++ = d;
+ n--;
}
if (!TOO_SMALL (n))
@@ -64,7 +63,7 @@ memset (void *m,
/* Store D into each char sized location in BUFFER so that
we can set large blocks quickly. */
buffer = (d << 8) | d;
- buffer |= (buffer << 16);
+ buffer = (buffer << 16) | buffer;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
buffer = (buffer << i) | buffer;
@@ -84,13 +83,13 @@ memset (void *m,
n -= LBLOCKSIZE;
}
/* Pick up the remainder with a bytewise loop. */
- s = (char*)aligned_addr;
+ s = (unsigned char*)aligned_addr;
}
#endif /* not PREFER_SIZE_OVER_SPEED */
- while (n--)
- *s++ = (char) c;
+ for (; n; n--)
+ *s++ = d;
return m;
}
diff --git a/newlib/libc/string/rawmemchr.c b/newlib/libc/string/rawmemchr.c
index 56e2b5e2d..3ab95bb28 100644
--- a/newlib/libc/string/rawmemchr.c
+++ b/newlib/libc/string/rawmemchr.c
@@ -36,7 +36,7 @@ QUICKREF
#define UNALIGNED(X) ((long)X & (sizeof (long) - 1))
/* How many bytes are loaded each iteration of the word copy loop. */
-#define LBLOCKSIZE (sizeof (long))
+#define LBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the bytewise iterator. */
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
@@ -65,10 +65,10 @@ rawmemchr (const void *src_void,
int c)
{
const unsigned char *src = (const unsigned char *) src_void;
- unsigned char d = c;
+ const unsigned char d = (unsigned char) c;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
- unsigned long *asrc;
+ const unsigned long *asrc;
unsigned long mask;
unsigned int i;
@@ -86,29 +86,26 @@ rawmemchr (const void *src_void,
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 = (unsigned long *) src;
+ asrc = (const unsigned long *) src;
mask = d << 8 | d;
mask = mask << 16 | mask;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
mask = (mask << i) | mask;
- while (1)
+ while (!DETECTCHAR (*asrc, mask))
{
- if (DETECTCHAR (*asrc, mask))
- break;
asrc++;
}
/* We have the matching word, now we resort to a bytewise loop. */
- src = (unsigned char *) asrc;
+ src = (const unsigned char *) asrc;
#endif /* !PREFER_SIZE_OVER_SPEED && !__OPTIMIZE_SIZE__ */
- while (1)
+ while (*src != d)
{
- if (*src == d)
- return (void *) src;
src++;
}
+ return (void *) src;
}
diff --git a/newlib/libc/string/stpcpy.c b/newlib/libc/string/stpcpy.c
index 4e2ae9fe0..bbd96ab98 100644
--- a/newlib/libc/string/stpcpy.c
+++ b/newlib/libc/string/stpcpy.c
@@ -35,7 +35,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
@@ -64,7 +64,7 @@ stpcpy (char *__restrict dst,
if (!UNALIGNED (src, dst))
{
aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_src = (const long*)src;
/* SRC and DEST are both "long int" aligned, try to do "long int"
sized copies. */
@@ -74,11 +74,11 @@ stpcpy (char *__restrict dst,
}
dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ src = (const char*)aligned_src;
}
#endif /* not PREFER_SIZE_OVER_SPEED */
- while ((*dst++ = *src++))
- ;
- return --dst;
+ while ((*dst = *src))
+ dst++, src++;
+ return dst;
}
diff --git a/newlib/libc/string/stpncpy.c b/newlib/libc/string/stpncpy.c
index 87fe268cf..6ca186e95 100644
--- a/newlib/libc/string/stpncpy.c
+++ b/newlib/libc/string/stpncpy.c
@@ -41,7 +41,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
@@ -75,7 +75,7 @@ stpncpy (char *__restrict dst,
if (!UNALIGNED (src, dst) && !TOO_SMALL (count))
{
aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_src = (const long*)src;
/* SRC and DEST are both "long int" aligned, try to do "long int"
sized copies. */
@@ -86,21 +86,22 @@ stpncpy (char *__restrict dst,
}
dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ src = (const char*)aligned_src;
}
#endif /* not PREFER_SIZE_OVER_SPEED */
while (count > 0)
{
--count;
- if ((*dst++ = *src++) == '\0')
+ if ((*dst = *src) == '\0')
{
- ret = dst - 1;
+ ret = dst;
break;
}
+ dst++, src++;
}
- while (count-- > 0)
+ for (; count > 0; count--)
*dst++ = '\0';
return ret ? ret : dst;
diff --git a/newlib/libc/string/strcasestr.c b/newlib/libc/string/strcasestr.c
index 36e183986..db6b07cb9 100644
--- a/newlib/libc/string/strcasestr.c
+++ b/newlib/libc/string/strcasestr.c
@@ -99,15 +99,13 @@ strcasestr (const char *s,
char c, sc;
size_t len;
- if ((c = *find++) != 0) {
- c = tolower((unsigned char)c);
+ if ((c = *find++) != '\0') {
+ c = tolower(c & 0xff);
len = strlen(find);
do {
- do {
- if ((sc = *s++) == 0)
- return (NULL);
- } while ((char)tolower((unsigned char)sc) != c);
- } while (strncasecmp(s, find, len) != 0);
+ if ((sc = *s++) == '\0')
+ return (NULL);
+ } while (((char)tolower(sc & 0xff) != c) && strncasecmp(s, find, len) != 0);
s--;
}
return ((char *)s);
@@ -115,8 +113,8 @@ strcasestr (const char *s,
#else /* compilation for speed */
/* Larger code size, but guaranteed linear performance. */
- const char *haystack = s;
- const char *needle = find;
+ const unsigned char *haystack = (const unsigned char *)s;
+ const unsigned char *needle = (const unsigned char *)find;
size_t needle_len; /* Length of NEEDLE. */
size_t haystack_len; /* Known minimum length of HAYSTACK. */
int ok = 1; /* True if NEEDLE is prefix of HAYSTACK. */
@@ -125,22 +123,20 @@ strcasestr (const char *s,
HAYSTACK is at least as long (no point processing all of a long
NEEDLE if HAYSTACK is too short). */
while (*haystack && *needle)
- ok &= (tolower ((unsigned char) *haystack++)
- == tolower ((unsigned char) *needle++));
+ ok &= (tolower (*haystack++)
+ == tolower (*needle++));
if (*needle)
return NULL;
if (ok)
return (char *) s;
needle_len = needle - find;
- haystack = s + 1;
+ needle = (const unsigned char *)find;
+ haystack = (const unsigned char *)s + 1;
haystack_len = needle_len - 1;
/* Perform the search. */
if (needle_len < LONG_NEEDLE_THRESHOLD)
- return two_way_short_needle ((const unsigned char *) haystack,
- haystack_len,
- (const unsigned char *) find, needle_len);
- return two_way_long_needle ((const unsigned char *) haystack, haystack_len,
- (const unsigned char *) find, needle_len);
+ return two_way_short_needle (haystack, haystack_len, needle, needle_len);
+ return two_way_long_needle (haystack, haystack_len, needle, needle_len);
#endif /* compilation for speed */
}
diff --git a/newlib/libc/string/strcat.c b/newlib/libc/string/strcat.c
index 92313c492..ce5183c9b 100644
--- a/newlib/libc/string/strcat.c
+++ b/newlib/libc/string/strcat.c
@@ -63,8 +63,8 @@ strcat (char *__restrict s1,
while (*s1)
s1++;
- while (*s1++ = *s2++)
- ;
+ while (*s1 = *s2)
+ s1++, s2++;
return s;
#else
char *s = s1;
@@ -73,7 +73,7 @@ strcat (char *__restrict s1,
/* Skip over the data in s1 as quickly as possible. */
if (ALIGNED (s1))
{
- unsigned long *aligned_s1 = (unsigned long *)s1;
+ long *aligned_s1 = (long *)s1;
while (!DETECTNULL (*aligned_s1))
aligned_s1++;
diff --git a/newlib/libc/string/strchr.c b/newlib/libc/string/strchr.c
index 96f30be04..3bf44c43c 100644
--- a/newlib/libc/string/strchr.c
+++ b/newlib/libc/string/strchr.c
@@ -55,12 +55,12 @@ char *
strchr (const char *s1,
int i)
{
- const unsigned char *s = (const unsigned char *)s1;
- unsigned char c = i;
+ const char *s = (const char *)s1;
+ const char c = (char)i;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
unsigned long mask,j;
- unsigned long *aligned_addr;
+ const long *aligned_addr;
/* Special case for finding 0. */
if (!c)
@@ -72,11 +72,11 @@ strchr (const char *s1,
s++;
}
/* Operate a word at a time. */
- aligned_addr = (unsigned long *) s;
+ aligned_addr = (const long *) s;
while (!DETECTNULL (*aligned_addr))
aligned_addr++;
/* Found the end of string. */
- s = (const unsigned char *) aligned_addr;
+ s = (const char *) aligned_addr;
while (*s)
s++;
return (char *) s;
@@ -92,11 +92,13 @@ strchr (const char *s1,
s++;
}
- mask = c;
- for (j = 8; j < LBLOCKSIZE * 8; j <<= 1)
+ mask = c & 0xff;
+ mask = mask << 8 | mask;
+ mask = mask << 16 | mask;
+ for (j = 32; j < LBLOCKSIZE * 8; j <<= 1)
mask = (mask << j) | mask;
- aligned_addr = (unsigned long *) s;
+ aligned_addr = (const long *) s;
while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask))
aligned_addr++;
@@ -104,7 +106,7 @@ strchr (const char *s1,
contains either a null or the target char, or both. We
catch it using the bytewise search. */
- s = (unsigned char *) aligned_addr;
+ s = (const char *) aligned_addr;
#endif /* not PREFER_SIZE_OVER_SPEED */
diff --git a/newlib/libc/string/strcmp.c b/newlib/libc/string/strcmp.c
index 894424a69..0a534cfdf 100644
--- a/newlib/libc/string/strcmp.c
+++ b/newlib/libc/string/strcmp.c
@@ -34,7 +34,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* DETECTNULL returns nonzero if (long)X contains a NULL byte. */
#if LONG_MAX == 2147483647L
@@ -62,17 +62,17 @@ strcmp (const char *s1,
s2++;
}
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+ return (*(const unsigned char *) s1) - (*(const unsigned char *) s2);
#else
- unsigned long *a1;
- unsigned long *a2;
+ const long *a1;
+ const long *a2;
/* If s1 or s2 are unaligned, then compare bytes. */
if (!UNALIGNED (s1, s2))
{
/* If s1 and s2 are word-aligned, compare them a word at a time. */
- a1 = (unsigned long*)s1;
- a2 = (unsigned long*)s2;
+ a1 = (const long*)s1;
+ a2 = (const long*)s2;
while (*a1 == *a2)
{
/* To get here, *a1 == *a2, thus if we find a null in *a1,
@@ -85,8 +85,8 @@ strcmp (const char *s1,
}
/* A difference was detected in last few bytes of s1, so search bytewise */
- s1 = (char*)a1;
- s2 = (char*)a2;
+ s1 = (const char*)a1;
+ s2 = (const char*)a2;
}
while (*s1 != '\0' && *s1 == *s2)
@@ -94,6 +94,6 @@ strcmp (const char *s1,
s1++;
s2++;
}
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+ return (*(const unsigned char *) s1) - (*(const unsigned char *) s2);
#endif /* not PREFER_SIZE_OVER_SPEED */
}
diff --git a/newlib/libc/string/strcpy.c b/newlib/libc/string/strcpy.c
index 94e16b512..9d3792ed3 100644
--- a/newlib/libc/string/strcpy.c
+++ b/newlib/libc/string/strcpy.c
@@ -34,7 +34,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
@@ -56,10 +56,10 @@ strcpy (char *dst0,
const char *src0)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- char *s = dst0;
+ char * const s = dst0;
- while (*dst0++ = *src0++)
- ;
+ while (*dst0 = *src0)
+ dst0++, src0++;
return s;
#else
@@ -72,7 +72,7 @@ strcpy (char *dst0,
if (!UNALIGNED (src, dst))
{
aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_src = (const long*)src;
/* SRC and DEST are both "long int" aligned, try to do "long int"
sized copies. */
@@ -82,11 +82,11 @@ strcpy (char *dst0,
}
dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ src = (const char*)aligned_src;
}
- while ((*dst++ = *src++))
- ;
+ while (*dst = *src)
+ dst++, src++;
return dst0;
#endif /* not PREFER_SIZE_OVER_SPEED */
}
diff --git a/newlib/libc/string/strcspn.c b/newlib/libc/string/strcspn.c
index abaa93ad6..89ba3eb4d 100644
--- a/newlib/libc/string/strcspn.c
+++ b/newlib/libc/string/strcspn.c
@@ -29,20 +29,19 @@ size_t
strcspn (const char *s1,
const char *s2)
{
- const char *s = s1;
+ const char *s;
const char *c;
- while (*s1)
+ for (s = s1; *s; s++)
{
for (c = s2; *c; c++)
{
- if (*s1 == *c)
+ if (*s == *c)
break;
}
if (*c)
break;
- s1++;
}
- return s1 - s;
+ return s - s1;
}
diff --git a/newlib/libc/string/strlen.c b/newlib/libc/string/strlen.c
index acffa49e1..1b7c7969d 100644
--- a/newlib/libc/string/strlen.c
+++ b/newlib/libc/string/strlen.c
@@ -54,7 +54,7 @@ strlen (const char *str)
const char *start = str;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
- unsigned long *aligned_addr;
+ const long *aligned_addr;
/* Align the pointer, so we can search a word at a time. */
while (UNALIGNED (str))
@@ -66,17 +66,17 @@ strlen (const char *str)
/* If the string is word-aligned, we can check for the presence of
a null in each word-sized block. */
- aligned_addr = (unsigned long *)str;
+ aligned_addr = (const long *)str;
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. */
- str = (char *) aligned_addr;
+ str = (const char *) aligned_addr;
#endif /* not PREFER_SIZE_OVER_SPEED */
- while (*str)
+ while (*str != '\0')
str++;
return str - start;
}
diff --git a/newlib/libc/string/strncmp.c b/newlib/libc/string/strncmp.c
index 16f8a7729..77291aebb 100644
--- a/newlib/libc/string/strncmp.c
+++ b/newlib/libc/string/strncmp.c
@@ -34,7 +34,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((long)X | (long)Y) & (sizeof (long) - 1))
/* DETECTNULL returns nonzero if (long)X contains a NULL byte. */
#if LONG_MAX == 2147483647L
@@ -60,18 +60,18 @@ strncmp (const char *s1,
if (n == 0)
return 0;
- while (n-- != 0 && *s1 == *s2)
+ while (*s1 == *s2)
{
- if (n == 0 || *s1 == '\0')
+ if (--n == 0 || *s1 == '\0')
break;
s1++;
s2++;
}
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+ return (*(const unsigned char *) s1) - (*(const unsigned char *) s2);
#else
- unsigned long *a1;
- unsigned long *a2;
+ const long *a1;
+ const long *a2;
if (n == 0)
return 0;
@@ -80,8 +80,8 @@ strncmp (const char *s1,
if (!UNALIGNED (s1, s2))
{
/* If s1 and s2 are word-aligned, compare them a word at a time. */
- a1 = (unsigned long*)s1;
- a2 = (unsigned long*)s2;
+ a1 = (const long*)s1;
+ a2 = (const long*)s2;
while (n >= sizeof (long) && *a1 == *a2)
{
n -= sizeof (long);
@@ -96,19 +96,19 @@ strncmp (const char *s1,
}
/* A difference was detected in last few bytes of s1, so search bytewise */
- s1 = (char*)a1;
- s2 = (char*)a2;
+ s1 = (const char*)a1;
+ s2 = (const char*)a2;
}
- while (n-- > 0 && *s1 == *s2)
+ while (*s1 == *s2)
{
/* If we've run out of bytes or hit a null, return zero
since we already know *s1 == *s2. */
- if (n == 0 || *s1 == '\0')
- return 0;
+ if (--n == 0 || *s1 == '\0')
+ return 0;
s1++;
s2++;
}
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+ return (*(const unsigned char *) s1) - (*(const unsigned char *) s2);
#endif /* not PREFER_SIZE_OVER_SPEED */
}
diff --git a/newlib/libc/string/strncpy.c b/newlib/libc/string/strncpy.c
index e7eb34d72..55921b6a1 100644
--- a/newlib/libc/string/strncpy.c
+++ b/newlib/libc/string/strncpy.c
@@ -39,7 +39,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
@@ -75,7 +75,7 @@ strncpy (char *__restrict dst0,
if ((*dscan++ = *sscan++) == '\0')
break;
}
- while (count-- > 0)
+ for (; count; count--)
*dscan++ = '\0';
return dst0;
@@ -89,7 +89,7 @@ strncpy (char *__restrict dst0,
if (!UNALIGNED (src, dst) && !TOO_SMALL (count))
{
aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_src = (const long*)src;
/* SRC and DEST are both "long int" aligned, try to do "long int"
sized copies. */
@@ -100,7 +100,7 @@ strncpy (char *__restrict dst0,
}
dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ src = (const char*)aligned_src;
}
while (count > 0)
@@ -110,7 +110,7 @@ strncpy (char *__restrict dst0,
break;
}
- while (count-- > 0)
+ for (; count; count--)
*dst++ = '\0';
return dst0;
diff --git a/newlib/libc/string/strnlen.c b/newlib/libc/string/strnlen.c
index 3ee18d1c0..adc09f160 100644
--- a/newlib/libc/string/strnlen.c
+++ b/newlib/libc/string/strnlen.c
@@ -35,7 +35,7 @@ strnlen (const char *str,
{
const char *start = str;
- while (n-- > 0 && *str)
+ for (; n && *str; n--)
str++;
return str - start;
diff --git a/newlib/libc/string/strnstr.c b/newlib/libc/string/strnstr.c
index cb5f71914..b2e529a4e 100644
--- a/newlib/libc/string/strnstr.c
+++ b/newlib/libc/string/strnstr.c
@@ -40,7 +40,7 @@ QUICKREF
char *
strnstr(const char *haystack, const char *needle, size_t haystack_len)
{
- size_t needle_len = strnlen(needle, haystack_len);
+ const size_t needle_len = strnlen(needle, haystack_len);
if (needle_len < haystack_len || !needle[needle_len]) {
char *x = memmem(haystack, haystack_len, needle, needle_len);
diff --git a/newlib/libc/string/strrchr.c b/newlib/libc/string/strrchr.c
index 35a7060d2..a7e5da8b9 100644
--- a/newlib/libc/string/strrchr.c
+++ b/newlib/libc/string/strrchr.c
@@ -34,11 +34,10 @@ strrchr (const char *s,
int i)
{
const char *last = NULL;
- char c = i;
- if (c)
+ if (i & 0xff)
{
- while ((s=strchr(s, c)))
+ while ((s=strchr(s, i)))
{
last = s;
s++;
@@ -46,7 +45,7 @@ strrchr (const char *s,
}
else
{
- last = strchr(s, c);
+ last = strchr(s, i);
}
return (char *) last;
diff --git a/newlib/libc/string/strspn.c b/newlib/libc/string/strspn.c
index baf239947..553977186 100644
--- a/newlib/libc/string/strspn.c
+++ b/newlib/libc/string/strspn.c
@@ -36,7 +36,7 @@ strspn (const char *s1,
const char *s = s1;
const char *c;
- while (*s1)
+ for (s = s1; *s; s++)
{
for (c = s2; *c; c++)
{
@@ -45,8 +45,7 @@ strspn (const char *s1,
}
if (*c == '\0')
break;
- s1++;
}
- return s1 - s;
+ return s - s1;
}
diff --git a/newlib/libc/string/strstr.c b/newlib/libc/string/strstr.c
index 84e4632f1..9afbc1fa1 100644
--- a/newlib/libc/string/strstr.c
+++ b/newlib/libc/string/strstr.c
@@ -67,7 +67,7 @@ char *
strstr (const char *hs, const char *ne)
{
size_t i;
- int c = ne[0];
+ char c = ne[0];
if (c == 0)
return (char*)hs;
@@ -143,24 +143,22 @@ strstr4 (const unsigned char *hs, const unsigned char *ne)
char *
strstr (const char *haystack, const char *needle)
{
- const unsigned char *hs = (const unsigned char *) haystack;
- const unsigned char *ne = (const unsigned char *) needle;
- int i;
+ size_t i;
/* Handle short needle special cases first. */
- if (ne[0] == '\0')
- return (char *) hs;
- if (ne[1] == '\0')
- return (char*)strchr ((const char *) hs, ne[0]);
- if (ne[2] == '\0')
- return strstr2 (hs, ne);
- if (ne[3] == '\0')
- return strstr3 (hs, ne);
- if (ne[4] == '\0')
- return strstr4 (hs, ne);
-
- size_t ne_len = strlen ((const char *) ne);
- size_t hs_len = strnlen ((const char *) hs, ne_len | 512);
+ if (needle[0] == '\0')
+ return haystack;
+ if (needle[1] == '\0')
+ return (char*)strchr (haystack, needle[0]);
+ if (needle[2] == '\0')
+ return strstr2 (haystack, needle);
+ if (needle[3] == '\0')
+ return strstr3 (haystack, needle);
+ if (needle[4] == '\0')
+ return strstr4 (haystack, needle);
+
+ size_t ne_len = strlen (haystack);
+ size_t hs_len = strnlen (needle, ne_len | 512);
/* Ensure haystack length is >= needle length. */
if (hs_len < ne_len)
@@ -170,35 +168,35 @@ strstr (const char *haystack, const char *needle)
if (__builtin_expect (ne_len < 255, 1))
{
uint8_t shift[1 << SHIFT_TABLE_BITS];
- const unsigned char *end = hs + hs_len - ne_len;
+ const char *end = haystack + hs_len - ne_len;
/* Initialize bad character shift hash table. */
memset (shift, ne_len + 1, sizeof (shift));
for (i = 0; i < ne_len; i++)
- shift[ne[i] % sizeof (shift)] = ne_len - i;
+ shift[needle[i] % sizeof (shift)] = ne_len - i;
do
{
- hs--;
+ haystack--;
/* Search by skipping past bad characters. */
- size_t tmp = shift[hs[ne_len] % sizeof (shift)];
- for (hs += tmp; hs <= end; hs += tmp)
+ size_t tmp = shift[haystack[ne_len] % sizeof (shift)];
+ for (haystack += tmp; haystack <= end; haystack += tmp)
{
- tmp = shift[hs[ne_len] % sizeof (shift)];
- if (memcmp (hs, ne, ne_len) == 0)
- return (char*) hs;
+ tmp = shift[haystack[ne_len] % sizeof (shift)];
+ if (memcmp (haystack, needle, ne_len) == 0)
+ return (char*) haystack;
}
if (end[ne_len] == 0)
return NULL;
end += strnlen ((const char *) (end + ne_len), 2048);
}
- while (hs <= end);
+ while (haystack <= end);
return NULL;
}
/* Use Two-Way algorithm for very long needles. */
- return two_way_long_needle (hs, hs_len, ne, ne_len);
+ return two_way_long_needle (haystack, hs_len, needle, ne_len);
}
#endif /* compilation for speed */
diff --git a/newlib/libc/string/strxfrm.c b/newlib/libc/string/strxfrm.c
index c5df0bcd5..537981586 100644
--- a/newlib/libc/string/strxfrm.c
+++ b/newlib/libc/string/strxfrm.c
@@ -50,14 +50,12 @@ strxfrm (char *__restrict s1,
const char *__restrict s2,
size_t n)
{
- size_t res;
- res = 0;
- while (n-- > 0)
+ size_t res = 0;
+ for (; n; n--)
{
- if ((*s1++ = *s2++) != '\0')
- ++res;
- else
- return res;
+ if ((*s1++ = *s2++) == '\0')
+ return res;
+ ++res;
}
while (*s2)
{
diff --git a/newlib/libc/string/swab.c b/newlib/libc/string/swab.c
index 28ab978bd..01910dc53 100644
--- a/newlib/libc/string/swab.c
+++ b/newlib/libc/string/swab.c
@@ -22,13 +22,13 @@ swab (const void *b1,
void *b2,
ssize_t length)
{
- const char *from = b1;
- char *to = b2;
+ const unsigned char *from = b1;
+ unsigned char *to = b2;
ssize_t ptr;
for (ptr = 1; ptr < length; ptr += 2)
{
- char p = from[ptr];
- char q = from[ptr-1];
+ unsigned char p = from[ptr];
+ unsigned char q = from[ptr-1];
to[ptr-1] = p;
to[ptr ] = q;
}
-- 
2.37.1

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] newlib: libc: Optimize the string functions
  2022-08-12 21:11 Seija Kijin
@ 2022-08-16 11:08 ` Corinna Vinschen
  0 siblings, 0 replies; 4+ messages in thread
From: Corinna Vinschen @ 2022-08-16 11:08 UTC (permalink / raw)
  To: Seija Kijin; +Cc: newlib

Hi Seija,

Thanks for the patch.

First of all, your patch is broken in terms of whitespaces and line
breaks, so it can't be applied.  I suspect your MUA is doing that
automatically.  You better provide the git patch as attachement, or
change your MUA settings to leave whitespaces and line breaks alone.

On Aug 12 17:11, Seija Kijin wrote:
> --- a/newlib/libc/string/memccpy.c
> +++ b/newlib/libc/string/memccpy.c
> @@ -34,16 +34,17 @@ PORTABILITY
> /* Nonzero if either X or Y is not aligned on a "long" boundary. */
> #define UNALIGNED(X, Y) \
> - (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
> + (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
> /* How many bytes are copied each iteration of the word copy loop. */
> -#define LITTLEBLOCKSIZE (sizeof (long))
> +#define LITTLEBLOCKSIZE (sizeof (unsigned long))
> /* Threshhold for punting to the byte copier. */
> #define TOO_SMALL(LEN) ((LEN) < LITTLEBLOCKSIZE)
> /* Macros for detecting endchar */
> #if LONG_MAX == 2147483647L
> +#define MAGIC

Why? There's no MAGIC in this code.

> #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
> #else
> #if LONG_MAX == 9223372036854775807L
> @@ -64,11 +65,11 @@ memccpy (void *__restrict dst0,
> #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
> void *ptr = NULL;
> - char *dst = (char *) dst0;
> - char *src = (char *) src0;
> - char endchar = endchar0 & 0xff;
> + unsigned char *dst = (unsigned char *) dst0;
> + const unsigned char *src = (const unsigned char *) src0;
> + const unsigned char endchar = (unsigned char) endchar0;
> - while (len0--)
> + for (; len0; len0--)

What exactly are you winning here?  How do you know that splitting a
compare-postdecrement into separate compare and decrement is faster than
the original operation?

- Not decrementing immediately after compare only "optimizes" the first
  iteration of the loop.  Any further iteration needs to decrement and
  compare anyway.  So the supposed advantage only affects the degenerated
  case of len0 == 0 and is insignificant in any other case.

- The compiler can optimize this by its own, with different optimizations
  leading to one of the expressions being faster than the other depending
  on compiler version and/or target CPU.

- One CPU could have optimized microcode for compare-postdecrement which
  you may break up into less optimized code if the compiler's optimizer
  isn't capable of combining the ops again.

- Alternatively the target CPU has an optimized predecrement-compare op
  and no optimized compare-postdecrement op.  But this is generic code.
  You don't know if you're speeding up or slowing down, or not affecting
  at all.

Given that, I'd leave this loops alone.  It's the job of the compiler to
optimize them.  The changes only raise the size of the patch unnecessarily.

Same goes for changes like this:

  while ([...])
    {
-     if (!length--)
+     if (!length)
	[...]
+     length--;
    }

> void *
> memmem (const void *haystack, size_t hs_len, const void *needle, size_t ne_len)
> {
> - const char *hs = haystack;
> - const char *ne = needle;
> + const unsigned char *hs = haystack;
> + const unsigned char *ne = needle;
> if (ne_len == 0)
> return (void *)hs;
> - int i;
> - int c = ne[0];
> - const char *end = hs + hs_len - ne_len;
> + size_t i;
    ^^^^^^^^^
    This is actually a bugfix.  Thanks for catching it, but it
    very much deserves a patch of its own, together with the
    other changes from int to size_t in memmem and strstr.

> @@ -143,7 +143,7 @@ memmem (const void *haystack, size_t hs_len, const
> void *needle, size_t ne_len)
> size_t tmp, shift1;
> size_t m1 = ne_len - 1;
> size_t offset = 0;
> - int i;
> + size_t i;
    ^^^^^^^^^
 ...this one.

Sorry, but I've given up after about half of the patch.  I don't see why
this is only a single huge patch.  If there's any problem, multiple
smaller patches are easier to understand, and easier to revert or
bisect.

Please resend this patch as a patchset, preferredly one file per patch
including a matching commit message per patch.  The aforementioned
bugfix should be a separate patch in the patchset.


Thanks,
Corinna


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] newlib: libc: Optimize the string functions
@ 2022-08-12 21:11 Seija Kijin
  2022-08-16 11:08 ` Corinna Vinschen
  0 siblings, 1 reply; 4+ messages in thread
From: Seija Kijin @ 2022-08-12 21:11 UTC (permalink / raw)
  To: newlib

The code is well written, however, there is some room for improvement
in terms of performance. This is an attempt to make the string
functions more consistent and performant.

Most of the changes were simple refactorings, with some code changed
to better match that of other files in the same directory.

Pointers to unsigned variables in memory sometimes cause some older
compilers to generate better code than if they were signed, hence
those changes as well.
---
newlib/libc/machine/microblaze/strcmp.c | 2 +-
newlib/libc/machine/microblaze/strcpy.c | 2 +-
newlib/libc/string/memccpy.c | 49 ++++++++++++-----------
newlib/libc/string/memchr.c | 9 +++--
newlib/libc/string/memcmp.c | 32 +++++++--------
newlib/libc/string/memcpy.c | 34 +++++++---------
newlib/libc/string/memmem.c | 18 ++++-----
newlib/libc/string/memmove.c | 34 ++++++++--------
newlib/libc/string/mempcpy.c | 30 +++++++-------
newlib/libc/string/memrchr.c | 17 ++++----
newlib/libc/string/memset.c | 19 +++++----
newlib/libc/string/rawmemchr.c | 19 ++++-----
newlib/libc/string/stpcpy.c | 12 +++---
newlib/libc/string/stpncpy.c | 13 ++++---
newlib/libc/string/strcasestr.c | 30 +++++++-------
newlib/libc/string/strcat.c | 6 +--
newlib/libc/string/strchr.c | 20 +++++-----
newlib/libc/string/strcmp.c | 18 ++++-----
newlib/libc/string/strcpy.c | 16 ++++----
newlib/libc/string/strcspn.c | 9 ++---
newlib/libc/string/strlen.c | 8 ++--
newlib/libc/string/strncmp.c | 28 ++++++-------
newlib/libc/string/strncpy.c | 10 ++---
newlib/libc/string/strnlen.c | 2 +-
newlib/libc/string/strnstr.c | 2 +-
newlib/libc/string/strrchr.c | 7 ++--
newlib/libc/string/strspn.c | 5 +--
newlib/libc/string/strstr.c | 52 ++++++++++++-------------
newlib/libc/string/strxfrm.c | 12 +++---
newlib/libc/string/swab.c | 8 ++--
30 files changed, 254 insertions(+), 269 deletions(-)

diff --git a/newlib/libc/machine/microblaze/strcmp.c
b/newlib/libc/machine/microblaze/strcmp.c
index 434195e2c..050437149 100644
--- a/newlib/libc/machine/microblaze/strcmp.c
+++ b/newlib/libc/machine/microblaze/strcmp.c
@@ -63,7 +63,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* DETECTNULL returns nonzero if (long)X contains a NULL byte. */
#if LONG_MAX == 2147483647L
diff --git a/newlib/libc/machine/microblaze/strcpy.c
b/newlib/libc/machine/microblaze/strcpy.c
index 62072fa28..b4e45e6a2 100644
--- a/newlib/libc/machine/microblaze/strcpy.c
+++ b/newlib/libc/machine/microblaze/strcpy.c
@@ -63,7 +63,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
diff --git a/newlib/libc/string/memccpy.c b/newlib/libc/string/memccpy.c
index 1f5f55c50..6e352f57e 100644
--- a/newlib/libc/string/memccpy.c
+++ b/newlib/libc/string/memccpy.c
@@ -34,16 +34,17 @@ PORTABILITY
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the word copy loop. */
-#define LITTLEBLOCKSIZE (sizeof (long))
+#define LITTLEBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the byte copier. */
#define TOO_SMALL(LEN) ((LEN) < LITTLEBLOCKSIZE)
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647L
+#define MAGIC
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
#else
#if LONG_MAX == 9223372036854775807L
@@ -64,11 +65,11 @@ memccpy (void *__restrict dst0,
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
void *ptr = NULL;
- char *dst = (char *) dst0;
- char *src = (char *) src0;
- char endchar = endchar0 & 0xff;
+ unsigned char *dst = (unsigned char *) dst0;
+ const unsigned char *src = (const unsigned char *) src0;
+ const unsigned char endchar = (unsigned char) endchar0;
- while (len0--)
+ for (; len0; len0--)
{
if ((*dst++ = *src++) == endchar)
{
@@ -80,21 +81,21 @@ memccpy (void *__restrict dst0,
return ptr;
#else
void *ptr = NULL;
- char *dst = dst0;
- const char *src = src0;
- long *aligned_dst;
- const long *aligned_src;
- char endchar = endchar0 & 0xff;
+ unsigned char *dst = (unsigned char *) dst0;
+ const unsigned char *src = (const unsigned char *) src0;
+ unsigned long *aligned_dst;
+ const unsigned long *aligned_src;
+ const unsigned char endchar = (unsigned char) endchar0;
/* If the size is small, or either SRC or DST is unaligned,
then punt into the byte copy loop. This should be rare. */
if (!TOO_SMALL(len0) && !UNALIGNED (src, dst))
{
unsigned int i;
- unsigned long mask = 0;
+ unsigned long mask;
- aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_dst = (unsigned long*)dst;
+ aligned_src = (const unsigned long*)src;
/* The fast code reads the ASCII one word at a time and only
performs the bytewise search on word-sized segments if they
@@ -102,27 +103,29 @@ memccpy (void *__restrict dst0,
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;
+
+ mask = endchar << 8 | endchar;
+ mask = mask << 16 | mask;
+ for (i = 32; i < LITTLEBLOCKSIZE * 8; i <<= 1)
+ mask = (mask << i) | mask;
/* Copy one long word at a time if possible. */
- while (len0 >= LITTLEBLOCKSIZE)
+ do
{
- unsigned long buffer = (unsigned long)(*aligned_src);
- buffer ^= mask;
+ unsigned long buffer = *aligned_src ^ mask;
if (DETECTNULL (buffer))
break; /* endchar is found, go byte by byte from here */
*aligned_dst++ = *aligned_src++;
len0 -= LITTLEBLOCKSIZE;
- }
+ } while (len0 >= LITTLEBLOCKSIZE);
/* Pick up any residual with a byte copier. */
- dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ dst = (unsigned char*)aligned_dst;
+ src = (const unsigned char*)aligned_src;
}
- while (len0--)
+ for (; len0; len0--)
{
if ((*dst++ = *src++) == endchar)
{
diff --git a/newlib/libc/string/memchr.c b/newlib/libc/string/memchr.c
index 21bc4d879..614af2bfc 100644
--- a/newlib/libc/string/memchr.c
+++ b/newlib/libc/string/memchr.c
@@ -37,7 +37,7 @@ QUICKREF
#define UNALIGNED(X) ((long)X & (sizeof (long) - 1))
/* How many bytes are loaded each iteration of the word copy loop. */
-#define LBLOCKSIZE (sizeof (long))
+#define LBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the bytewise iterator. */
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
@@ -67,7 +67,7 @@ memchr (const void *src_void,
size_t length)
{
const unsigned char *src = (const unsigned char *) src_void;
- unsigned char d = c;
+ const unsigned char d = (unsigned char) c;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
unsigned long *asrc;
@@ -76,11 +76,12 @@ memchr (const void *src_void,
while (UNALIGNED (src))
{
- if (!length--)
+ if (!length)
return NULL;
if (*src == d)
return (void *) src;
src++;
+ length--;
}
if (!TOO_SMALL (length))
@@ -93,7 +94,7 @@ memchr (const void *src_void,
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 = (unsigned long *) src;
+ asrc = (const unsigned long *) src;
mask = d << 8 | d;
mask = mask << 16 | mask;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
diff --git a/newlib/libc/string/memcmp.c b/newlib/libc/string/memcmp.c
index 342fb9fbc..4f186777d 100644
--- a/newlib/libc/string/memcmp.c
+++ b/newlib/libc/string/memcmp.c
@@ -34,10 +34,10 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the word copy loop. */
-#define LBLOCKSIZE (sizeof (long))
+#define LBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the byte copier. */
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
@@ -48,22 +48,20 @@ memcmp (const void *m1,
size_t n)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- unsigned char *s1 = (unsigned char *) m1;
- unsigned char *s2 = (unsigned char *) m2;
+ const unsigned char *s1 = (const unsigned char *) m1;
+ const unsigned char *s2 = (const unsigned char *) m2;
- while (n--)
+ for (; n; n--)
{
if (*s1 != *s2)
- {
return *s1 - *s2;
- }
s1++;
s2++;
}
return 0;
#else
- unsigned char *s1 = (unsigned char *) m1;
- unsigned char *s2 = (unsigned char *) m2;
+ const unsigned char *s1 = (const unsigned char *) m1;
+ const unsigned char *s2 = (const unsigned char *) m2;
unsigned long *a1;
unsigned long *a2;
@@ -74,24 +72,24 @@ memcmp (const void *m1,
{
/* Otherwise, load and compare the blocks of memory one
word at a time. */
- a1 = (unsigned long*) s1;
- a2 = (unsigned long*) s2;
- while (n >= LBLOCKSIZE)
+ a1 = (const unsigned long*) s1;
+ a2 = (const unsigned long*) s2;
+ while (*a1 == *a2)
{
- if (*a1 != *a2)
- break;
a1++;
a2++;
n -= LBLOCKSIZE;
+ if (TOO_SMALL(n))
+ break;
}
/* check m mod LBLOCKSIZE remaining characters */
- s1 = (unsigned char*)a1;
- s2 = (unsigned char*)a2;
+ s1 = (const unsigned char*)a1;
+ s2 = (const unsigned char*)a2;
}
- while (n--)
+ for (; n; n--)
{
if (*s1 != *s2)
return *s1 - *s2;
diff --git a/newlib/libc/string/memcpy.c b/newlib/libc/string/memcpy.c
index 52f716b92..96cacd99e 100644
--- a/newlib/libc/string/memcpy.c
+++ b/newlib/libc/string/memcpy.c
@@ -33,7 +33,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the 4X unrolled loop. */
#define BIGBLOCKSIZE (sizeof (long) << 2)
@@ -51,29 +51,25 @@ memcpy (void *__restrict dst0,
size_t len0)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- char *dst = (char *) dst0;
- char *src = (char *) src0;
+ unsigned char *dst = (unsigned char *) dst0;
+ const unsigned char *src = (const unsigned char *) src0;
- void *save = dst0;
-
- while (len0--)
- {
+ for (; len0; len0--)
*dst++ = *src++;
- }
- return save;
+ return dst0;
#else
- char *dst = dst0;
- const char *src = src0;
- long *aligned_dst;
- const long *aligned_src;
+ unsigned char *dst = dst0;
+ const unsigned char *src = src0;
+ unsigned long *aligned_dst;
+ const unsigned long *aligned_src;
/* If the size is small, or either SRC or DST is unaligned,
then punt into the byte copy loop. This should be rare. */
if (!TOO_SMALL(len0) && !UNALIGNED (src, dst))
{
- aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_dst = (unsigned long*)dst;
+ aligned_src = (const unsigned long*)src;
/* Copy 4X long words at a time if possible. */
while (len0 >= BIGBLOCKSIZE)
@@ -93,12 +89,12 @@ memcpy (void *__restrict dst0,
}
/* Pick up any residual with a byte copier. */
- dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ dst = (unsigned char*)aligned_dst;
+ src = (const unsigned char*)aligned_src;
}
- while (len0--)
- *dst++ = *src++;
+ for (; len0; len0--)
+ *dst++ = *src++;
return dst0;
#endif /* not PREFER_SIZE_OVER_SPEED */
diff --git a/newlib/libc/string/memmem.c b/newlib/libc/string/memmem.c
index 65267b9c5..c074a295c 100644
--- a/newlib/libc/string/memmem.c
+++ b/newlib/libc/string/memmem.c
@@ -68,14 +68,14 @@ QUICKREF
void *
memmem (const void *haystack, size_t hs_len, const void *needle, size_t ne_len)
{
- const char *hs = haystack;
- const char *ne = needle;
+ const unsigned char *hs = haystack;
+ const unsigned char *ne = needle;
if (ne_len == 0)
return (void *)hs;
- int i;
- int c = ne[0];
- const char *end = hs + hs_len - ne_len;
+ size_t i;
+ const unsigned char c = ne[0];
+ const unsigned char *end = hs + hs_len - ne_len;
for ( ; hs <= end; hs++)
{
@@ -143,7 +143,7 @@ memmem (const void *haystack, size_t hs_len, const
void *needle, size_t ne_len)
size_t tmp, shift1;
size_t m1 = ne_len - 1;
size_t offset = 0;
- int i;
+ size_t i;
/* Initialize bad character shift hash table. */
memset (shift, 0, sizeof (shift));
@@ -152,7 +152,7 @@ memmem (const void *haystack, size_t hs_len, const
void *needle, size_t ne_len)
shift1 = m1 - shift[hash2 (ne + m1)];
shift[hash2 (ne + m1)] = m1;
- for ( ; hs <= end; )
+ while (hs <= end)
{
/* Skip past character pairs not in the needle. */
do
@@ -170,13 +170,13 @@ memmem (const void *haystack, size_t hs_len,
const void *needle, size_t ne_len)
/* The last 2 characters match. If the needle is long, check a
fixed number of characters first to quickly filter out mismatches. */
- if (m1 <= 15 || memcmp (hs + offset, ne + offset, sizeof (long)) == 0)
+ if (m1 <= 15 || memcmp (hs + offset, ne + offset, sizeof (unsigned
long)) == 0)
{
if (memcmp (hs, ne, m1) == 0)
return (void *) hs;
/* Adjust filter offset when it doesn't find the mismatch. */
- offset = (offset >= sizeof (long) ? offset : m1) - sizeof (long);
+ offset = (offset >= sizeof (unsigned long) ? offset : m1) - sizeof
(unsigned long);
}
/* Skip based on matching the last 2 characters. */
diff --git a/newlib/libc/string/memmove.c b/newlib/libc/string/memmove.c
index da5dfdbdd..17334c37a 100644
--- a/newlib/libc/string/memmove.c
+++ b/newlib/libc/string/memmove.c
@@ -36,7 +36,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the 4X unrolled loop. */
#define BIGBLOCKSIZE (sizeof (long) << 2)
@@ -55,22 +55,22 @@ memmove (void *dst_void,
size_t length)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- char *dst = dst_void;
- const char *src = src_void;
+ unsigned char *dst = dst_void;
+ const unsigned char *src = src_void;
- if (src < dst && dst < src + length)
+ if (dst - src < length) /* Unsigned compare means underflow is
accounted for */
{
/* Have to copy backwards */
src += length;
dst += length;
- while (length--)
+ for (; length; length--)
{
*--dst = *--src;
}
}
else
{
- while (length--)
+ for (; length; length--)
{
*dst++ = *src++;
}
@@ -78,17 +78,17 @@ memmove (void *dst_void,
return dst_void;
#else
- char *dst = dst_void;
- const char *src = src_void;
- long *aligned_dst;
- const long *aligned_src;
+ unsigned char *dst = dst_void;
+ const unsigned char *src = src_void;
+ unsigned long *aligned_dst;
+ const unsigned long *aligned_src;
- if (src < dst && dst < src + length)
+ if (dst - src < length) /* Unsigned compare means underflow is
accounted for */
{
/* Destructive overlap...have to copy backwards */
src += length;
dst += length;
- while (length--)
+ for (; length; --length)
{
*--dst = *--src;
}
@@ -100,8 +100,8 @@ memmove (void *dst_void,
then punt into the byte copy loop. This should be rare. */
if (!TOO_SMALL(length) && !UNALIGNED (src, dst))
{
- aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_dst = (unsigned long*)dst;
+ aligned_src = (const unsigned long*)src;
/* Copy 4X long words at a time if possible. */
while (length >= BIGBLOCKSIZE)
@@ -121,11 +121,11 @@ memmove (void *dst_void,
}
/* Pick up any residual with a byte copier. */
- dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ dst = (unsigned char*)aligned_dst;
+ src = (const unsigned char*)aligned_src;
}
- while (length--)
+ for (; length; length--)
{
*dst++ = *src++;
}
diff --git a/newlib/libc/string/mempcpy.c b/newlib/libc/string/mempcpy.c
index 129165603..b13af2dc5 100644
--- a/newlib/libc/string/mempcpy.c
+++ b/newlib/libc/string/mempcpy.c
@@ -31,7 +31,7 @@ PORTABILITY
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the 4X unrolled loop. */
#define BIGBLOCKSIZE (sizeof (long) << 2)
@@ -48,27 +48,25 @@ mempcpy (void *dst0,
size_t len0)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- char *dst = (char *) dst0;
- char *src = (char *) src0;
+ unsigned char *dst = (unsigned char *) dst0;
+ const unsigned char *src = (const unsigned char *) src0;
- while (len0--)
- {
+ for (; len0; len0--)
*dst++ = *src++;
- }
return dst;
#else
- char *dst = dst0;
- const char *src = src0;
- long *aligned_dst;
- const long *aligned_src;
+ unsigned char *dst = dst0;
+ const unsigned char *src = src0;
+ unsigned long *aligned_dst;
+ const unsigned long *aligned_src;
/* If the size is small, or either SRC or DST is unaligned,
then punt into the byte copy loop. This should be rare. */
if (!TOO_SMALL(len0) && !UNALIGNED (src, dst))
{
- aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_dst = (unsigned long*)dst;
+ aligned_src = (const unsigned long*)src;
/* Copy 4X long words at a time if possible. */
while (len0 >= BIGBLOCKSIZE)
@@ -88,12 +86,12 @@ mempcpy (void *dst0,
}
/* Pick up any residual with a byte copier. */
- dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ dst = (unsigned char*)aligned_dst;
+ src = (const unsigned char*)aligned_src;
}
- while (len0--)
- *dst++ = *src++;
+ for (; len0; len0--)
+ *dst++ = *src++;
return dst;
#endif /* not PREFER_SIZE_OVER_SPEED */
diff --git a/newlib/libc/string/memrchr.c b/newlib/libc/string/memrchr.c
index 652efb359..b5aa1e0d2 100644
--- a/newlib/libc/string/memrchr.c
+++ b/newlib/libc/string/memrchr.c
@@ -37,7 +37,7 @@ QUICKREF
#define UNALIGNED(X) ((long)(X + 1) & (sizeof (long) - 1))
/* How many bytes are loaded each iteration of the word copy loop. */
-#define LBLOCKSIZE (sizeof (long))
+#define LBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the bytewise iterator. */
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
@@ -67,7 +67,7 @@ memrchr (const void *src_void,
size_t length)
{
const unsigned char *src = (const unsigned char *) src_void + length - 1;
- unsigned char d = c;
+ const unsigned char d = (unsigned char) c;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
unsigned long *asrc;
@@ -76,10 +76,11 @@ memrchr (const void *src_void,
while (UNALIGNED (src))
{
- if (!length--)
+ if (!length)
return NULL;
if (*src == d)
return (void *) src;
+ length--;
src--;
}
@@ -93,15 +94,15 @@ memrchr (const void *src_void,
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 = (unsigned long *) (src - LBLOCKSIZE + 1);
+ asrc = (const unsigned long *) (src - LBLOCKSIZE + 1);
mask = d << 8 | d;
mask = mask << 16 | mask;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
mask = (mask << i) | mask;
- while (length >= LBLOCKSIZE)
+ while (!DETECTCHAR (*asrc, mask))
{
- if (DETECTCHAR (*asrc, mask))
+ if (TOO_SMALL (length))
break;
length -= LBLOCKSIZE;
asrc--;
@@ -110,12 +111,12 @@ memrchr (const void *src_void,
/* If there are fewer than LBLOCKSIZE characters left,
then we resort to the bytewise loop. */
- src = (unsigned char *) asrc + LBLOCKSIZE - 1;
+ src = (const unsigned char *) asrc + LBLOCKSIZE - 1;
}
#endif /* not PREFER_SIZE_OVER_SPEED */
- while (length--)
+ for (; length; length--)
{
if (*src == d)
return (void *) src;
diff --git a/newlib/libc/string/memset.c b/newlib/libc/string/memset.c
index e8e667a24..0c8f8012a 100644
--- a/newlib/libc/string/memset.c
+++ b/newlib/libc/string/memset.c
@@ -39,21 +39,20 @@ memset (void *m,
int c,
size_t n)
{
- char *s = (char *) m;
+ unsigned char *s = (unsigned char *) m;
+ const unsigned char d = (unsigned char) c;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
unsigned int i;
unsigned long buffer;
unsigned long *aligned_addr;
- unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an
- unsigned variable. */
while (UNALIGNED (s))
{
- if (n--)
- *s++ = (char) c;
- else
+ if (!n)
return m;
+ *s++ = d;
+ n--;
}
if (!TOO_SMALL (n))
@@ -64,7 +63,7 @@ memset (void *m,
/* Store D into each char sized location in BUFFER so that
we can set large blocks quickly. */
buffer = (d << 8) | d;
- buffer |= (buffer << 16);
+ buffer = (buffer << 16) | buffer;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
buffer = (buffer << i) | buffer;
@@ -84,13 +83,13 @@ memset (void *m,
n -= LBLOCKSIZE;
}
/* Pick up the remainder with a bytewise loop. */
- s = (char*)aligned_addr;
+ s = (unsigned char*)aligned_addr;
}
#endif /* not PREFER_SIZE_OVER_SPEED */
- while (n--)
- *s++ = (char) c;
+ for (; n; n--)
+ *s++ = d;
return m;
}
diff --git a/newlib/libc/string/rawmemchr.c b/newlib/libc/string/rawmemchr.c
index 56e2b5e2d..3ab95bb28 100644
--- a/newlib/libc/string/rawmemchr.c
+++ b/newlib/libc/string/rawmemchr.c
@@ -36,7 +36,7 @@ QUICKREF
#define UNALIGNED(X) ((long)X & (sizeof (long) - 1))
/* How many bytes are loaded each iteration of the word copy loop. */
-#define LBLOCKSIZE (sizeof (long))
+#define LBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the bytewise iterator. */
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
@@ -65,10 +65,10 @@ rawmemchr (const void *src_void,
int c)
{
const unsigned char *src = (const unsigned char *) src_void;
- unsigned char d = c;
+ const unsigned char d = (unsigned char) c;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
- unsigned long *asrc;
+ const unsigned long *asrc;
unsigned long mask;
unsigned int i;
@@ -86,29 +86,26 @@ rawmemchr (const void *src_void,
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 = (unsigned long *) src;
+ asrc = (const unsigned long *) src;
mask = d << 8 | d;
mask = mask << 16 | mask;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
mask = (mask << i) | mask;
- while (1)
+ while (!DETECTCHAR (*asrc, mask))
{
- if (DETECTCHAR (*asrc, mask))
- break;
asrc++;
}
/* We have the matching word, now we resort to a bytewise loop. */
- src = (unsigned char *) asrc;
+ src = (const unsigned char *) asrc;
#endif /* !PREFER_SIZE_OVER_SPEED && !__OPTIMIZE_SIZE__ */
- while (1)
+ while (*src != d)
{
- if (*src == d)
- return (void *) src;
src++;
}
+ return (void *) src;
}
diff --git a/newlib/libc/string/stpcpy.c b/newlib/libc/string/stpcpy.c
index 4e2ae9fe0..bbd96ab98 100644
--- a/newlib/libc/string/stpcpy.c
+++ b/newlib/libc/string/stpcpy.c
@@ -35,7 +35,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
@@ -64,7 +64,7 @@ stpcpy (char *__restrict dst,
if (!UNALIGNED (src, dst))
{
aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_src = (const long*)src;
/* SRC and DEST are both "long int" aligned, try to do "long int"
sized copies. */
@@ -74,11 +74,11 @@ stpcpy (char *__restrict dst,
}
dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ src = (const char*)aligned_src;
}
#endif /* not PREFER_SIZE_OVER_SPEED */
- while ((*dst++ = *src++))
- ;
- return --dst;
+ while ((*dst = *src))
+ dst++, src++;
+ return dst;
}
diff --git a/newlib/libc/string/stpncpy.c b/newlib/libc/string/stpncpy.c
index 87fe268cf..6ca186e95 100644
--- a/newlib/libc/string/stpncpy.c
+++ b/newlib/libc/string/stpncpy.c
@@ -41,7 +41,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
@@ -75,7 +75,7 @@ stpncpy (char *__restrict dst,
if (!UNALIGNED (src, dst) && !TOO_SMALL (count))
{
aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_src = (const long*)src;
/* SRC and DEST are both "long int" aligned, try to do "long int"
sized copies. */
@@ -86,21 +86,22 @@ stpncpy (char *__restrict dst,
}
dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ src = (const char*)aligned_src;
}
#endif /* not PREFER_SIZE_OVER_SPEED */
while (count > 0)
{
--count;
- if ((*dst++ = *src++) == '\0')
+ if ((*dst = *src) == '\0')
{
- ret = dst - 1;
+ ret = dst;
break;
}
+ dst++, src++;
}
- while (count-- > 0)
+ for (; count > 0; count--)
*dst++ = '\0';
return ret ? ret : dst;
diff --git a/newlib/libc/string/strcasestr.c b/newlib/libc/string/strcasestr.c
index 36e183986..db6b07cb9 100644
--- a/newlib/libc/string/strcasestr.c
+++ b/newlib/libc/string/strcasestr.c
@@ -99,15 +99,13 @@ strcasestr (const char *s,
char c, sc;
size_t len;
- if ((c = *find++) != 0) {
- c = tolower((unsigned char)c);
+ if ((c = *find++) != '\0') {
+ c = tolower(c & 0xff);
len = strlen(find);
do {
- do {
- if ((sc = *s++) == 0)
- return (NULL);
- } while ((char)tolower((unsigned char)sc) != c);
- } while (strncasecmp(s, find, len) != 0);
+ if ((sc = *s++) == '\0')
+ return (NULL);
+ } while (((char)tolower(sc & 0xff) != c) && strncasecmp(s, find, len) != 0);
s--;
}
return ((char *)s);
@@ -115,8 +113,8 @@ strcasestr (const char *s,
#else /* compilation for speed */
/* Larger code size, but guaranteed linear performance. */
- const char *haystack = s;
- const char *needle = find;
+ const unsigned char *haystack = (const unsigned char *)s;
+ const unsigned char *needle = (const unsigned char *)find;
size_t needle_len; /* Length of NEEDLE. */
size_t haystack_len; /* Known minimum length of HAYSTACK. */
int ok = 1; /* True if NEEDLE is prefix of HAYSTACK. */
@@ -125,22 +123,20 @@ strcasestr (const char *s,
HAYSTACK is at least as long (no point processing all of a long
NEEDLE if HAYSTACK is too short). */
while (*haystack && *needle)
- ok &= (tolower ((unsigned char) *haystack++)
- == tolower ((unsigned char) *needle++));
+ ok &= (tolower (*haystack++)
+ == tolower (*needle++));
if (*needle)
return NULL;
if (ok)
return (char *) s;
needle_len = needle - find;
- haystack = s + 1;
+ needle = (const unsigned char *)find;
+ haystack = (const unsigned char *)s + 1;
haystack_len = needle_len - 1;
/* Perform the search. */
if (needle_len < LONG_NEEDLE_THRESHOLD)
- return two_way_short_needle ((const unsigned char *) haystack,
- haystack_len,
- (const unsigned char *) find, needle_len);
- return two_way_long_needle ((const unsigned char *) haystack, haystack_len,
- (const unsigned char *) find, needle_len);
+ return two_way_short_needle (haystack, haystack_len, needle, needle_len);
+ return two_way_long_needle (haystack, haystack_len, needle, needle_len);
#endif /* compilation for speed */
}
diff --git a/newlib/libc/string/strcat.c b/newlib/libc/string/strcat.c
index 92313c492..ce5183c9b 100644
--- a/newlib/libc/string/strcat.c
+++ b/newlib/libc/string/strcat.c
@@ -63,8 +63,8 @@ strcat (char *__restrict s1,
while (*s1)
s1++;
- while (*s1++ = *s2++)
- ;
+ while (*s1 = *s2)
+ s1++, s2++;
return s;
#else
char *s = s1;
@@ -73,7 +73,7 @@ strcat (char *__restrict s1,
/* Skip over the data in s1 as quickly as possible. */
if (ALIGNED (s1))
{
- unsigned long *aligned_s1 = (unsigned long *)s1;
+ long *aligned_s1 = (long *)s1;
while (!DETECTNULL (*aligned_s1))
aligned_s1++;
diff --git a/newlib/libc/string/strchr.c b/newlib/libc/string/strchr.c
index 96f30be04..3bf44c43c 100644
--- a/newlib/libc/string/strchr.c
+++ b/newlib/libc/string/strchr.c
@@ -55,12 +55,12 @@ char *
strchr (const char *s1,
int i)
{
- const unsigned char *s = (const unsigned char *)s1;
- unsigned char c = i;
+ const char *s = (const char *)s1;
+ const char c = (char)i;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
unsigned long mask,j;
- unsigned long *aligned_addr;
+ const long *aligned_addr;
/* Special case for finding 0. */
if (!c)
@@ -72,11 +72,11 @@ strchr (const char *s1,
s++;
}
/* Operate a word at a time. */
- aligned_addr = (unsigned long *) s;
+ aligned_addr = (const long *) s;
while (!DETECTNULL (*aligned_addr))
aligned_addr++;
/* Found the end of string. */
- s = (const unsigned char *) aligned_addr;
+ s = (const char *) aligned_addr;
while (*s)
s++;
return (char *) s;
@@ -92,11 +92,13 @@ strchr (const char *s1,
s++;
}
- mask = c;
- for (j = 8; j < LBLOCKSIZE * 8; j <<= 1)
+ mask = c & 0xff;
+ mask = mask << 8 | mask;
+ mask = mask << 16 | mask;
+ for (j = 32; j < LBLOCKSIZE * 8; j <<= 1)
mask = (mask << j) | mask;
- aligned_addr = (unsigned long *) s;
+ aligned_addr = (const long *) s;
while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask))
aligned_addr++;
@@ -104,7 +106,7 @@ strchr (const char *s1,
contains either a null or the target char, or both. We
catch it using the bytewise search. */
- s = (unsigned char *) aligned_addr;
+ s = (const char *) aligned_addr;
#endif /* not PREFER_SIZE_OVER_SPEED */
diff --git a/newlib/libc/string/strcmp.c b/newlib/libc/string/strcmp.c
index 894424a69..0a534cfdf 100644
--- a/newlib/libc/string/strcmp.c
+++ b/newlib/libc/string/strcmp.c
@@ -34,7 +34,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* DETECTNULL returns nonzero if (long)X contains a NULL byte. */
#if LONG_MAX == 2147483647L
@@ -62,17 +62,17 @@ strcmp (const char *s1,
s2++;
}
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+ return (*(const unsigned char *) s1) - (*(const unsigned char *) s2);
#else
- unsigned long *a1;
- unsigned long *a2;
+ const long *a1;
+ const long *a2;
/* If s1 or s2 are unaligned, then compare bytes. */
if (!UNALIGNED (s1, s2))
{
/* If s1 and s2 are word-aligned, compare them a word at a time. */
- a1 = (unsigned long*)s1;
- a2 = (unsigned long*)s2;
+ a1 = (const long*)s1;
+ a2 = (const long*)s2;
while (*a1 == *a2)
{
/* To get here, *a1 == *a2, thus if we find a null in *a1,
@@ -85,8 +85,8 @@ strcmp (const char *s1,
}
/* A difference was detected in last few bytes of s1, so search bytewise */
- s1 = (char*)a1;
- s2 = (char*)a2;
+ s1 = (const char*)a1;
+ s2 = (const char*)a2;
}
while (*s1 != '\0' && *s1 == *s2)
@@ -94,6 +94,6 @@ strcmp (const char *s1,
s1++;
s2++;
}
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+ return (*(const unsigned char *) s1) - (*(const unsigned char *) s2);
#endif /* not PREFER_SIZE_OVER_SPEED */
}
diff --git a/newlib/libc/string/strcpy.c b/newlib/libc/string/strcpy.c
index 94e16b512..9d3792ed3 100644
--- a/newlib/libc/string/strcpy.c
+++ b/newlib/libc/string/strcpy.c
@@ -34,7 +34,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
@@ -56,10 +56,10 @@ strcpy (char *dst0,
const char *src0)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- char *s = dst0;
+ char * const s = dst0;
- while (*dst0++ = *src0++)
- ;
+ while (*dst0 = *src0)
+ dst0++, src0++;
return s;
#else
@@ -72,7 +72,7 @@ strcpy (char *dst0,
if (!UNALIGNED (src, dst))
{
aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_src = (const long*)src;
/* SRC and DEST are both "long int" aligned, try to do "long int"
sized copies. */
@@ -82,11 +82,11 @@ strcpy (char *dst0,
}
dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ src = (const char*)aligned_src;
}
- while ((*dst++ = *src++))
- ;
+ while (*dst = *src)
+ dst++, src++;
return dst0;
#endif /* not PREFER_SIZE_OVER_SPEED */
}
diff --git a/newlib/libc/string/strcspn.c b/newlib/libc/string/strcspn.c
index abaa93ad6..89ba3eb4d 100644
--- a/newlib/libc/string/strcspn.c
+++ b/newlib/libc/string/strcspn.c
@@ -29,20 +29,19 @@ size_t
strcspn (const char *s1,
const char *s2)
{
- const char *s = s1;
+ const char *s;
const char *c;
- while (*s1)
+ for (s = s1; *s; s++)
{
for (c = s2; *c; c++)
{
- if (*s1 == *c)
+ if (*s == *c)
break;
}
if (*c)
break;
- s1++;
}
- return s1 - s;
+ return s - s1;
}
diff --git a/newlib/libc/string/strlen.c b/newlib/libc/string/strlen.c
index acffa49e1..1b7c7969d 100644
--- a/newlib/libc/string/strlen.c
+++ b/newlib/libc/string/strlen.c
@@ -54,7 +54,7 @@ strlen (const char *str)
const char *start = str;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
- unsigned long *aligned_addr;
+ const long *aligned_addr;
/* Align the pointer, so we can search a word at a time. */
while (UNALIGNED (str))
@@ -66,17 +66,17 @@ strlen (const char *str)
/* If the string is word-aligned, we can check for the presence of
a null in each word-sized block. */
- aligned_addr = (unsigned long *)str;
+ aligned_addr = (const long *)str;
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. */
- str = (char *) aligned_addr;
+ str = (const char *) aligned_addr;
#endif /* not PREFER_SIZE_OVER_SPEED */
- while (*str)
+ while (*str != '\0')
str++;
return str - start;
}
diff --git a/newlib/libc/string/strncmp.c b/newlib/libc/string/strncmp.c
index 16f8a7729..77291aebb 100644
--- a/newlib/libc/string/strncmp.c
+++ b/newlib/libc/string/strncmp.c
@@ -34,7 +34,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((long)X | (long)Y) & (sizeof (long) - 1))
/* DETECTNULL returns nonzero if (long)X contains a NULL byte. */
#if LONG_MAX == 2147483647L
@@ -60,18 +60,18 @@ strncmp (const char *s1,
if (n == 0)
return 0;
- while (n-- != 0 && *s1 == *s2)
+ while (*s1 == *s2)
{
- if (n == 0 || *s1 == '\0')
+ if (--n == 0 || *s1 == '\0')
break;
s1++;
s2++;
}
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+ return (*(const unsigned char *) s1) - (*(const unsigned char *) s2);
#else
- unsigned long *a1;
- unsigned long *a2;
+ const long *a1;
+ const long *a2;
if (n == 0)
return 0;
@@ -80,8 +80,8 @@ strncmp (const char *s1,
if (!UNALIGNED (s1, s2))
{
/* If s1 and s2 are word-aligned, compare them a word at a time. */
- a1 = (unsigned long*)s1;
- a2 = (unsigned long*)s2;
+ a1 = (const long*)s1;
+ a2 = (const long*)s2;
while (n >= sizeof (long) && *a1 == *a2)
{
n -= sizeof (long);
@@ -96,19 +96,19 @@ strncmp (const char *s1,
}
/* A difference was detected in last few bytes of s1, so search bytewise */
- s1 = (char*)a1;
- s2 = (char*)a2;
+ s1 = (const char*)a1;
+ s2 = (const char*)a2;
}
- while (n-- > 0 && *s1 == *s2)
+ while (*s1 == *s2)
{
/* If we've run out of bytes or hit a null, return zero
since we already know *s1 == *s2. */
- if (n == 0 || *s1 == '\0')
- return 0;
+ if (--n == 0 || *s1 == '\0')
+ return 0;
s1++;
s2++;
}
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+ return (*(const unsigned char *) s1) - (*(const unsigned char *) s2);
#endif /* not PREFER_SIZE_OVER_SPEED */
}
diff --git a/newlib/libc/string/strncpy.c b/newlib/libc/string/strncpy.c
index e7eb34d72..55921b6a1 100644
--- a/newlib/libc/string/strncpy.c
+++ b/newlib/libc/string/strncpy.c
@@ -39,7 +39,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
@@ -75,7 +75,7 @@ strncpy (char *__restrict dst0,
if ((*dscan++ = *sscan++) == '\0')
break;
}
- while (count-- > 0)
+ for (; count; count--)
*dscan++ = '\0';
return dst0;
@@ -89,7 +89,7 @@ strncpy (char *__restrict dst0,
if (!UNALIGNED (src, dst) && !TOO_SMALL (count))
{
aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_src = (const long*)src;
/* SRC and DEST are both "long int" aligned, try to do "long int"
sized copies. */
@@ -100,7 +100,7 @@ strncpy (char *__restrict dst0,
}
dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ src = (const char*)aligned_src;
}
while (count > 0)
@@ -110,7 +110,7 @@ strncpy (char *__restrict dst0,
break;
}
- while (count-- > 0)
+ for (; count; count--)
*dst++ = '\0';
return dst0;
diff --git a/newlib/libc/string/strnlen.c b/newlib/libc/string/strnlen.c
index 3ee18d1c0..adc09f160 100644
--- a/newlib/libc/string/strnlen.c
+++ b/newlib/libc/string/strnlen.c
@@ -35,7 +35,7 @@ strnlen (const char *str,
{
const char *start = str;
- while (n-- > 0 && *str)
+ for (; n && *str; n--)
str++;
return str - start;
diff --git a/newlib/libc/string/strnstr.c b/newlib/libc/string/strnstr.c
index cb5f71914..b2e529a4e 100644
--- a/newlib/libc/string/strnstr.c
+++ b/newlib/libc/string/strnstr.c
@@ -40,7 +40,7 @@ QUICKREF
char *
strnstr(const char *haystack, const char *needle, size_t haystack_len)
{
- size_t needle_len = strnlen(needle, haystack_len);
+ const size_t needle_len = strnlen(needle, haystack_len);
if (needle_len < haystack_len || !needle[needle_len]) {
char *x = memmem(haystack, haystack_len, needle, needle_len);
diff --git a/newlib/libc/string/strrchr.c b/newlib/libc/string/strrchr.c
index 35a7060d2..a7e5da8b9 100644
--- a/newlib/libc/string/strrchr.c
+++ b/newlib/libc/string/strrchr.c
@@ -34,11 +34,10 @@ strrchr (const char *s,
int i)
{
const char *last = NULL;
- char c = i;
- if (c)
+ if (i & 0xff)
{
- while ((s=strchr(s, c)))
+ while ((s=strchr(s, i)))
{
last = s;
s++;
@@ -46,7 +45,7 @@ strrchr (const char *s,
}
else
{
- last = strchr(s, c);
+ last = strchr(s, i);
}
return (char *) last;
diff --git a/newlib/libc/string/strspn.c b/newlib/libc/string/strspn.c
index baf239947..553977186 100644
--- a/newlib/libc/string/strspn.c
+++ b/newlib/libc/string/strspn.c
@@ -36,7 +36,7 @@ strspn (const char *s1,
const char *s = s1;
const char *c;
- while (*s1)
+ for (s = s1; *s; s++)
{
for (c = s2; *c; c++)
{
@@ -45,8 +45,7 @@ strspn (const char *s1,
}
if (*c == '\0')
break;
- s1++;
}
- return s1 - s;
+ return s - s1;
}
diff --git a/newlib/libc/string/strstr.c b/newlib/libc/string/strstr.c
index 84e4632f1..9afbc1fa1 100644
--- a/newlib/libc/string/strstr.c
+++ b/newlib/libc/string/strstr.c
@@ -67,7 +67,7 @@ char *
strstr (const char *hs, const char *ne)
{
size_t i;
- int c = ne[0];
+ char c = ne[0];
if (c == 0)
return (char*)hs;
@@ -143,24 +143,22 @@ strstr4 (const unsigned char *hs, const unsigned char *ne)
char *
strstr (const char *haystack, const char *needle)
{
- const unsigned char *hs = (const unsigned char *) haystack;
- const unsigned char *ne = (const unsigned char *) needle;
- int i;
+ size_t i;
/* Handle short needle special cases first. */
- if (ne[0] == '\0')
- return (char *) hs;
- if (ne[1] == '\0')
- return (char*)strchr ((const char *) hs, ne[0]);
- if (ne[2] == '\0')
- return strstr2 (hs, ne);
- if (ne[3] == '\0')
- return strstr3 (hs, ne);
- if (ne[4] == '\0')
- return strstr4 (hs, ne);
-
- size_t ne_len = strlen ((const char *) ne);
- size_t hs_len = strnlen ((const char *) hs, ne_len | 512);
+ if (needle[0] == '\0')
+ return haystack;
+ if (needle[1] == '\0')
+ return (char*)strchr (haystack, needle[0]);
+ if (needle[2] == '\0')
+ return strstr2 (haystack, needle);
+ if (needle[3] == '\0')
+ return strstr3 (haystack, needle);
+ if (needle[4] == '\0')
+ return strstr4 (haystack, needle);
+
+ size_t ne_len = strlen (haystack);
+ size_t hs_len = strnlen (needle, ne_len | 512);
/* Ensure haystack length is >= needle length. */
if (hs_len < ne_len)
@@ -170,35 +168,35 @@ strstr (const char *haystack, const char *needle)
if (__builtin_expect (ne_len < 255, 1))
{
uint8_t shift[1 << SHIFT_TABLE_BITS];
- const unsigned char *end = hs + hs_len - ne_len;
+ const char *end = haystack + hs_len - ne_len;
/* Initialize bad character shift hash table. */
memset (shift, ne_len + 1, sizeof (shift));
for (i = 0; i < ne_len; i++)
- shift[ne[i] % sizeof (shift)] = ne_len - i;
+ shift[needle[i] % sizeof (shift)] = ne_len - i;
do
{
- hs--;
+ haystack--;
/* Search by skipping past bad characters. */
- size_t tmp = shift[hs[ne_len] % sizeof (shift)];
- for (hs += tmp; hs <= end; hs += tmp)
+ size_t tmp = shift[haystack[ne_len] % sizeof (shift)];
+ for (haystack += tmp; haystack <= end; haystack += tmp)
{
- tmp = shift[hs[ne_len] % sizeof (shift)];
- if (memcmp (hs, ne, ne_len) == 0)
- return (char*) hs;
+ tmp = shift[haystack[ne_len] % sizeof (shift)];
+ if (memcmp (haystack, needle, ne_len) == 0)
+ return (char*) haystack;
}
if (end[ne_len] == 0)
return NULL;
end += strnlen ((const char *) (end + ne_len), 2048);
}
- while (hs <= end);
+ while (haystack <= end);
return NULL;
}
/* Use Two-Way algorithm for very long needles. */
- return two_way_long_needle (hs, hs_len, ne, ne_len);
+ return two_way_long_needle (haystack, hs_len, needle, ne_len);
}
#endif /* compilation for speed */
diff --git a/newlib/libc/string/strxfrm.c b/newlib/libc/string/strxfrm.c
index c5df0bcd5..537981586 100644
--- a/newlib/libc/string/strxfrm.c
+++ b/newlib/libc/string/strxfrm.c
@@ -50,14 +50,12 @@ strxfrm (char *__restrict s1,
const char *__restrict s2,
size_t n)
{
- size_t res;
- res = 0;
- while (n-- > 0)
+ size_t res = 0;
+ for (; n; n--)
{
- if ((*s1++ = *s2++) != '\0')
- ++res;
- else
- return res;
+ if ((*s1++ = *s2++) == '\0')
+ return res;
+ ++res;
}
while (*s2)
{
diff --git a/newlib/libc/string/swab.c b/newlib/libc/string/swab.c
index 28ab978bd..01910dc53 100644
--- a/newlib/libc/string/swab.c
+++ b/newlib/libc/string/swab.c
@@ -22,13 +22,13 @@ swab (const void *b1,
void *b2,
ssize_t length)
{
- const char *from = b1;
- char *to = b2;
+ const unsigned char *from = b1;
+ unsigned char *to = b2;
ssize_t ptr;
for (ptr = 1; ptr < length; ptr += 2)
{
- char p = from[ptr];
- char q = from[ptr-1];
+ unsigned char p = from[ptr];
+ unsigned char q = from[ptr-1];
to[ptr-1] = p;
to[ptr ] = q;
}
-- 
2.37.1

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] newlib: libc: Optimize the string functions
@ 2022-08-12 20:38 Seija Kijin
  0 siblings, 0 replies; 4+ messages in thread
From: Seija Kijin @ 2022-08-12 20:38 UTC (permalink / raw)
  To: newlib

The code is well written, however, there is some room for improvement
in terms of performance. This is an attempt to make the string
functions more consistent and performant.
Most of the changes were simple refactorings, with some code changed
to better match that of other files in the same directory.
Pointers to unsigned variables in memory sometimes cause some older
compilers to generate better code than if they were signed, hence
those changes as well.
---
newlib/libc/machine/microblaze/strcmp.c | 2 +-
newlib/libc/machine/microblaze/strcpy.c | 2 +-
newlib/libc/string/memccpy.c | 49 ++++++++++++-----------
newlib/libc/string/memchr.c | 9 +++--
newlib/libc/string/memcmp.c | 34 ++++++++--------
newlib/libc/string/memcpy.c | 34 +++++++---------
newlib/libc/string/memmem.c | 18 ++++-----
newlib/libc/string/memmove.c | 34 ++++++++--------
newlib/libc/string/mempcpy.c | 30 +++++++-------
newlib/libc/string/memrchr.c | 17 ++++----
newlib/libc/string/memset.c | 19 +++++----
newlib/libc/string/rawmemchr.c | 19 ++++-----
newlib/libc/string/stpcpy.c | 12 +++---
newlib/libc/string/stpncpy.c | 13 ++++---
newlib/libc/string/strcasestr.c | 30 +++++++-------
newlib/libc/string/strcat.c | 6 +--
newlib/libc/string/strchr.c | 20 +++++-----
newlib/libc/string/strcmp.c | 18 ++++-----
newlib/libc/string/strcpy.c | 16 ++++----
newlib/libc/string/strcspn.c | 9 ++---
newlib/libc/string/strlen.c | 8 ++--
newlib/libc/string/strncmp.c | 28 ++++++-------
newlib/libc/string/strncpy.c | 10 ++---
newlib/libc/string/strnlen.c | 2 +-
newlib/libc/string/strnstr.c | 2 +-
newlib/libc/string/strrchr.c | 7 ++--
newlib/libc/string/strspn.c | 5 +--
newlib/libc/string/strstr.c | 52 ++++++++++++-------------
newlib/libc/string/strxfrm.c | 12 +++---
newlib/libc/string/swab.c | 8 ++--
30 files changed, 255 insertions(+), 270 deletions(-)

diff --git a/newlib/libc/machine/microblaze/strcmp.c
b/newlib/libc/machine/microblaze/strcmp.c
index 434195e2c..050437149 100644
--- a/newlib/libc/machine/microblaze/strcmp.c
+++ b/newlib/libc/machine/microblaze/strcmp.c
@@ -63,7 +63,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* DETECTNULL returns nonzero if (long)X contains a NULL byte. */
#if LONG_MAX == 2147483647L
diff --git a/newlib/libc/machine/microblaze/strcpy.c
b/newlib/libc/machine/microblaze/strcpy.c
index 62072fa28..b4e45e6a2 100644
--- a/newlib/libc/machine/microblaze/strcpy.c
+++ b/newlib/libc/machine/microblaze/strcpy.c
@@ -63,7 +63,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
diff --git a/newlib/libc/string/memccpy.c b/newlib/libc/string/memccpy.c
index 1f5f55c50..6e352f57e 100644
--- a/newlib/libc/string/memccpy.c
+++ b/newlib/libc/string/memccpy.c
@@ -34,16 +34,17 @@ PORTABILITY
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the word copy loop. */
-#define LITTLEBLOCKSIZE (sizeof (long))
+#define LITTLEBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the byte copier. */
#define TOO_SMALL(LEN) ((LEN) < LITTLEBLOCKSIZE)
/* Macros for detecting endchar */
#if LONG_MAX == 2147483647L
+#define MAGIC
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
#else
#if LONG_MAX == 9223372036854775807L
@@ -64,11 +65,11 @@ memccpy (void *__restrict dst0,
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
void *ptr = NULL;
- char *dst = (char *) dst0;
- char *src = (char *) src0;
- char endchar = endchar0 & 0xff;
+ unsigned char *dst = (unsigned char *) dst0;
+ const unsigned char *src = (const unsigned char *) src0;
+ const unsigned char endchar = (unsigned char) endchar0;
- while (len0--)
+ for (; len0; len0--)
{
if ((*dst++ = *src++) == endchar)
{
@@ -80,21 +81,21 @@ memccpy (void *__restrict dst0,
return ptr;
#else
void *ptr = NULL;
- char *dst = dst0;
- const char *src = src0;
- long *aligned_dst;
- const long *aligned_src;
- char endchar = endchar0 & 0xff;
+ unsigned char *dst = (unsigned char *) dst0;
+ const unsigned char *src = (const unsigned char *) src0;
+ unsigned long *aligned_dst;
+ const unsigned long *aligned_src;
+ const unsigned char endchar = (unsigned char) endchar0;
/* If the size is small, or either SRC or DST is unaligned,
then punt into the byte copy loop. This should be rare. */
if (!TOO_SMALL(len0) && !UNALIGNED (src, dst))
{
unsigned int i;
- unsigned long mask = 0;
+ unsigned long mask;
- aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_dst = (unsigned long*)dst;
+ aligned_src = (const unsigned long*)src;
/* The fast code reads the ASCII one word at a time and only
performs the bytewise search on word-sized segments if they
@@ -102,27 +103,29 @@ memccpy (void *__restrict dst0,
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;
+
+ mask = endchar << 8 | endchar;
+ mask = mask << 16 | mask;
+ for (i = 32; i < LITTLEBLOCKSIZE * 8; i <<= 1)
+ mask = (mask << i) | mask;
/* Copy one long word at a time if possible. */
- while (len0 >= LITTLEBLOCKSIZE)
+ do
{
- unsigned long buffer = (unsigned long)(*aligned_src);
- buffer ^= mask;
+ unsigned long buffer = *aligned_src ^ mask;
if (DETECTNULL (buffer))
break; /* endchar is found, go byte by byte from here */
*aligned_dst++ = *aligned_src++;
len0 -= LITTLEBLOCKSIZE;
- }
+ } while (len0 >= LITTLEBLOCKSIZE);
/* Pick up any residual with a byte copier. */
- dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ dst = (unsigned char*)aligned_dst;
+ src = (const unsigned char*)aligned_src;
}
- while (len0--)
+ for (; len0; len0--)
{
if ((*dst++ = *src++) == endchar)
{
diff --git a/newlib/libc/string/memchr.c b/newlib/libc/string/memchr.c
index 21bc4d879..614af2bfc 100644
--- a/newlib/libc/string/memchr.c
+++ b/newlib/libc/string/memchr.c
@@ -37,7 +37,7 @@ QUICKREF
#define UNALIGNED(X) ((long)X & (sizeof (long) - 1))
/* How many bytes are loaded each iteration of the word copy loop. */
-#define LBLOCKSIZE (sizeof (long))
+#define LBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the bytewise iterator. */
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
@@ -67,7 +67,7 @@ memchr (const void *src_void,
size_t length)
{
const unsigned char *src = (const unsigned char *) src_void;
- unsigned char d = c;
+ const unsigned char d = (unsigned char) c;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
unsigned long *asrc;
@@ -76,11 +76,12 @@ memchr (const void *src_void,
while (UNALIGNED (src))
{
- if (!length--)
+ if (!length)
return NULL;
if (*src == d)
return (void *) src;
src++;
+ length--;
}
if (!TOO_SMALL (length))
@@ -93,7 +94,7 @@ memchr (const void *src_void,
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 = (unsigned long *) src;
+ asrc = (const unsigned long *) src;
mask = d << 8 | d;
mask = mask << 16 | mask;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
diff --git a/newlib/libc/string/memcmp.c b/newlib/libc/string/memcmp.c
index 342fb9fbc..044a0fba0 100644
--- a/newlib/libc/string/memcmp.c
+++ b/newlib/libc/string/memcmp.c
@@ -34,10 +34,10 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the word copy loop. */
-#define LBLOCKSIZE (sizeof (long))
+#define LBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the byte copier. */
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
@@ -48,22 +48,20 @@ memcmp (const void *m1,
size_t n)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- unsigned char *s1 = (unsigned char *) m1;
- unsigned char *s2 = (unsigned char *) m2;
+ const unsigned char *s1 = (const unsigned char *) m1;
+ const unsigned char *s2 = (const unsigned char *) m2;
- while (n--)
+ for (; n; n--)
{
if (*s1 != *s2)
- {
return *s1 - *s2;
- }
s1++;
s2++;
}
return 0;
#else
- unsigned char *s1 = (unsigned char *) m1;
- unsigned char *s2 = (unsigned char *) m2;
+ const unsigned char *s1 = (const unsigned char *) m1;
+ const unsigned char *s2 = (const unsigned char *) m2;
unsigned long *a1;
unsigned long *a2;
@@ -74,27 +72,27 @@ memcmp (const void *m1,
{
/* Otherwise, load and compare the blocks of memory one
word at a time. */
- a1 = (unsigned long*) s1;
- a2 = (unsigned long*) s2;
- while (n >= LBLOCKSIZE)
+ a1 = (const unsigned long*) s1;
+ a2 = (const unsigned long*) s2;
+ while (*a1 == *a2)
{
- if (*a1 != *a2)
- break;
a1++;
a2++;
n -= LBLOCKSIZE;
+ if (TOO_SMALL(n))
+ break;
}
/* check m mod LBLOCKSIZE remaining characters */
- s1 = (unsigned char*)a1;
- s2 = (unsigned char*)a2;
+ s1 = (const unsigned char*)a1;
+ s2 = (const unsigned char*)a2;
}
- while (n--)
+ for (; n; n--)
{
if (*s1 != *s2)
- return *s1 - *s2;
+ return *s1 - *s2;
s1++;
s2++;
}
diff --git a/newlib/libc/string/memcpy.c b/newlib/libc/string/memcpy.c
index 52f716b92..96cacd99e 100644
--- a/newlib/libc/string/memcpy.c
+++ b/newlib/libc/string/memcpy.c
@@ -33,7 +33,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the 4X unrolled loop. */
#define BIGBLOCKSIZE (sizeof (long) << 2)
@@ -51,29 +51,25 @@ memcpy (void *__restrict dst0,
size_t len0)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- char *dst = (char *) dst0;
- char *src = (char *) src0;
+ unsigned char *dst = (unsigned char *) dst0;
+ const unsigned char *src = (const unsigned char *) src0;
- void *save = dst0;
-
- while (len0--)
- {
+ for (; len0; len0--)
*dst++ = *src++;
- }
- return save;
+ return dst0;
#else
- char *dst = dst0;
- const char *src = src0;
- long *aligned_dst;
- const long *aligned_src;
+ unsigned char *dst = dst0;
+ const unsigned char *src = src0;
+ unsigned long *aligned_dst;
+ const unsigned long *aligned_src;
/* If the size is small, or either SRC or DST is unaligned,
then punt into the byte copy loop. This should be rare. */
if (!TOO_SMALL(len0) && !UNALIGNED (src, dst))
{
- aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_dst = (unsigned long*)dst;
+ aligned_src = (const unsigned long*)src;
/* Copy 4X long words at a time if possible. */
while (len0 >= BIGBLOCKSIZE)
@@ -93,12 +89,12 @@ memcpy (void *__restrict dst0,
}
/* Pick up any residual with a byte copier. */
- dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ dst = (unsigned char*)aligned_dst;
+ src = (const unsigned char*)aligned_src;
}
- while (len0--)
- *dst++ = *src++;
+ for (; len0; len0--)
+ *dst++ = *src++;
return dst0;
#endif /* not PREFER_SIZE_OVER_SPEED */
diff --git a/newlib/libc/string/memmem.c b/newlib/libc/string/memmem.c
index 65267b9c5..c074a295c 100644
--- a/newlib/libc/string/memmem.c
+++ b/newlib/libc/string/memmem.c
@@ -68,14 +68,14 @@ QUICKREF
void *
memmem (const void *haystack, size_t hs_len, const void *needle, size_t ne_len)
{
- const char *hs = haystack;
- const char *ne = needle;
+ const unsigned char *hs = haystack;
+ const unsigned char *ne = needle;
if (ne_len == 0)
return (void *)hs;
- int i;
- int c = ne[0];
- const char *end = hs + hs_len - ne_len;
+ size_t i;
+ const unsigned char c = ne[0];
+ const unsigned char *end = hs + hs_len - ne_len;
for ( ; hs <= end; hs++)
{
@@ -143,7 +143,7 @@ memmem (const void *haystack, size_t hs_len, const
void *needle, size_t ne_len)
size_t tmp, shift1;
size_t m1 = ne_len - 1;
size_t offset = 0;
- int i;
+ size_t i;
/* Initialize bad character shift hash table. */
memset (shift, 0, sizeof (shift));
@@ -152,7 +152,7 @@ memmem (const void *haystack, size_t hs_len, const
void *needle, size_t ne_len)
shift1 = m1 - shift[hash2 (ne + m1)];
shift[hash2 (ne + m1)] = m1;
- for ( ; hs <= end; )
+ while (hs <= end)
{
/* Skip past character pairs not in the needle. */
do
@@ -170,13 +170,13 @@ memmem (const void *haystack, size_t hs_len,
const void *needle, size_t ne_len)
/* The last 2 characters match. If the needle is long, check a
fixed number of characters first to quickly filter out mismatches. */
- if (m1 <= 15 || memcmp (hs + offset, ne + offset, sizeof (long)) == 0)
+ if (m1 <= 15 || memcmp (hs + offset, ne + offset, sizeof (unsigned
long)) == 0)
{
if (memcmp (hs, ne, m1) == 0)
return (void *) hs;
/* Adjust filter offset when it doesn't find the mismatch. */
- offset = (offset >= sizeof (long) ? offset : m1) - sizeof (long);
+ offset = (offset >= sizeof (unsigned long) ? offset : m1) - sizeof
(unsigned long);
}
/* Skip based on matching the last 2 characters. */
diff --git a/newlib/libc/string/memmove.c b/newlib/libc/string/memmove.c
index da5dfdbdd..24a93488d 100644
--- a/newlib/libc/string/memmove.c
+++ b/newlib/libc/string/memmove.c
@@ -36,7 +36,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the 4X unrolled loop. */
#define BIGBLOCKSIZE (sizeof (long) << 2)
@@ -55,22 +55,22 @@ memmove (void *dst_void,
size_t length)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- char *dst = dst_void;
- const char *src = src_void;
+ unsigned char *dst = dst_void;
+ const unsigned char *src = src_void;
- if (src < dst && dst < src + length)
+ if (dst - src >= length) /* Unsigned compare means underflow is
accounted for */
{
/* Have to copy backwards */
src += length;
dst += length;
- while (length--)
+ for (; length; length--)
{
*--dst = *--src;
}
}
else
{
- while (length--)
+ for (; length; length--)
{
*dst++ = *src++;
}
@@ -78,17 +78,17 @@ memmove (void *dst_void,
return dst_void;
#else
- char *dst = dst_void;
- const char *src = src_void;
- long *aligned_dst;
- const long *aligned_src;
+ unsigned char *dst = dst_void;
+ const unsigned char *src = src_void;
+ unsigned long *aligned_dst;
+ const unsigned long *aligned_src;
- if (src < dst && dst < src + length)
+ if (dst - src >= length) /* Unsigned compare means underflow is
accounted for */
{
/* Destructive overlap...have to copy backwards */
src += length;
dst += length;
- while (length--)
+ for (; length; --length)
{
*--dst = *--src;
}
@@ -100,8 +100,8 @@ memmove (void *dst_void,
then punt into the byte copy loop. This should be rare. */
if (!TOO_SMALL(length) && !UNALIGNED (src, dst))
{
- aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_dst = (unsigned long*)dst;
+ aligned_src = (const unsigned long*)src;
/* Copy 4X long words at a time if possible. */
while (length >= BIGBLOCKSIZE)
@@ -121,11 +121,11 @@ memmove (void *dst_void,
}
/* Pick up any residual with a byte copier. */
- dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ dst = (unsigned char*)aligned_dst;
+ src = (const unsigned char*)aligned_src;
}
- while (length--)
+ for (; length; length--)
{
*dst++ = *src++;
}
diff --git a/newlib/libc/string/mempcpy.c b/newlib/libc/string/mempcpy.c
index 129165603..b13af2dc5 100644
--- a/newlib/libc/string/mempcpy.c
+++ b/newlib/libc/string/mempcpy.c
@@ -31,7 +31,7 @@ PORTABILITY
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* How many bytes are copied each iteration of the 4X unrolled loop. */
#define BIGBLOCKSIZE (sizeof (long) << 2)
@@ -48,27 +48,25 @@ mempcpy (void *dst0,
size_t len0)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- char *dst = (char *) dst0;
- char *src = (char *) src0;
+ unsigned char *dst = (unsigned char *) dst0;
+ const unsigned char *src = (const unsigned char *) src0;
- while (len0--)
- {
+ for (; len0; len0--)
*dst++ = *src++;
- }
return dst;
#else
- char *dst = dst0;
- const char *src = src0;
- long *aligned_dst;
- const long *aligned_src;
+ unsigned char *dst = dst0;
+ const unsigned char *src = src0;
+ unsigned long *aligned_dst;
+ const unsigned long *aligned_src;
/* If the size is small, or either SRC or DST is unaligned,
then punt into the byte copy loop. This should be rare. */
if (!TOO_SMALL(len0) && !UNALIGNED (src, dst))
{
- aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_dst = (unsigned long*)dst;
+ aligned_src = (const unsigned long*)src;
/* Copy 4X long words at a time if possible. */
while (len0 >= BIGBLOCKSIZE)
@@ -88,12 +86,12 @@ mempcpy (void *dst0,
}
/* Pick up any residual with a byte copier. */
- dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ dst = (unsigned char*)aligned_dst;
+ src = (const unsigned char*)aligned_src;
}
- while (len0--)
- *dst++ = *src++;
+ for (; len0; len0--)
+ *dst++ = *src++;
return dst;
#endif /* not PREFER_SIZE_OVER_SPEED */
diff --git a/newlib/libc/string/memrchr.c b/newlib/libc/string/memrchr.c
index 652efb359..b5aa1e0d2 100644
--- a/newlib/libc/string/memrchr.c
+++ b/newlib/libc/string/memrchr.c
@@ -37,7 +37,7 @@ QUICKREF
#define UNALIGNED(X) ((long)(X + 1) & (sizeof (long) - 1))
/* How many bytes are loaded each iteration of the word copy loop. */
-#define LBLOCKSIZE (sizeof (long))
+#define LBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the bytewise iterator. */
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
@@ -67,7 +67,7 @@ memrchr (const void *src_void,
size_t length)
{
const unsigned char *src = (const unsigned char *) src_void + length - 1;
- unsigned char d = c;
+ const unsigned char d = (unsigned char) c;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
unsigned long *asrc;
@@ -76,10 +76,11 @@ memrchr (const void *src_void,
while (UNALIGNED (src))
{
- if (!length--)
+ if (!length)
return NULL;
if (*src == d)
return (void *) src;
+ length--;
src--;
}
@@ -93,15 +94,15 @@ memrchr (const void *src_void,
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 = (unsigned long *) (src - LBLOCKSIZE + 1);
+ asrc = (const unsigned long *) (src - LBLOCKSIZE + 1);
mask = d << 8 | d;
mask = mask << 16 | mask;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
mask = (mask << i) | mask;
- while (length >= LBLOCKSIZE)
+ while (!DETECTCHAR (*asrc, mask))
{
- if (DETECTCHAR (*asrc, mask))
+ if (TOO_SMALL (length))
break;
length -= LBLOCKSIZE;
asrc--;
@@ -110,12 +111,12 @@ memrchr (const void *src_void,
/* If there are fewer than LBLOCKSIZE characters left,
then we resort to the bytewise loop. */
- src = (unsigned char *) asrc + LBLOCKSIZE - 1;
+ src = (const unsigned char *) asrc + LBLOCKSIZE - 1;
}
#endif /* not PREFER_SIZE_OVER_SPEED */
- while (length--)
+ for (; length; length--)
{
if (*src == d)
return (void *) src;
diff --git a/newlib/libc/string/memset.c b/newlib/libc/string/memset.c
index e8e667a24..0c8f8012a 100644
--- a/newlib/libc/string/memset.c
+++ b/newlib/libc/string/memset.c
@@ -39,21 +39,20 @@ memset (void *m,
int c,
size_t n)
{
- char *s = (char *) m;
+ unsigned char *s = (unsigned char *) m;
+ const unsigned char d = (unsigned char) c;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
unsigned int i;
unsigned long buffer;
unsigned long *aligned_addr;
- unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an
- unsigned variable. */
while (UNALIGNED (s))
{
- if (n--)
- *s++ = (char) c;
- else
+ if (!n)
return m;
+ *s++ = d;
+ n--;
}
if (!TOO_SMALL (n))
@@ -64,7 +63,7 @@ memset (void *m,
/* Store D into each char sized location in BUFFER so that
we can set large blocks quickly. */
buffer = (d << 8) | d;
- buffer |= (buffer << 16);
+ buffer = (buffer << 16) | buffer;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
buffer = (buffer << i) | buffer;
@@ -84,13 +83,13 @@ memset (void *m,
n -= LBLOCKSIZE;
}
/* Pick up the remainder with a bytewise loop. */
- s = (char*)aligned_addr;
+ s = (unsigned char*)aligned_addr;
}
#endif /* not PREFER_SIZE_OVER_SPEED */
- while (n--)
- *s++ = (char) c;
+ for (; n; n--)
+ *s++ = d;
return m;
}
diff --git a/newlib/libc/string/rawmemchr.c b/newlib/libc/string/rawmemchr.c
index 56e2b5e2d..3ab95bb28 100644
--- a/newlib/libc/string/rawmemchr.c
+++ b/newlib/libc/string/rawmemchr.c
@@ -36,7 +36,7 @@ QUICKREF
#define UNALIGNED(X) ((long)X & (sizeof (long) - 1))
/* How many bytes are loaded each iteration of the word copy loop. */
-#define LBLOCKSIZE (sizeof (long))
+#define LBLOCKSIZE (sizeof (unsigned long))
/* Threshhold for punting to the bytewise iterator. */
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
@@ -65,10 +65,10 @@ rawmemchr (const void *src_void,
int c)
{
const unsigned char *src = (const unsigned char *) src_void;
- unsigned char d = c;
+ const unsigned char d = (unsigned char) c;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
- unsigned long *asrc;
+ const unsigned long *asrc;
unsigned long mask;
unsigned int i;
@@ -86,29 +86,26 @@ rawmemchr (const void *src_void,
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 = (unsigned long *) src;
+ asrc = (const unsigned long *) src;
mask = d << 8 | d;
mask = mask << 16 | mask;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
mask = (mask << i) | mask;
- while (1)
+ while (!DETECTCHAR (*asrc, mask))
{
- if (DETECTCHAR (*asrc, mask))
- break;
asrc++;
}
/* We have the matching word, now we resort to a bytewise loop. */
- src = (unsigned char *) asrc;
+ src = (const unsigned char *) asrc;
#endif /* !PREFER_SIZE_OVER_SPEED && !__OPTIMIZE_SIZE__ */
- while (1)
+ while (*src != d)
{
- if (*src == d)
- return (void *) src;
src++;
}
+ return (void *) src;
}
diff --git a/newlib/libc/string/stpcpy.c b/newlib/libc/string/stpcpy.c
index 4e2ae9fe0..bbd96ab98 100644
--- a/newlib/libc/string/stpcpy.c
+++ b/newlib/libc/string/stpcpy.c
@@ -35,7 +35,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
@@ -64,7 +64,7 @@ stpcpy (char *__restrict dst,
if (!UNALIGNED (src, dst))
{
aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_src = (const long*)src;
/* SRC and DEST are both "long int" aligned, try to do "long int"
sized copies. */
@@ -74,11 +74,11 @@ stpcpy (char *__restrict dst,
}
dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ src = (const char*)aligned_src;
}
#endif /* not PREFER_SIZE_OVER_SPEED */
- while ((*dst++ = *src++))
- ;
- return --dst;
+ while ((*dst = *src))
+ dst++, src++;
+ return dst;
}
diff --git a/newlib/libc/string/stpncpy.c b/newlib/libc/string/stpncpy.c
index 87fe268cf..6ca186e95 100644
--- a/newlib/libc/string/stpncpy.c
+++ b/newlib/libc/string/stpncpy.c
@@ -41,7 +41,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
@@ -75,7 +75,7 @@ stpncpy (char *__restrict dst,
if (!UNALIGNED (src, dst) && !TOO_SMALL (count))
{
aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_src = (const long*)src;
/* SRC and DEST are both "long int" aligned, try to do "long int"
sized copies. */
@@ -86,21 +86,22 @@ stpncpy (char *__restrict dst,
}
dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ src = (const char*)aligned_src;
}
#endif /* not PREFER_SIZE_OVER_SPEED */
while (count > 0)
{
--count;
- if ((*dst++ = *src++) == '\0')
+ if ((*dst = *src) == '\0')
{
- ret = dst - 1;
+ ret = dst;
break;
}
+ dst++, src++;
}
- while (count-- > 0)
+ for (; count > 0; count--)
*dst++ = '\0';
return ret ? ret : dst;
diff --git a/newlib/libc/string/strcasestr.c b/newlib/libc/string/strcasestr.c
index 36e183986..db6b07cb9 100644
--- a/newlib/libc/string/strcasestr.c
+++ b/newlib/libc/string/strcasestr.c
@@ -99,15 +99,13 @@ strcasestr (const char *s,
char c, sc;
size_t len;
- if ((c = *find++) != 0) {
- c = tolower((unsigned char)c);
+ if ((c = *find++) != '\0') {
+ c = tolower(c & 0xff);
len = strlen(find);
do {
- do {
- if ((sc = *s++) == 0)
- return (NULL);
- } while ((char)tolower((unsigned char)sc) != c);
- } while (strncasecmp(s, find, len) != 0);
+ if ((sc = *s++) == '\0')
+ return (NULL);
+ } while (((char)tolower(sc & 0xff) != c) && strncasecmp(s, find, len) != 0);
s--;
}
return ((char *)s);
@@ -115,8 +113,8 @@ strcasestr (const char *s,
#else /* compilation for speed */
/* Larger code size, but guaranteed linear performance. */
- const char *haystack = s;
- const char *needle = find;
+ const unsigned char *haystack = (const unsigned char *)s;
+ const unsigned char *needle = (const unsigned char *)find;
size_t needle_len; /* Length of NEEDLE. */
size_t haystack_len; /* Known minimum length of HAYSTACK. */
int ok = 1; /* True if NEEDLE is prefix of HAYSTACK. */
@@ -125,22 +123,20 @@ strcasestr (const char *s,
HAYSTACK is at least as long (no point processing all of a long
NEEDLE if HAYSTACK is too short). */
while (*haystack && *needle)
- ok &= (tolower ((unsigned char) *haystack++)
- == tolower ((unsigned char) *needle++));
+ ok &= (tolower (*haystack++)
+ == tolower (*needle++));
if (*needle)
return NULL;
if (ok)
return (char *) s;
needle_len = needle - find;
- haystack = s + 1;
+ needle = (const unsigned char *)find;
+ haystack = (const unsigned char *)s + 1;
haystack_len = needle_len - 1;
/* Perform the search. */
if (needle_len < LONG_NEEDLE_THRESHOLD)
- return two_way_short_needle ((const unsigned char *) haystack,
- haystack_len,
- (const unsigned char *) find, needle_len);
- return two_way_long_needle ((const unsigned char *) haystack, haystack_len,
- (const unsigned char *) find, needle_len);
+ return two_way_short_needle (haystack, haystack_len, needle, needle_len);
+ return two_way_long_needle (haystack, haystack_len, needle, needle_len);
#endif /* compilation for speed */
}
diff --git a/newlib/libc/string/strcat.c b/newlib/libc/string/strcat.c
index 92313c492..ce5183c9b 100644
--- a/newlib/libc/string/strcat.c
+++ b/newlib/libc/string/strcat.c
@@ -63,8 +63,8 @@ strcat (char *__restrict s1,
while (*s1)
s1++;
- while (*s1++ = *s2++)
- ;
+ while (*s1 = *s2)
+ s1++, s2++;
return s;
#else
char *s = s1;
@@ -73,7 +73,7 @@ strcat (char *__restrict s1,
/* Skip over the data in s1 as quickly as possible. */
if (ALIGNED (s1))
{
- unsigned long *aligned_s1 = (unsigned long *)s1;
+ long *aligned_s1 = (long *)s1;
while (!DETECTNULL (*aligned_s1))
aligned_s1++;
diff --git a/newlib/libc/string/strchr.c b/newlib/libc/string/strchr.c
index 96f30be04..3bf44c43c 100644
--- a/newlib/libc/string/strchr.c
+++ b/newlib/libc/string/strchr.c
@@ -55,12 +55,12 @@ char *
strchr (const char *s1,
int i)
{
- const unsigned char *s = (const unsigned char *)s1;
- unsigned char c = i;
+ const char *s = (const char *)s1;
+ const char c = (char)i;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
unsigned long mask,j;
- unsigned long *aligned_addr;
+ const long *aligned_addr;
/* Special case for finding 0. */
if (!c)
@@ -72,11 +72,11 @@ strchr (const char *s1,
s++;
}
/* Operate a word at a time. */
- aligned_addr = (unsigned long *) s;
+ aligned_addr = (const long *) s;
while (!DETECTNULL (*aligned_addr))
aligned_addr++;
/* Found the end of string. */
- s = (const unsigned char *) aligned_addr;
+ s = (const char *) aligned_addr;
while (*s)
s++;
return (char *) s;
@@ -92,11 +92,13 @@ strchr (const char *s1,
s++;
}
- mask = c;
- for (j = 8; j < LBLOCKSIZE * 8; j <<= 1)
+ mask = c & 0xff;
+ mask = mask << 8 | mask;
+ mask = mask << 16 | mask;
+ for (j = 32; j < LBLOCKSIZE * 8; j <<= 1)
mask = (mask << j) | mask;
- aligned_addr = (unsigned long *) s;
+ aligned_addr = (const long *) s;
while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask))
aligned_addr++;
@@ -104,7 +106,7 @@ strchr (const char *s1,
contains either a null or the target char, or both. We
catch it using the bytewise search. */
- s = (unsigned char *) aligned_addr;
+ s = (const char *) aligned_addr;
#endif /* not PREFER_SIZE_OVER_SPEED */
diff --git a/newlib/libc/string/strcmp.c b/newlib/libc/string/strcmp.c
index 894424a69..0a534cfdf 100644
--- a/newlib/libc/string/strcmp.c
+++ b/newlib/libc/string/strcmp.c
@@ -34,7 +34,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
/* DETECTNULL returns nonzero if (long)X contains a NULL byte. */
#if LONG_MAX == 2147483647L
@@ -62,17 +62,17 @@ strcmp (const char *s1,
s2++;
}
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+ return (*(const unsigned char *) s1) - (*(const unsigned char *) s2);
#else
- unsigned long *a1;
- unsigned long *a2;
+ const long *a1;
+ const long *a2;
/* If s1 or s2 are unaligned, then compare bytes. */
if (!UNALIGNED (s1, s2))
{
/* If s1 and s2 are word-aligned, compare them a word at a time. */
- a1 = (unsigned long*)s1;
- a2 = (unsigned long*)s2;
+ a1 = (const long*)s1;
+ a2 = (const long*)s2;
while (*a1 == *a2)
{
/* To get here, *a1 == *a2, thus if we find a null in *a1,
@@ -85,8 +85,8 @@ strcmp (const char *s1,
}
/* A difference was detected in last few bytes of s1, so search bytewise */
- s1 = (char*)a1;
- s2 = (char*)a2;
+ s1 = (const char*)a1;
+ s2 = (const char*)a2;
}
while (*s1 != '\0' && *s1 == *s2)
@@ -94,6 +94,6 @@ strcmp (const char *s1,
s1++;
s2++;
}
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+ return (*(const unsigned char *) s1) - (*(const unsigned char *) s2);
#endif /* not PREFER_SIZE_OVER_SPEED */
}
diff --git a/newlib/libc/string/strcpy.c b/newlib/libc/string/strcpy.c
index 94e16b512..9d3792ed3 100644
--- a/newlib/libc/string/strcpy.c
+++ b/newlib/libc/string/strcpy.c
@@ -34,7 +34,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
@@ -56,10 +56,10 @@ strcpy (char *dst0,
const char *src0)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
- char *s = dst0;
+ char * const s = dst0;
- while (*dst0++ = *src0++)
- ;
+ while (*dst0 = *src0)
+ dst0++, src0++;
return s;
#else
@@ -72,7 +72,7 @@ strcpy (char *dst0,
if (!UNALIGNED (src, dst))
{
aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_src = (const long*)src;
/* SRC and DEST are both "long int" aligned, try to do "long int"
sized copies. */
@@ -82,11 +82,11 @@ strcpy (char *dst0,
}
dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ src = (const char*)aligned_src;
}
- while ((*dst++ = *src++))
- ;
+ while (*dst = *src)
+ dst++, src++;
return dst0;
#endif /* not PREFER_SIZE_OVER_SPEED */
}
diff --git a/newlib/libc/string/strcspn.c b/newlib/libc/string/strcspn.c
index abaa93ad6..89ba3eb4d 100644
--- a/newlib/libc/string/strcspn.c
+++ b/newlib/libc/string/strcspn.c
@@ -29,20 +29,19 @@ size_t
strcspn (const char *s1,
const char *s2)
{
- const char *s = s1;
+ const char *s;
const char *c;
- while (*s1)
+ for (s = s1; *s; s++)
{
for (c = s2; *c; c++)
{
- if (*s1 == *c)
+ if (*s == *c)
break;
}
if (*c)
break;
- s1++;
}
- return s1 - s;
+ return s - s1;
}
diff --git a/newlib/libc/string/strlen.c b/newlib/libc/string/strlen.c
index acffa49e1..1b7c7969d 100644
--- a/newlib/libc/string/strlen.c
+++ b/newlib/libc/string/strlen.c
@@ -54,7 +54,7 @@ strlen (const char *str)
const char *start = str;
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
- unsigned long *aligned_addr;
+ const long *aligned_addr;
/* Align the pointer, so we can search a word at a time. */
while (UNALIGNED (str))
@@ -66,17 +66,17 @@ strlen (const char *str)
/* If the string is word-aligned, we can check for the presence of
a null in each word-sized block. */
- aligned_addr = (unsigned long *)str;
+ aligned_addr = (const long *)str;
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. */
- str = (char *) aligned_addr;
+ str = (const char *) aligned_addr;
#endif /* not PREFER_SIZE_OVER_SPEED */
- while (*str)
+ while (*str != '\0')
str++;
return str - start;
}
diff --git a/newlib/libc/string/strncmp.c b/newlib/libc/string/strncmp.c
index 16f8a7729..77291aebb 100644
--- a/newlib/libc/string/strncmp.c
+++ b/newlib/libc/string/strncmp.c
@@ -34,7 +34,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((long)X | (long)Y) & (sizeof (long) - 1))
/* DETECTNULL returns nonzero if (long)X contains a NULL byte. */
#if LONG_MAX == 2147483647L
@@ -60,18 +60,18 @@ strncmp (const char *s1,
if (n == 0)
return 0;
- while (n-- != 0 && *s1 == *s2)
+ while (*s1 == *s2)
{
- if (n == 0 || *s1 == '\0')
+ if (--n == 0 || *s1 == '\0')
break;
s1++;
s2++;
}
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+ return (*(const unsigned char *) s1) - (*(const unsigned char *) s2);
#else
- unsigned long *a1;
- unsigned long *a2;
+ const long *a1;
+ const long *a2;
if (n == 0)
return 0;
@@ -80,8 +80,8 @@ strncmp (const char *s1,
if (!UNALIGNED (s1, s2))
{
/* If s1 and s2 are word-aligned, compare them a word at a time. */
- a1 = (unsigned long*)s1;
- a2 = (unsigned long*)s2;
+ a1 = (const long*)s1;
+ a2 = (const long*)s2;
while (n >= sizeof (long) && *a1 == *a2)
{
n -= sizeof (long);
@@ -96,19 +96,19 @@ strncmp (const char *s1,
}
/* A difference was detected in last few bytes of s1, so search bytewise */
- s1 = (char*)a1;
- s2 = (char*)a2;
+ s1 = (const char*)a1;
+ s2 = (const char*)a2;
}
- while (n-- > 0 && *s1 == *s2)
+ while (*s1 == *s2)
{
/* If we've run out of bytes or hit a null, return zero
since we already know *s1 == *s2. */
- if (n == 0 || *s1 == '\0')
- return 0;
+ if (--n == 0 || *s1 == '\0')
+ return 0;
s1++;
s2++;
}
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+ return (*(const unsigned char *) s1) - (*(const unsigned char *) s2);
#endif /* not PREFER_SIZE_OVER_SPEED */
}
diff --git a/newlib/libc/string/strncpy.c b/newlib/libc/string/strncpy.c
index e7eb34d72..55921b6a1 100644
--- a/newlib/libc/string/strncpy.c
+++ b/newlib/libc/string/strncpy.c
@@ -39,7 +39,7 @@ QUICKREF
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
- (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+ (((unsigned long)X | (unsigned long)Y) & (sizeof (unsigned long) - 1))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
@@ -75,7 +75,7 @@ strncpy (char *__restrict dst0,
if ((*dscan++ = *sscan++) == '\0')
break;
}
- while (count-- > 0)
+ for (; count; count--)
*dscan++ = '\0';
return dst0;
@@ -89,7 +89,7 @@ strncpy (char *__restrict dst0,
if (!UNALIGNED (src, dst) && !TOO_SMALL (count))
{
aligned_dst = (long*)dst;
- aligned_src = (long*)src;
+ aligned_src = (const long*)src;
/* SRC and DEST are both "long int" aligned, try to do "long int"
sized copies. */
@@ -100,7 +100,7 @@ strncpy (char *__restrict dst0,
}
dst = (char*)aligned_dst;
- src = (char*)aligned_src;
+ src = (const char*)aligned_src;
}
while (count > 0)
@@ -110,7 +110,7 @@ strncpy (char *__restrict dst0,
break;
}
- while (count-- > 0)
+ for (; count; count--)
*dst++ = '\0';
return dst0;
diff --git a/newlib/libc/string/strnlen.c b/newlib/libc/string/strnlen.c
index 3ee18d1c0..adc09f160 100644
--- a/newlib/libc/string/strnlen.c
+++ b/newlib/libc/string/strnlen.c
@@ -35,7 +35,7 @@ strnlen (const char *str,
{
const char *start = str;
- while (n-- > 0 && *str)
+ for (; n && *str; n--)
str++;
return str - start;
diff --git a/newlib/libc/string/strnstr.c b/newlib/libc/string/strnstr.c
index cb5f71914..b2e529a4e 100644
--- a/newlib/libc/string/strnstr.c
+++ b/newlib/libc/string/strnstr.c
@@ -40,7 +40,7 @@ QUICKREF
char *
strnstr(const char *haystack, const char *needle, size_t haystack_len)
{
- size_t needle_len = strnlen(needle, haystack_len);
+ const size_t needle_len = strnlen(needle, haystack_len);
if (needle_len < haystack_len || !needle[needle_len]) {
char *x = memmem(haystack, haystack_len, needle, needle_len);
diff --git a/newlib/libc/string/strrchr.c b/newlib/libc/string/strrchr.c
index 35a7060d2..a7e5da8b9 100644
--- a/newlib/libc/string/strrchr.c
+++ b/newlib/libc/string/strrchr.c
@@ -34,11 +34,10 @@ strrchr (const char *s,
int i)
{
const char *last = NULL;
- char c = i;
- if (c)
+ if (i & 0xff)
{
- while ((s=strchr(s, c)))
+ while ((s=strchr(s, i)))
{
last = s;
s++;
@@ -46,7 +45,7 @@ strrchr (const char *s,
}
else
{
- last = strchr(s, c);
+ last = strchr(s, i);
}
return (char *) last;
diff --git a/newlib/libc/string/strspn.c b/newlib/libc/string/strspn.c
index baf239947..553977186 100644
--- a/newlib/libc/string/strspn.c
+++ b/newlib/libc/string/strspn.c
@@ -36,7 +36,7 @@ strspn (const char *s1,
const char *s = s1;
const char *c;
- while (*s1)
+ for (s = s1; *s; s++)
{
for (c = s2; *c; c++)
{
@@ -45,8 +45,7 @@ strspn (const char *s1,
}
if (*c == '\0')
break;
- s1++;
}
- return s1 - s;
+ return s - s1;
}
diff --git a/newlib/libc/string/strstr.c b/newlib/libc/string/strstr.c
index 84e4632f1..9afbc1fa1 100644
--- a/newlib/libc/string/strstr.c
+++ b/newlib/libc/string/strstr.c
@@ -67,7 +67,7 @@ char *
strstr (const char *hs, const char *ne)
{
size_t i;
- int c = ne[0];
+ char c = ne[0];
if (c == 0)
return (char*)hs;
@@ -143,24 +143,22 @@ strstr4 (const unsigned char *hs, const unsigned char *ne)
char *
strstr (const char *haystack, const char *needle)
{
- const unsigned char *hs = (const unsigned char *) haystack;
- const unsigned char *ne = (const unsigned char *) needle;
- int i;
+ size_t i;
/* Handle short needle special cases first. */
- if (ne[0] == '\0')
- return (char *) hs;
- if (ne[1] == '\0')
- return (char*)strchr ((const char *) hs, ne[0]);
- if (ne[2] == '\0')
- return strstr2 (hs, ne);
- if (ne[3] == '\0')
- return strstr3 (hs, ne);
- if (ne[4] == '\0')
- return strstr4 (hs, ne);
-
- size_t ne_len = strlen ((const char *) ne);
- size_t hs_len = strnlen ((const char *) hs, ne_len | 512);
+ if (needle[0] == '\0')
+ return haystack;
+ if (needle[1] == '\0')
+ return (char*)strchr (haystack, needle[0]);
+ if (needle[2] == '\0')
+ return strstr2 (haystack, needle);
+ if (needle[3] == '\0')
+ return strstr3 (haystack, needle);
+ if (needle[4] == '\0')
+ return strstr4 (haystack, needle);
+
+ size_t ne_len = strlen (haystack);
+ size_t hs_len = strnlen (needle, ne_len | 512);
/* Ensure haystack length is >= needle length. */
if (hs_len < ne_len)
@@ -170,35 +168,35 @@ strstr (const char *haystack, const char *needle)
if (__builtin_expect (ne_len < 255, 1))
{
uint8_t shift[1 << SHIFT_TABLE_BITS];
- const unsigned char *end = hs + hs_len - ne_len;
+ const char *end = haystack + hs_len - ne_len;
/* Initialize bad character shift hash table. */
memset (shift, ne_len + 1, sizeof (shift));
for (i = 0; i < ne_len; i++)
- shift[ne[i] % sizeof (shift)] = ne_len - i;
+ shift[needle[i] % sizeof (shift)] = ne_len - i;
do
{
- hs--;
+ haystack--;
/* Search by skipping past bad characters. */
- size_t tmp = shift[hs[ne_len] % sizeof (shift)];
- for (hs += tmp; hs <= end; hs += tmp)
+ size_t tmp = shift[haystack[ne_len] % sizeof (shift)];
+ for (haystack += tmp; haystack <= end; haystack += tmp)
{
- tmp = shift[hs[ne_len] % sizeof (shift)];
- if (memcmp (hs, ne, ne_len) == 0)
- return (char*) hs;
+ tmp = shift[haystack[ne_len] % sizeof (shift)];
+ if (memcmp (haystack, needle, ne_len) == 0)
+ return (char*) haystack;
}
if (end[ne_len] == 0)
return NULL;
end += strnlen ((const char *) (end + ne_len), 2048);
}
- while (hs <= end);
+ while (haystack <= end);
return NULL;
}
/* Use Two-Way algorithm for very long needles. */
- return two_way_long_needle (hs, hs_len, ne, ne_len);
+ return two_way_long_needle (haystack, hs_len, needle, ne_len);
}
#endif /* compilation for speed */
diff --git a/newlib/libc/string/strxfrm.c b/newlib/libc/string/strxfrm.c
index c5df0bcd5..537981586 100644
--- a/newlib/libc/string/strxfrm.c
+++ b/newlib/libc/string/strxfrm.c
@@ -50,14 +50,12 @@ strxfrm (char *__restrict s1,
const char *__restrict s2,
size_t n)
{
- size_t res;
- res = 0;
- while (n-- > 0)
+ size_t res = 0;
+ for (; n; n--)
{
- if ((*s1++ = *s2++) != '\0')
- ++res;
- else
- return res;
+ if ((*s1++ = *s2++) == '\0')
+ return res;
+ ++res;
}
while (*s2)
{
diff --git a/newlib/libc/string/swab.c b/newlib/libc/string/swab.c
index 28ab978bd..01910dc53 100644
--- a/newlib/libc/string/swab.c
+++ b/newlib/libc/string/swab.c
@@ -22,13 +22,13 @@ swab (const void *b1,
void *b2,
ssize_t length)
{
- const char *from = b1;
- char *to = b2;
+ const unsigned char *from = b1;
+ unsigned char *to = b2;
ssize_t ptr;
for (ptr = 1; ptr < length; ptr += 2)
{
- char p = from[ptr];
- char q = from[ptr-1];
+ unsigned char p = from[ptr];
+ unsigned char q = from[ptr-1];
to[ptr-1] = p;
to[ptr ] = q;
}
-- 
2.37.1

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-08-16 11:08 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-12 21:09 [PATCH] newlib: libc: Optimize the string functions Seija Kijin
  -- strict thread matches above, loose matches on Subject: below --
2022-08-12 21:11 Seija Kijin
2022-08-16 11:08 ` Corinna Vinschen
2022-08-12 20:38 Seija Kijin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).