UbixOS  2.0
strlen.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2002-2018 The UbixOS Project.
3  * All rights reserved.
4  *
5  * This was developed by Christopher W. Olsen for the UbixOS Project.
6  *
7  * Redistribution and use in source and binary forms, with or without modification, are permitted
8  * provided that the following conditions are met:
9  *
10  * 1) Redistributions of source code must retain the above copyright notice, this list of
11  * conditions, the following disclaimer and the list of authors.
12  * 2) Redistributions in binary form must reproduce the above copyright notice, this list of
13  * conditions, the following disclaimer and the list of authors in the documentation and/or
14  * other materials provided with the distribution.
15  * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to
16  * endorse or promote products derived from this software without specific prior written
17  * permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/limits.h>
30 #include <sys/types.h>
31 
32 /* Magic numbers for the algorithm */
33 #if LONG_BIT == 32
34 static const unsigned long mask01 = 0x01010101;
35 static const unsigned long mask80 = 0x80808080;
36 #elif LONG_BIT == 64
37 static const unsigned long mask01 = 0x0101010101010101;
38 static const unsigned long mask80 = 0x8080808080808080;
39 #else
40 #error Unsupported word size
41 #endif
42 
43 #define LONGPTR_MASK (sizeof(long) - 1)
44 
45 /*
46  * Helper macro to return string length if we caught the zero
47  * byte.
48  */
49 #define testbyte(x) \
50  do { \
51  if (p[x] == '\0') \
52  return (p - str + x); \
53  } while (0)
54 
55 size_t strlen(const char *str) {
56  const char *p;
57  const unsigned long *lp;
58  long va, vb;
59 
60  /*
61  * Before trying the hard (unaligned byte-by-byte access) way
62  * to figure out whether there is a nul character, try to see
63  * if there is a nul character is within this accessible word
64  * first.
65  *
66  * p and (p & ~LONGPTR_MASK) must be equally accessible since
67  * they always fall in the same memory page, as long as page
68  * boundaries is integral multiple of word size.
69  */
70  lp = (const unsigned long *) ((uintptr_t) str & ~LONGPTR_MASK);
71  va = (*lp - mask01);
72  vb = ((~*lp) & mask80);
73  lp++;
74  if (va & vb)
75  /* Check if we have \0 in the first part */
76  for (p = str; p < (const char *) lp; p++)
77  if (*p == '\0')
78  return (p - str);
79 
80  /* Scan the rest of the string using word sized operation */
81  for (;; lp++) {
82  va = (*lp - mask01);
83  vb = ((~*lp) & mask80);
84  if (va & vb) {
85  p = (const char *) (lp);
86  testbyte(0);
87  testbyte(1);
88  testbyte(2);
89  testbyte(3);
90 #if (LONG_BIT >= 64)
91  testbyte(4);
92  testbyte(5);
93  testbyte(6);
94  testbyte(7);
95 #endif
96  }
97  }
98 
99  /* NOTREACHED */
100  return (0);
101 }
limits.h
types.h
LONGPTR_MASK
#define LONGPTR_MASK
Definition: strlen.c:43
strlen
size_t strlen(const char *str)
Definition: strlen.c:55
testbyte
#define testbyte(x)
Definition: strlen.c:49
uintptr_t
uint32_t uintptr_t
Definition: types.h:136