Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1693 | serge | 1 | /* |
2 | FUNCTION |
||
3 | < |
||
4 | |||
5 | INDEX |
||
6 | memchr |
||
7 | |||
8 | ANSI_SYNOPSIS |
||
9 | #include |
||
10 | void *memchr(const void *<[src]>, int <[c]>, size_t <[length]>); |
||
11 | |||
12 | TRAD_SYNOPSIS |
||
13 | #include |
||
14 | void *memchr(<[src]>, <[c]>, <[length]>) |
||
15 | void *<[src]>; |
||
16 | void *<[c]>; |
||
17 | size_t <[length]>; |
||
18 | |||
19 | DESCRIPTION |
||
20 | This function searches memory starting at <<*<[src]>>> for the |
||
21 | character <[c]>. The search only ends with the first |
||
22 | occurrence of <[c]>, or after <[length]> characters; in |
||
23 | particular, < |
||
24 | |||
25 | RETURNS |
||
26 | If the character <[c]> is found within <[length]> characters |
||
27 | of <<*<[src]>>>, a pointer to the character is returned. If |
||
28 | <[c]> is not found, then < |
||
29 | |||
30 | PORTABILITY |
||
31 | < |
||
32 | |||
33 | < |
||
34 | |||
35 | QUICKREF |
||
36 | memchr ansi pure |
||
37 | */ |
||
38 | |||
39 | #include <_ansi.h> |
||
40 | #include |
||
41 | #include |
||
42 | |||
43 | /* Nonzero if either X or Y is not aligned on a "long" boundary. */ |
||
44 | #define UNALIGNED(X) ((long)X & (sizeof (long) - 1)) |
||
45 | |||
46 | /* How many bytes are loaded each iteration of the word copy loop. */ |
||
47 | #define LBLOCKSIZE (sizeof (long)) |
||
48 | |||
49 | /* Threshhold for punting to the bytewise iterator. */ |
||
50 | #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) |
||
51 | |||
52 | #if LONG_MAX == 2147483647L |
||
53 | #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) |
||
54 | #else |
||
55 | #if LONG_MAX == 9223372036854775807L |
||
56 | /* Nonzero if X (a long int) contains a NULL byte. */ |
||
57 | #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) |
||
58 | #else |
||
59 | #error long int is not a 32bit or 64bit type. |
||
60 | #endif |
||
61 | #endif |
||
62 | |||
63 | #ifndef DETECTNULL |
||
64 | #error long int is not a 32bit or 64bit byte |
||
65 | #endif |
||
66 | |||
67 | /* DETECTCHAR returns nonzero if (long)X contains the byte used |
||
68 | to fill (long)MASK. */ |
||
69 | #define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK)) |
||
70 | |||
71 | _PTR |
||
72 | _DEFUN (memchr, (src_void, c, length), |
||
73 | _CONST _PTR src_void _AND |
||
74 | int c _AND |
||
75 | size_t length) |
||
76 | { |
||
77 | _CONST unsigned char *src = (_CONST unsigned char *) src_void; |
||
78 | unsigned char d = c; |
||
79 | |||
80 | #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) |
||
81 | unsigned long *asrc; |
||
82 | unsigned long mask; |
||
83 | int i; |
||
84 | |||
85 | while (UNALIGNED (src)) |
||
86 | { |
||
87 | if (!length--) |
||
88 | return NULL; |
||
89 | if (*src == d) |
||
90 | return (void *) src; |
||
91 | src++; |
||
92 | } |
||
93 | |||
94 | if (!TOO_SMALL (length)) |
||
95 | { |
||
96 | /* If we get this far, we know that length is large and src is |
||
97 | word-aligned. */ |
||
98 | /* The fast code reads the source one word at a time and only |
||
99 | performs the bytewise search on word-sized segments if they |
||
100 | contain the search character, which is detected by XORing |
||
101 | the word-sized segment with a word-sized block of the search |
||
102 | character and then detecting for the presence of NUL in the |
||
103 | result. */ |
||
104 | asrc = (unsigned long *) src; |
||
105 | mask = d << 8 | d; |
||
106 | mask = mask << 16 | mask; |
||
107 | for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) |
||
108 | mask = (mask << i) | mask; |
||
109 | |||
110 | while (length >= LBLOCKSIZE) |
||
111 | { |
||
112 | if (DETECTCHAR (*asrc, mask)) |
||
113 | break; |
||
114 | length -= LBLOCKSIZE; |
||
115 | asrc++; |
||
116 | } |
||
117 | |||
118 | /* If there are fewer than LBLOCKSIZE characters left, |
||
119 | then we resort to the bytewise loop. */ |
||
120 | |||
121 | src = (unsigned char *) asrc; |
||
122 | } |
||
123 | |||
124 | #endif /* not PREFER_SIZE_OVER_SPEED */ |
||
125 | |||
126 | while (length--) |
||
127 | { |
||
128 | if (*src == d) |
||
129 | return (void *) src; |
||
130 | src++; |
||
131 | } |
||
132 | |||
133 | return NULL; |
||
134 | }><>=><=>>><>><>> |