1 /* 2 Copyright (c) 1994 Cygnus Support. 3 All rights reserved. 4 5 Redistribution and use in source and binary forms are permitted 6 provided that the above copyright notice and this paragraph are 7 duplicated in all such forms and that any documentation, 8 and/or other materials related to such 9 distribution and use acknowledge that the software was developed 10 at Cygnus Support, Inc. Cygnus Support, Inc. may not be used to 11 endorse or promote products derived from this software without 12 specific prior written permission. 13 THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 /* 18 FUNCTION 19 <<strlen>>---character string length 20 21 INDEX 22 strlen 23 24 SYNOPSIS 25 #include <string.h> 26 size_t strlen(const char *<[str]>); 27 28 DESCRIPTION 29 The <<strlen>> function works out the length of the string 30 starting at <<*<[str]>>> by counting chararacters until it 31 reaches a <<NULL>> character. 32 33 RETURNS 34 <<strlen>> returns the character count. 35 36 PORTABILITY 37 <<strlen>> is ANSI C. 38 39 <<strlen>> requires no supporting OS subroutines. 40 41 QUICKREF 42 strlen ansi pure 43 */ 44 45 #include <_ansi.h> 46 #include <string.h> 47 #include <limits.h> 48 #include <stdint.h> 49 50 #define LBLOCKSIZE (sizeof (long)) 51 #define UNALIGNED(X) ((uintptr_t)X & (LBLOCKSIZE - 1)) 52 53 #if LONG_MAX == 2147483647L 54 #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) 55 #else 56 #if LONG_MAX == 9223372036854775807L 57 /* Nonzero if X (a long int) contains a NULL byte. */ 58 #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) 59 #else 60 #error long int is not a 32bit or 64bit type. 61 #endif 62 #endif 63 64 #ifndef DETECTNULL 65 #error long int is not a 32bit or 64bit byte 66 #endif 67 68 size_t strlen(const char * str)69strlen (const char *str) 70 { 71 const char *start = str; 72 73 #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) && \ 74 !defined(PICOLIBC_NO_OUT_OF_BOUNDS_READS) 75 unsigned long *aligned_addr; 76 77 /* Align the pointer, so we can search a word at a time. */ 78 while (UNALIGNED (str)) 79 { 80 if (!*str) 81 return str - start; 82 str++; 83 } 84 85 /* If the string is word-aligned, we can check for the presence of 86 a null in each word-sized block. */ 87 aligned_addr = (unsigned long *)str; 88 while (!DETECTNULL (*aligned_addr)) 89 aligned_addr++; 90 91 /* Once a null is detected, we check each byte in that block for a 92 precise position of the null. */ 93 str = (char *) aligned_addr; 94 95 #endif /* not PREFER_SIZE_OVER_SPEED */ 96 97 while (*str) 98 str++; 99 return str - start; 100 } 101