• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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