1 #ifndef __V4L_GETSUBOPT__
2 #define __V4L_GETSUBOPT__
3
4 /*
5 * Apparently non-glibc variants of getsubopt behave slightly
6 * differently, and on some OSes (Android) it is missing altogether.
7 * So add support for it here, if needed.
8 */
9
10 #if defined(__GLIBC__)
11
12 #define v4l_getsubopt getsubopt
13
14 #else
15
16 /*
17 * Import strchrnul(...) from uClibc version 0.9.33.2 since this feature is
18 * missing in the Android C library.
19 */
20
21 /* Copyright (C) 1991,93,94,95,96,97,99,2000 Free Software Foundation, Inc.
22 This file is part of the GNU C Library.
23 Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
24 with help from Dan Sahlin (dan@sics.se) and
25 bug fix and commentary by Jim Blandy (jimb@ai.mit.edu);
26 adaptation to strchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
27 and implemented by Roland McGrath (roland@ai.mit.edu).
28
29 The GNU C Library is free software; you can redistribute it and/or
30 modify it under the terms of the GNU Lesser General Public
31 License as published by the Free Software Foundation; either
32 version 2.1 of the License, or (at your option) any later version.
33
34 The GNU C Library is distributed in the hope that it will be useful,
35 but WITHOUT ANY WARRANTY; without even the implied warranty of
36 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
37 Lesser General Public License for more details.
38
39 You should have received a copy of the GNU Lesser General Public
40 License along with the GNU C Library; if not, write to the Free
41 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
42 02111-1307 USA. */
43
44 #include <string.h>
45 #include <stdlib.h>
46
47 /* Find the first occurrence of C in S or the final NUL byte. */
v4l_strchrnul(const char * s,int c_in)48 static inline char *v4l_strchrnul (const char *s, int c_in)
49 {
50 const unsigned char *char_ptr;
51 const unsigned long int *longword_ptr;
52 unsigned long int longword, magic_bits, charmask;
53 unsigned char c;
54
55 c = (unsigned char) c_in;
56
57 /* Handle the first few characters by reading one character at a time.
58 Do this until CHAR_PTR is aligned on a longword boundary. */
59 for (char_ptr = (const unsigned char *) s;
60 ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0;
61 ++char_ptr)
62 if (*char_ptr == c || *char_ptr == '\0')
63 return (char *) char_ptr;
64
65 /* All these elucidatory comments refer to 4-byte longwords,
66 but the theory applies equally well to 8-byte longwords. */
67
68 longword_ptr = (unsigned long int *) char_ptr;
69
70 /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits
71 the "holes." Note that there is a hole just to the left of
72 each byte, with an extra at the end:
73
74 bits: 01111110 11111110 11111110 11111111
75 bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
76
77 The 1-bits make sure that carries propagate to the next 0-bit.
78 The 0-bits provide holes for carries to fall into. */
79 switch (sizeof (longword))
80 {
81 case 4: magic_bits = 0x7efefeffL; break;
82 case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break;
83 default:
84 abort ();
85 }
86
87 /* Set up a longword, each of whose bytes is C. */
88 charmask = c | (c << 8);
89 charmask |= charmask << 16;
90 if (sizeof (longword) > 4)
91 /* Do the shift in two steps to avoid a warning if long has 32 bits. */
92 charmask |= (charmask << 16) << 16;
93 if (sizeof (longword) > 8)
94 abort ();
95
96 /* Instead of the traditional loop which tests each character,
97 we will test a longword at a time. The tricky part is testing
98 if *any of the four* bytes in the longword in question are zero. */
99 for (;;)
100 {
101 /* We tentatively exit the loop if adding MAGIC_BITS to
102 LONGWORD fails to change any of the hole bits of LONGWORD.
103
104 1) Is this safe? Will it catch all the zero bytes?
105 Suppose there is a byte with all zeros. Any carry bits
106 propagating from its left will fall into the hole at its
107 least significant bit and stop. Since there will be no
108 carry from its most significant bit, the LSB of the
109 byte to the left will be unchanged, and the zero will be
110 detected.
111
112 2) Is this worthwhile? Will it ignore everything except
113 zero bytes? Suppose every byte of LONGWORD has a bit set
114 somewhere. There will be a carry into bit 8. If bit 8
115 is set, this will carry into bit 16. If bit 8 is clear,
116 one of bits 9-15 must be set, so there will be a carry
117 into bit 16. Similarly, there will be a carry into bit
118 24. If one of bits 24-30 is set, there will be a carry
119 into bit 31, so all of the hole bits will be changed.
120
121 The one misfire occurs when bits 24-30 are clear and bit
122 31 is set; in this case, the hole at bit 31 is not
123 changed. If we had access to the processor carry flag,
124 we could close this loophole by putting the fourth hole
125 at bit 32!
126
127 So it ignores everything except 128's, when they're aligned
128 properly.
129
130 3) But wait! Aren't we looking for C as well as zero?
131 Good point. So what we do is XOR LONGWORD with a longword,
132 each of whose bytes is C. This turns each byte that is C
133 into a zero. */
134
135 longword = *longword_ptr++;
136
137 /* Add MAGIC_BITS to LONGWORD. */
138 if ((((longword + magic_bits)
139
140 /* Set those bits that were unchanged by the addition. */
141 ^ ~longword)
142
143 /* Look at only the hole bits. If any of the hole bits
144 are unchanged, most likely one of the bytes was a
145 zero. */
146 & ~magic_bits) != 0 ||
147
148 /* That caught zeroes. Now test for C. */
149 ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask))
150 & ~magic_bits) != 0)
151 {
152 /* Which of the bytes was C or zero?
153 If none of them were, it was a misfire; continue the search. */
154
155 const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
156
157 if (*cp == c || *cp == '\0')
158 return (char *) cp;
159 if (*++cp == c || *cp == '\0')
160 return (char *) cp;
161 if (*++cp == c || *cp == '\0')
162 return (char *) cp;
163 if (*++cp == c || *cp == '\0')
164 return (char *) cp;
165 if (sizeof (longword) > 4)
166 {
167 if (*++cp == c || *cp == '\0')
168 return (char *) cp;
169 if (*++cp == c || *cp == '\0')
170 return (char *) cp;
171 if (*++cp == c || *cp == '\0')
172 return (char *) cp;
173 if (*++cp == c || *cp == '\0')
174 return (char *) cp;
175 }
176 }
177 }
178
179 /* This should never happen. */
180 return NULL;
181 }
182
183 /*
184 * Import getsubopt(...) from uClibc version 0.9.33.2 since this feature is
185 * missing in the Android C library.
186 */
187
188 /* Parse comma separate list into words.
189 Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc.
190 This file is part of the GNU C Library.
191 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
192
193 The GNU C Library is free software; you can redistribute it and/or
194 modify it under the terms of the GNU Lesser General Public
195 License as published by the Free Software Foundation; either
196 version 2.1 of the License, or (at your option) any later version.
197
198 The GNU C Library is distributed in the hope that it will be useful,
199 but WITHOUT ANY WARRANTY; without even the implied warranty of
200 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
201 Lesser General Public License for more details.
202
203 You should have received a copy of the GNU Lesser General Public
204 License along with the GNU C Library; if not, write to the Free
205 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
206 02111-1307 USA. */
207
208 /* Parse comma separated suboption from *OPTIONP and match against
209 strings in TOKENS. If found return index and set *VALUEP to
210 optional value introduced by an equal sign. If the suboption is
211 not part of TOKENS return in *VALUEP beginning of unknown
212 suboption. On exit *OPTIONP is set to the beginning of the next
213 token or at the terminating NUL character. */
214 static inline int
v4l_getsubopt(char ** optionp,char * const * tokens,char ** valuep)215 v4l_getsubopt (char **optionp, char *const *tokens, char **valuep)
216 {
217 char *endp, *vstart;
218 int cnt;
219
220 if (**optionp == '\0')
221 return -1;
222
223 /* Find end of next token. */
224 endp = v4l_strchrnul (*optionp, ',');
225
226 /* Find start of value. */
227 vstart = (char *) memchr (*optionp, '=', endp - *optionp);
228 if (vstart == NULL)
229 vstart = endp;
230
231 /* Try to match the characters between *OPTIONP and VSTART against
232 one of the TOKENS. */
233 for (cnt = 0; tokens[cnt] != NULL; ++cnt)
234 if (strncmp (*optionp, tokens[cnt], vstart - *optionp) == 0
235 && tokens[cnt][vstart - *optionp] == '\0')
236 {
237 /* We found the current option in TOKENS. */
238 *valuep = vstart != endp ? vstart + 1 : NULL;
239
240 if (*endp != '\0')
241 *endp++ = '\0';
242 *optionp = endp;
243
244 return cnt;
245 }
246
247 /* The current suboption does not match any option. */
248 *valuep = *optionp;
249
250 if (*endp != '\0')
251 *endp++ = '\0';
252 *optionp = endp;
253
254 return -1;
255 }
256
257 #endif
258
259 #endif
260