Fix handling of tail bytes of buffer in SSE2/SSSE3 x86-64 version strn{,case}cmp
[platform/upstream/glibc.git] / string / strlen.c
1 /* Copyright (C) 1991,1993,1997,2000,2003,2009 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Written by Torbjorn Granlund (tege@sics.se),
4    with help from Dan Sahlin (dan@sics.se);
5    commentary by Jim Blandy (jimb@ai.mit.edu).
6
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
11
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, write to the Free
19    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20    02111-1307 USA.  */
21
22 #include <string.h>
23 #include <stdlib.h>
24
25 #undef strlen
26
27 /* Return the length of the null-terminated string STR.  Scan for
28    the null terminator quickly by testing four bytes at a time.  */
29 size_t
30 strlen (str)
31      const char *str;
32 {
33   const char *char_ptr;
34   const unsigned long int *longword_ptr;
35   unsigned long int longword, himagic, lomagic;
36
37   /* Handle the first few characters by reading one character at a time.
38      Do this until CHAR_PTR is aligned on a longword boundary.  */
39   for (char_ptr = str; ((unsigned long int) char_ptr
40                         & (sizeof (longword) - 1)) != 0;
41        ++char_ptr)
42     if (*char_ptr == '\0')
43       return char_ptr - str;
44
45   /* All these elucidatory comments refer to 4-byte longwords,
46      but the theory applies equally well to 8-byte longwords.  */
47
48   longword_ptr = (unsigned long int *) char_ptr;
49
50   /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
51      the "holes."  Note that there is a hole just to the left of
52      each byte, with an extra at the end:
53
54      bits:  01111110 11111110 11111110 11111111
55      bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
56
57      The 1-bits make sure that carries propagate to the next 0-bit.
58      The 0-bits provide holes for carries to fall into.  */
59   himagic = 0x80808080L;
60   lomagic = 0x01010101L;
61   if (sizeof (longword) > 4)
62     {
63       /* 64-bit version of the magic.  */
64       /* Do the shift in two steps to avoid a warning if long has 32 bits.  */
65       himagic = ((himagic << 16) << 16) | himagic;
66       lomagic = ((lomagic << 16) << 16) | lomagic;
67     }
68   if (sizeof (longword) > 8)
69     abort ();
70
71   /* Instead of the traditional loop which tests each character,
72      we will test a longword at a time.  The tricky part is testing
73      if *any of the four* bytes in the longword in question are zero.  */
74   for (;;)
75     {
76       longword = *longword_ptr++;
77
78       if (((longword - lomagic) & ~longword & himagic) != 0)
79         {
80           /* Which of the bytes was the zero?  If none of them were, it was
81              a misfire; continue the search.  */
82
83           const char *cp = (const char *) (longword_ptr - 1);
84
85           if (cp[0] == 0)
86             return cp - str;
87           if (cp[1] == 0)
88             return cp - str + 1;
89           if (cp[2] == 0)
90             return cp - str + 2;
91           if (cp[3] == 0)
92             return cp - str + 3;
93           if (sizeof (longword) > 4)
94             {
95               if (cp[4] == 0)
96                 return cp - str + 4;
97               if (cp[5] == 0)
98                 return cp - str + 5;
99               if (cp[6] == 0)
100                 return cp - str + 6;
101               if (cp[7] == 0)
102                 return cp - str + 7;
103             }
104         }
105     }
106 }
107 libc_hidden_builtin_def (strlen)