Cygwin: access: Fix X_OK behaviour for backup operators and admins
[newlib-cygwin.git] / newlib / libc / machine / riscv / strlen.c
blob3b04066992725ed1d36377cd0219c103f9e34a23
1 /* Copyright (c) 2017 SiFive Inc. All rights reserved.
3 This copyrighted material is made available to anyone wishing to use,
4 modify, copy, or redistribute it subject to the terms and conditions
5 of the FreeBSD License. This program is distributed in the hope that
6 it will be useful, but WITHOUT ANY WARRANTY expressed or implied,
7 including the implied warranties of MERCHANTABILITY or FITNESS FOR
8 A PARTICULAR PURPOSE. A copy of this license is available at
9 http://www.opensource.org/licenses.
12 #include <string.h>
13 #include <stdint.h>
15 size_t strlen(const char *str)
17 const char *start = str;
19 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
20 while (*str++)
22 return str - start - 1;
23 #else
24 if (__builtin_expect ((uintptr_t)str & (sizeof (long) - 1), 0)) do
26 char ch = *str;
27 str++;
28 if (!ch)
29 return str - start - 1;
30 } while ((uintptr_t)str & (sizeof (long) - 1));
32 unsigned long *ls = (unsigned long *)str;
33 while (!__libc_detect_null (*ls++))
35 asm volatile ("" : "+r"(ls)); /* prevent "optimization" */
37 str = (const char *)ls;
38 size_t ret = str - start, sl = sizeof (long);
40 char c0 = str[0 - sl], c1 = str[1 - sl], c2 = str[2 - sl], c3 = str[3 - sl];
41 if (c0 == 0) return ret + 0 - sl;
42 if (c1 == 0) return ret + 1 - sl;
43 if (c2 == 0) return ret + 2 - sl;
44 if (sl == 4 || c3 == 0) return ret + 3 - sl;
46 c0 = str[4 - sl], c1 = str[5 - sl], c2 = str[6 - sl], c3 = str[7 - sl];
47 if (c0 == 0) return ret + 4 - sl;
48 if (c1 == 0) return ret + 5 - sl;
49 if (c2 == 0) return ret + 6 - sl;
51 return ret + 7 - sl;
52 #endif /* not PREFER_SIZE_OVER_SPEED */