This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Generic strlen
- From: Gregory Pietsch <gpietsch at comcast dot net>
- To: newlib at sourceware dot org
- Date: Fri, 29 Oct 2010 21:22:35 -0400
- Subject: Generic strlen
To settle this issue, here's a new strlen for y'all to gander at:
#include<string.h>
#include<limits.h>
/* Nonzero if X is not aligned on a "long" boundary. */
#define UNALIGNED(X) ((long)X& (sizeof (long) - 1))
/* How many bytes are loaded each iteration of the word copy loop. */
#define LBLOCKSIZE (sizeof (long))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101)& ~(X)& 0x80808080)
#else
#if LONG_MAX == 9223372036854775807L
/* Nonzero if X (a long int) contains a NULL byte. */
#define DETECTNULL(X) (((X) - 0x0101010101010101)& ~(X)& 0x8080808080808080)
#else
#error long int is not a 32bit or 64bit type.
#endif
#endif
size_t
_DEFUN (strlen, (s),
_CONST char *s)
{
size_t n = 0;
#if !defined(PREFER_SIZE_OVER_SPEED)&& !defined(__OPTIMIZE_SIZE__)
unsigned long *aligned_addr;
/* Special case for finding 0. */
while (UNALIGNED (s))
{
if (*s == '\0')
return n;
++s;
++n;
}
/* Operate a word at a time. */
aligned_addr = (unsigned long *) s;
while (!DETECTNULL (*aligned_addr))
{
++aligned_addr;
n += sizeof (unsigned long);
}
/* Found the end of string. */
s = (const char *) aligned_addr;
/* The block of bytes currently pointed to by aligned_addr
contains a null. We catch it using the bytewise search. */
#endif /* not PREFER_SIZE_OVER_SPEED */
while (*s != '\0')
{
++s;
++n;
}
return n;
}
/* END OF FILE */