source: trunk/libs/newlib/src/newlib/libc/string/strchr.c @ 567

Last change on this file since 567 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 2.7 KB
Line 
1/*
2FUNCTION
3        <<strchr>>---search for character in string
4
5INDEX
6        strchr
7
8SYNOPSIS
9        #include <string.h>
10        char * strchr(const char *<[string]>, int <[c]>);
11
12DESCRIPTION
13        This function finds the first occurence of <[c]> (converted to
14        a char) in the string pointed to by <[string]> (including the
15        terminating null character).
16
17RETURNS
18        Returns a pointer to the located character, or a null pointer
19        if <[c]> does not occur in <[string]>.
20
21PORTABILITY
22<<strchr>> is ANSI C.
23
24<<strchr>> requires no supporting OS subroutines.
25
26QUICKREF
27        strchr ansi pure
28*/
29
30#include <string.h>
31#include <limits.h>
32
33/* Nonzero if X is not aligned on a "long" boundary.  */
34#define UNALIGNED(X) ((long)X & (sizeof (long) - 1))
35
36/* How many bytes are loaded each iteration of the word copy loop.  */
37#define LBLOCKSIZE (sizeof (long))
38
39#if LONG_MAX == 2147483647L
40#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
41#else
42#if LONG_MAX == 9223372036854775807L
43/* Nonzero if X (a long int) contains a NULL byte. */
44#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
45#else
46#error long int is not a 32bit or 64bit type.
47#endif
48#endif
49
50/* DETECTCHAR returns nonzero if (long)X contains the byte used
51   to fill (long)MASK. */
52#define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK))
53
54char *
55strchr (const char *s1,
56        int i)
57{
58  const unsigned char *s = (const unsigned char *)s1;
59  unsigned char c = i;
60
61#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
62  unsigned long mask,j;
63  unsigned long *aligned_addr;
64
65  /* Special case for finding 0.  */
66  if (!c)
67    {
68      while (UNALIGNED (s))
69        {
70          if (!*s)
71            return (char *) s;
72          s++;
73        }
74      /* Operate a word at a time.  */
75      aligned_addr = (unsigned long *) s;
76      while (!DETECTNULL (*aligned_addr))
77        aligned_addr++;
78      /* Found the end of string.  */
79      s = (const unsigned char *) aligned_addr;
80      while (*s)
81        s++;
82      return (char *) s;
83    }
84
85  /* All other bytes.  Align the pointer, then search a long at a time.  */
86  while (UNALIGNED (s))
87    {
88      if (!*s)
89        return NULL;
90      if (*s == c)
91        return (char *) s;
92      s++;
93    }
94
95  mask = c;
96  for (j = 8; j < LBLOCKSIZE * 8; j <<= 1)
97    mask = (mask << j) | mask;
98
99  aligned_addr = (unsigned long *) s;
100  while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask))
101    aligned_addr++;
102
103  /* The block of bytes currently pointed to by aligned_addr
104     contains either a null or the target char, or both.  We
105     catch it using the bytewise search.  */
106
107  s = (unsigned char *) aligned_addr;
108
109#endif /* not PREFER_SIZE_OVER_SPEED */
110
111  while (*s && *s != c)
112    s++;
113  if (*s == c)
114    return (char *)s;
115  return NULL;
116}
Note: See TracBrowser for help on using the repository browser.