Generic strlen

Gregory Pietsch gpietsch@comcast.net
Tue Nov 2 08:03:00 GMT 2010


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 */




More information about the Newlib mailing list