mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-21 01:12:26 +08:00
c0efbf8920
Copyright The GNU Toolchain Authors. The comments on strlen() don't match what the actual code does. They describe an older algorithm which is no longer in use. This change replace the old comments with new ones describing the algorithm used. I am a first time contributor, and I believe there is no need for copyright assignment, since the file changed is not in the shared source files list. This patch only changes comments, but for safety I have run the tests in my x64 ubuntu machine, with the following results: Summary of test results: 5051 PASS 80 UNSUPPORTED 16 XFAIL 6 XPASS Signed-off-by: Ricardo Bittencourt <bluepenguin@gmail.com>
101 lines
3.1 KiB
C
101 lines
3.1 KiB
C
/* Copyright (C) 1991-2022 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, see
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#undef strlen
|
|
|
|
#ifndef STRLEN
|
|
# define STRLEN strlen
|
|
#endif
|
|
|
|
/* Return the length of the null-terminated string STR. Scan for
|
|
the null terminator quickly by testing four bytes at a time. */
|
|
size_t
|
|
STRLEN (const char *str)
|
|
{
|
|
const char *char_ptr;
|
|
const unsigned long int *longword_ptr;
|
|
unsigned long int longword, himagic, lomagic;
|
|
|
|
/* Handle the first few characters by reading one character at a time.
|
|
Do this until CHAR_PTR is aligned on a longword boundary. */
|
|
for (char_ptr = str; ((unsigned long int) char_ptr
|
|
& (sizeof (longword) - 1)) != 0;
|
|
++char_ptr)
|
|
if (*char_ptr == '\0')
|
|
return char_ptr - str;
|
|
|
|
/* All these elucidatory comments refer to 4-byte longwords,
|
|
but the theory applies equally well to 8-byte longwords. */
|
|
|
|
longword_ptr = (unsigned long int *) char_ptr;
|
|
|
|
/* Computing (longword - lomagic) sets the high bit of any corresponding
|
|
byte that is either zero or greater than 0x80. The latter case can be
|
|
filtered out by computing (~longword & himagic). The final result
|
|
will always be non-zero if one of the bytes of longword is zero. */
|
|
himagic = 0x80808080L;
|
|
lomagic = 0x01010101L;
|
|
if (sizeof (longword) > 4)
|
|
{
|
|
/* 64-bit version of the magic. */
|
|
/* Do the shift in two steps to avoid a warning if long has 32 bits. */
|
|
himagic = ((himagic << 16) << 16) | himagic;
|
|
lomagic = ((lomagic << 16) << 16) | lomagic;
|
|
}
|
|
if (sizeof (longword) > 8)
|
|
abort ();
|
|
|
|
/* Instead of the traditional loop which tests each character,
|
|
we will test a longword at a time. The tricky part is testing
|
|
if *any of the four* bytes in the longword in question are zero. */
|
|
for (;;)
|
|
{
|
|
longword = *longword_ptr++;
|
|
|
|
if (((longword - lomagic) & ~longword & himagic) != 0)
|
|
{
|
|
/* Which of the bytes was the zero? */
|
|
|
|
const char *cp = (const char *) (longword_ptr - 1);
|
|
|
|
if (cp[0] == 0)
|
|
return cp - str;
|
|
if (cp[1] == 0)
|
|
return cp - str + 1;
|
|
if (cp[2] == 0)
|
|
return cp - str + 2;
|
|
if (cp[3] == 0)
|
|
return cp - str + 3;
|
|
if (sizeof (longword) > 4)
|
|
{
|
|
if (cp[4] == 0)
|
|
return cp - str + 4;
|
|
if (cp[5] == 0)
|
|
return cp - str + 5;
|
|
if (cp[6] == 0)
|
|
return cp - str + 6;
|
|
if (cp[7] == 0)
|
|
return cp - str + 7;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
libc_hidden_builtin_def (strlen)
|