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